みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

ループ中でのscanfおよびcin

あまりに基礎的な質問ですが,ループ中の入力関数が期待する動作になりません.
コードを載せます
while (1) {
int key;
scanf("%d", &key);
if (key == 1) break;
}
期待する動作は1が入力されるまでループし続けるというものですが
scanfは一度しか実行されずループし続けます,cinに変えても同様でした
何が原因か分かる方,ご教示ください

投稿日時 - 2009-07-16 18:19:13

QNo.5130686

困ってます

このQ&Aは役に立ちましたか?

1人が「このQ&Aが役に立った」と投票しています

回答(4)

ANo.4

http://www9.plala.or.jp/sgwr-t/c/sec05.html
の「5-4.scanf()の注意事項」を読みましょう。

>scanfは一度しか実行されずループし続けます

いいえ。scanfは実行されています。

「2度目以降のscanfを呼んだ時、入力バッファに変な物(%dとして受け付けない物)があると、scanfは入力バッファをそのままにして、何もしないで戻ってくる」ので「まるでscanfが実行されていないように見える」だけです。

scanfは「変換できた個数を返す」と言う仕様になっているので
while (1) {
int key;
if (feof(stdin)) break; //EOFの時は終了
if (scanf("%d", &key) != 1) { //予期しない入力なら
scanf("%*[^\n]%*c"); //改行も含めて読み飛ばす
} else { //変換できたなら
if (key == 1) break; //1なら終了
}
}
など、scanfの戻り値を確認すると良いでしょう。

よく「scanfは、初心者が絶対に使ってはいけない関数」などと暴言を吐く人が居ますが、そんな事はありません。

・scanfの戻り値をちゃんと確認すれば予期せぬ入力の判定は可能
・予期せぬ入力を読み飛ばす方法があるので、ちゃんと読み飛ばす

の2つをしっかり行えば、初心者でもちゃんと使える関数です。と言うか、変換の便利さ、書式の豊富さから言えば「超初心者向けの関数」です。

「scanfを使わずに、色々とゴチャゴチャ小細工する」って方が、よっぽど「上級者にしか出来ない高等テクニック」です。

投稿日時 - 2009-07-17 12:15:45

ANo.3

scanfは、初心者が絶対に使ってはいけない関数です。(中上級者も使い道無いですけど)
(1) fgetsとsscanfを組み合わせて使う
(2) sscanfの戻り値を確認する

char line[1000];
while(1){
int key;
if(!fgets(line,sizeof line,stdin)) break;
if(sscanf(line,"%d",&key)==1 && key==1) break;
}


もし、例題にscanf関数が出てくる入門書をお使いなら、別の本を探しましょう。

投稿日時 - 2009-07-16 20:25:09

ANo.2

このやり方だと、scanfは整数値として解釈できる入力がないと、何度でも再試行してしまいます。
期待した入力が得られなかった場合、行末まで読み飛ばす処理を入れるべきです。

なお、stdinのような入力ストリームに対してfflushを呼び出すと未定義の動作になりますので、やってはいけません。

参考URL:http://www.kijineko.co.jp/tech/superstitions/fflush-with-input-stream.html

投稿日時 - 2009-07-16 19:35:59

ANo.1

次の1行をscanfの次の行に追加したらいけるんじゃ?

fflush(stdin);

標準入力(stdin)のバッファを吐き出せということです。
入力というのはすぐにプログラムに渡されるわけではなく一定量が溜まってから渡されます。
これを一定量たまるまで待つのではなくすぐに渡せというのが上の意味です。

投稿日時 - 2009-07-16 19:23:53

あなたにオススメの質問