scanfの異常値入力の対策(C学習中)
scanfは予期しない入力があると無限ループに陥る(C学習中)のつづき。
今日ほげったこと
scanfの戻り値を使って入力の正誤判定をし、空読みで無限ループを回避する
int hoge; int ans = 7; while(1){ // 異常値対策 if(scanf("%d", &hoge) != 1){ printf("数字入れてクダサイ。\n"); scanf("%*s"); continue; } // 以下、本来の処理 }
scanf は、変換に成功した数を返す。この場合、1なら正しいので、異常値入力の検出に使用する。1以外の場合、ifブロックの中で文字の空読みをして、バッファに残った文字をクリアする。
scanf("%*s")というのが、空読みしている箇所。%は変換の先頭、*はフラグ。manによると、*は「割当の抑制」で、変換結果は廃棄される。
読み込みたい数字が2つの場合
次のように書く。しかし、問題がある。
int hoge; int moga; int ans = 7; while(1){ if(scanf("%d %d", &hoge, &moga) != 2){ printf("数字2つ入れてクダサイ。\n"); scanf("%*s"); continue; } // 以下、本来の処理 }
入力が「a」の場合は、ifブロックが1回実行される。しかし、入力が「a b」の場合は、aに対してifブロックが実行された後、何かが入力ストリームに取り残され、次のwhileループの際に読み込まれる(空白、b、改行文字のどれが取り残されるのかが、よくわかってません)。
結果として、次のようにifブロックが2回実行される。
a 数字2つ入れてクダサイ。 // これはOK a b 数字2つ入れてクダサイ。 数字2つ入れてクダサイ。 // ストリームから残りを読み込んでいる
わからないこと
- 空読みという言葉の意味
- 「バッファにnullを指す値を読み込んで、元あった値を追い出す」ということ?
宿題
- scanfを使ったときに起こしやすい問題とその対策を、対応づけて理解する
- いま、複数の問題がごっちゃになってる。%sで空白は読み込めないとか、異常値入力に弱いとか、改行文字がバッファに残るとか。