バッファのクリア

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
klang

バッファのクリア

#1

投稿記事 by klang » 10年前

scanf関数を使うことがあまりよくないらしいのですが、なぜでしょうか?
また、scanfのエラーに対する処理としてバッファをクリアすることがあるようですが、
そもそもバッファってなんですか?自分で調べた程度ではバッファ=scanfで入力されたものであり、メモリに入れる前のもの
という解釈なのですが、いまいちわかりません・・・。

用意した文字数以上の文字数を入力された場合、数字のはずが文字を入力された場合に
その、バッファをクリアするわけですよね。勝手にはクリアされないということでしょうか。

勉強しているサイトでは↓のプログラムのようにすればいいということなんですが、
「scanf("%*[^\n]%*c");」の行う意味、なぜこれでクリアされるかがわかりません。

どうか、解説お願いします。

コード:

       int place = 0,y,x;
	while(1){
		if(scanf("%d",&place) == 0){
			//数値がとれなかったらバッファをクリアする
			scanf("%*[^\n]%*c");
			printf("input error\n");
			continue;
		}
     //略(つづきがあると思ってください)
    }

Poco
記事: 161
登録日時: 13年前

Re: バッファのクリア

#2

投稿記事 by Poco » 10年前

ここでいうバッファの解釈はそれでいいと思います。

たとえば、提示のプログラムを実行して、scanf()で"aaa"+リターンとか入力すると、scanf()はplaceに入力値aaaを格納できません。
#数値を求めているわけで。
この時読み込めなかったaaaは次のscanf()の読み込み対象となります。
なのでaaaを読み込み対象から外さない限り、scanf("%d",&place)は0を返し続けます。
aaaを読み込み対象から外すためにscanf("%*[^\n]%*c")を使用します。
最初の%*[^\n]で”改行コードまでの文字列”を読み飛ばします。scanf()での%*は読み飛ばしだと思ってください。
次の%*cで1文字読み飛ばします。最初の%*[^\n]で改行以外を全部読み飛ばしているので、次の%*cは改行そのものです。
これによって、aaaと改行を読み込んで(バッファから取り除いて)かつ、次のscanf("%d",&place)では入力を待つようになります。

#と、ここまで解説したのですが、scanf("%d",&place)ならscanf("%*[^\n]")でもバッファクリアできそうですね。
#scanf("%c%d",...)ならscanf("%*[^\n]%*c")としないとダメかな。


アバター
へろりくしょん
記事: 92
登録日時: 13年前
住所: 福岡

Re: バッファのクリア

#4

投稿記事 by へろりくしょん » 10年前

Poco さんが書きました: #と、ここまで解説したのですが、scanf("%d",&place)ならscanf("%*[^\n]")でもバッファクリアできそうですね。
クリアされません。 依然として入力バッファには改行コードが残ります。



scanf("%d", &hoge"); というコードが実行され、
"aaa+\n" という文字列が入力された時、

"aaa+\n" は数字では無いので読み込まれません。
入力バッファには、"aaa+\n" がそのまま残ります。

続く、scanf("%*[^\n]"); というコードが実行され、
改行コード以外の、"aaa+" が読み飛ばされます。
入力バッファには、"\n" が残ります。

原則として、入力バッファは頭から順番に読まれます。

klang

Re: バッファのクリア

#5

投稿記事 by klang » 10年前

[quote="Poco"]
aaaを読み込み対象から外すためにscanf("%*[^\n]%*c")を使用します。
最初の%*[^\n]で”改行コードまでの文字列”を読み飛ばします。scanf()での%*は読み飛ばしだと思ってください。
次の%*cで1文字読み飛ばします。最初の%*[^\n]で改行以外を全部読み飛ばしているので、次の%*cは改行そのものです。
これによって、aaaと改行を読み込んで(バッファから取り除いて)かつ、次のscanf("%d",&place)では入力を待つようになります。


1、%*[^\n]によって入力された文字列の改行まで飛ぶ
2、%*cによって改行
(3、continueで次のループへ飛ぶ)
(4、次のscanfを行う)
ということでしょうか?

コード:

      int place = 0,y,x;
    while(1){
        if(scanf("%d",&place) == 0){
            //数値がとれなかったらバッファをクリアする
            scanf("%*[^\n]%*c");
            printf("input error\n");
            continue;
        }
     //略(つづきがあると思ってください)
    }
]

Poco
記事: 161
登録日時: 13年前

Re: バッファのクリア

#6

投稿記事 by Poco » 10年前

そうです。
またこの場合、%*cを指定しなくても4のscanfで改行を読み飛ばします。
#へろりんごさんの指摘通り、バッファクリアが行われる訳ではなく、結果として問題なく動作するという意味で書きました。
#誤解させるようなことを書いてすみません。
#指摘ありがとうございます。>へろりんごさん

klang

Re: バッファのクリア

#7

投稿記事 by klang » 10年前

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

閉鎖

“C言語何でも質問掲示板” へ戻る