異常な入力が行われた時の処理
出典: フリー百科事典『ウィキペディア(Wikipedia)』 (2021/11/23 00:15 UTC 版)
「scanf」の記事における「異常な入力が行われた時の処理」の解説
scanf関数は、予期せぬ値が入力されると、その値を読み込まず、ストリーム上に残してしまう。例えば int i;scanf("%d", &i); としたコードがあった場合、入力が数字でなかった場合は scanf はストリームにその文字列を残したまま終了することになる。このため次に scanf が呼ばれたときはそのストリーム上のバッファが実引数に代入され、他の scanf にも異常な結果を返すことになる。例として 1 が入力されたら終了、それ以外はもう一度入力を求めるようなプログラムを考えてみる、もしこのプログラムを int i;while(1) { scanf("%d", &i); if (i == 1) { break; }} というようなコードで記述した場合、数字以外の文字を入力してしまうと無限ループに陥ることになる。このような現象を防ぐ手段として scanf の戻り値を利用する方法がとられる。これは scanf は代入に成功した変数の数を戻り値として返すため、指定した実引数の数と scanf の戻り値が一致しないときに入力バッファをクリアすることで回避できる。例えば上記の例の場合は以下のようになる。 int i;while(1) { if (scanf("%d", &i) != 1) { scanf("%*s"); if (feof(stdin)) { /* エラー処理 */ } continue; } if (i == 1) { break; }} 入力バッファのクリアはここでは文字列を空読みすることで実現している(入力バッファのクリア方法は状況によって異なる方法が考えられる)。なお主にウェブ上などで、標準入力のバッファクリアの方法に fflush(stdin) や rewind(stdin) とする方法が紹介されることがあるが、ANSI規格ではこれらの動作は未定義であり、正しい動作を保障するものではない。 この方法でエラー処理をする場合には上記の空白文字の取り扱いの関連で問題になることがある。例えば int i, j;scanf("%d %d", &i, &j); のようなコードで、異常な入力があった場合エラー処理をしたいとする。これを int i, j;if (scanf("%d %d", &i, &j) != 2) { エラー処理} という方法で実現すると入力が "1" のみの場合、空白と改行は同一視されてしまうため、変数 "i" に 1 を入力して後、変数 "j"の入力待ち状態となる。もし、このような場合にもエラー処理を実行したい場合には、例えば以下のように一度文字列として読み込んで、その後 sscanf で読み込むことで実装すればよい。 char a[20];int i, j;scanf("%19[^\n]%*[^\n]", a);getchar();if (sscanf(a, "%d %d", &i, &j) != 2) { エラー処理}
※この「異常な入力が行われた時の処理」の解説は、「scanf」の解説の一部です。
「異常な入力が行われた時の処理」を含む「scanf」の記事については、「scanf」の概要を参照ください。
- 異常な入力が行われた時の処理のページへのリンク