%c を使用した誤った入力
次のコード スニペットを検討してください。
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("%c", &y);
printf("%d %c", x, y);
}
動作:
上記のプログラムを実行すると、10 進数の入力を待機する最初の scanf が呼び出されます。12 を入力するとします (これは ASCII '1' と ASCII '2' です)。次に、「Enter」キーを押して、入力の終わりを知らせます。次に、プログラムは 2 番目の scanf を実行しますが、プログラムは文字の入力を待たずに、すぐに出力 12 に進み、その後に '\n' が続くことに注意してください。
説明:
なぜそれが起こるのですか?プログラムの動作を順を追って見てみましょう。最初はバッファには何もありません。最初の scanf() が呼び出されると、読み取るものがないため、待機します。1,2 を入力してから「Enter」を入力するまで待機し続けます。バッファにあるのは、文字 1、文字 2、および文字 '\n' です。'\n' は、すべてのフィールドが入力されると、入力の終了を意味しますが、ASCII 文字としてバッファにも格納されることに注意してください。この時点で、scanf はバッファーから最大の 10 進入力を読み取り、それを整数に変換します。この例では、文字列 "12" を見つけて 10 進値の 12 に変換し、x に入れます。次に、scanf は制御をメイン関数に戻し、値 1 を返します。1 つのエントリを正常に変換できるため。この例では、変数内の scanf の戻り値をキャッチしません。堅牢なコードの場合、scanf( ) の戻り値をチェックして、ユーザーが正しいデータを入力したことを確認することが重要です。
現在バッファに残っているのは '\n' です。次に、2 番目の scanf が呼び出され、文字が必要です。バッファーには既に '\n' 文字が含まれているため、scanf はそれを認識し、バッファーから取得して y に入れます。そのため、後で printf を実行すると、12 と「enter」が画面に出力されます。
解決策:
ストーリーの教訓は、enter は他の文字と同じであり、バッファーに入力され、他の ASCII 文字と同様に %c によってバッファーから消費されるということです。これを修正するには、代わりに次のコードを使用してみてください。
int main( ){
int x;
char y;
scanf("%d", &x);
scanf("\n%c", &y); /* note the \n !! */
printf("%d %c", x, y);
}
**
これはどのように問題を解決しますか?
** もう一度 '1','2','\n' と入力します。最初の scanf は "1" と "2" を読み取り、それを 10 進数の 12 に変換して、'\n' をバッファに残します。次の scanf は、次の入力の先頭に '\n' を期待するようになりました。バッファ内で '\n' を見つけて読み取り、破棄します。これでバッファは空になり、scanf はユーザーが文字を入力するのを待っています。ユーザーが「c」を入力した後、Enter キーを押したとします。'c' は "enter" ではなく y に割り当てられるようになりました。したがって、printf は "12 c" を画面に出力します。注: '\n' が再びキューに入っています。したがって、単一の文字に対して別の scanf を実行する必要がある場合は、ユーザーから別の文字を取得する前に、その '\n' を「消費」する必要があります。
これは、入力の前の空白をすべて無視するため、他の形式指定子の問題ではありません。