用意している配列より、多い文字を入力されたとき。

[戻る]
リファール 2004/10/07(木) 08:17:40
おはようございます。
WindowsXP, VC++.net, C言語です。
文字列を入力されたときの対処法で悩んでいます。


#include <stdio.h>

int main(){
    char str[10];

    gets(str);

    /*
    if(str[9]!='\0'){
        str[9]='\0';
    }
    */

    puts(str);

    return 0;
}

10文字以上入力してしまうと 「Debug Error!」 となってしまいます。
コメントアウトにしてあるところを、戻してみたりしているのですが(なんとなく^
^;)
その警告が出たとき「中止」を選べば
最後まで実行してくれるみたいなのですが
警告されるということは、良くないということなんじゃないかな、と思ってしまっ
て・・・。

ユーザーが10文字以上入力した場合
どのように対処したらいいのか、お教え下さいませんか?
よろしくお願いします。

euro2004 2004/10/07(木) 09:16:30
gets()をヘルプで調べると
「セキュリティに関するメモ   gets では、読み取る文字数を制限する方法がないため、
信頼されない入力ではバッファ オーバーランが発生しやすくなります。代わりに、
fgets を使用してください。」
と書いてあります。

fgets()を使いましょう。

PATIO 2004/10/07(木) 11:32:39
そもそも用意したバッファをオーバーするようなデータの設定は、絶対に駄目です。
これはどんな状況でも許される事はありません。
ですから、こういう状況が起こらないようにプログラムを作成する必要があります。
方法はいくつかありますが、この辺は勉強もかねて御自分で考えてみてください。
既に一つの方法が示されています。

方法論はともかく、確保した領域を超えるデータの設定や参照は絶対に行っては
いけないという事を覚えて置いてください。

επιστημη [E-Mail] [HomePage] 2004/10/07(木) 14:27:17
> ユーザーが10文字以上入力した場合
> どのように対処したらいいのか、お教え下さいませんか?

入力できなくする もしくは やってもへっちゃらに作る のいずれかです。

やられちゃ困るのにできてしまう のがイケナイのですから。

リファール 2004/10/07(木) 17:25:38
[[解決]]
御三方、ご教授ありがとうございます。

fgets(str, sizeof(str), stdin);

としたら出来ました!
「読み取る文字数を制限する方法がないため・・・・・」とは
第二引数のことを言っているのですね。

僕は「バッファ」というものが、なんとなくしか分からないのですが
「ストリーム入出力」のヘルプに
「既定では、ストリーム バッファのサイズは 4 K です。」とありますね。

こんな入力をする人はいないと思いますが
24時間キーボードを押しっぱなしにしてしまうと
4Kオーバーでアウトになってしまうんでしょうか・・・。

そうだとしたら、僕にはどうしたらそうなるのか、分かりませんが
επιστημηさんが言われた
「入力できなくする」プログラムが一番いいということですね。

なんだか 文字列操作や、ファイルのとき「バッファ」という言葉が
よく出てくるので、ちゃんと勉強したいです。

ありがとうございました。

REE 2004/10/07(木) 18:45:39
ここで皆さんの言っているバッファは、
char str[10];
これのことです。

PATIO 2004/10/08(金) 10:01:24
バッファと言うのは一般的な表現なので標準関数が内部で構えている
データを一時保存しておく場所もバッファですし、あなたがgetsから
情報を受け取るために作ったchar str[10];もバッファになります。
もっと言うならバッファというより変数全てに言える事ですけれど、
変数は宣言されるとそれぞれデータ型や配列の長さに合わせたサイズで
確保されます。変数に対して参照したり、データを設定したりする行為は
この確保された範囲内で行わなくてはなりません。
標準関数内のバッファに関しては標準関数の方で管理しているので
外部で心配する必要は無いと思います。バッファをオーバーしそうだと
関数が判断すれば、オーバーしないように内部で調整します。
気をつけないといけないのは、プログラマーが作成した変数を
標準関数に引き渡す時にその変数を超えて参照したり、設定したりしない
ように注意する必要があるという事です。
今回のgetsの件はまさにそれになります。
また、str[10]というように配列の範囲を超えた部分を直接参照したり、
そこにデータを設定する事はしないようにする必要があります。
こういう事をするとプログラムが予想外の動作をして、最悪は不正アクセスで
強制終了する羽目になります。

リファール 2004/10/09(土) 07:57:40
むむむ、なるほど。
僕は入門書を理解した(つもり)程度のC言語の知識なのですが
char str[10];  と宣言したら  str[13]='a'; 
というようなことは、やってはいけないと分かってました。

でも  gets(str);  で同じようなことをやってたんですね(恥)
子供っぽい例えで、お恥ずかしいですが
自分で直接  str[13]='a';  としなくても
gets( )にそれをやらせていたんですね。
fgets(str, sizeof(str), stdin); とすることで
fgets( )に「10バイトを超えて値を設定するな。」と言ったというか・・・。

す〜〜〜っごい勉強になりました!!!
みなさん、ご親切にありがとうございます。
プログラム、面白いですね^−^

古いスレッドには追加発言できません。