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で空白は読み込めないとか、異常値入力に弱いとか、改行文字がバッファに残るとか。