きちんとしたプログラムでは,
Cのライブラリ関数scanf()を使うべきではない.
このページではそれを説明する.
scanf()は,不適当な入力が与えられた場合,
それを判断して処理を終了するが,
不適当な入力を除去することはしない.
したがって,何度やり直しても,事態は改善されず,
例えば,下手なプログラムでは,無限ループに陥ったりする.
"%d"で整数値を読み取ろうとしているところで,
「123a...」と入力したとする.
+-----+-----+-----+-----+--...
| '1' | '2' | '3' | 'a' |
+-----+-----+-----+-----+--...
↑
ここから始まったとする.
↓ '1'を読み取って1つ前へ
+-----+-----+-----+-----+--...
| '1' | '2' | '3' | 'a' |
+-----+-----+-----+-----+--...
↑
↓ '2'を読み取って1つ前へ
+-----+-----+-----+-----+--...
| '1' | '2' | '3' | 'a' |
+-----+-----+-----+-----+--...
↑
↓ '3'を読み取って1つ前へ
+-----+-----+-----+-----+--...
| '1' | '2' | '3' | 'a' |
+-----+-----+-----+-----+--...
↑
↓ 'a'を読み取って1つ前へ
+-----+-----+-----+-----+--... 読み込み終了. 変換した数値: 123
| '1' | '2' | '3' | 'a' | 戻り値: 1
+-----+-----+-----+-----+--...
↑
↓ 使わなかった'a'を読み戻す
+-----+-----+-----+-----+--...
| '1' | '2' | '3' | 'a' |
+-----+-----+-----+-----+--...
↑
次に読み込むときはここから
"%d"で整数値を読み取ろうとしているところで,
「abcd...」と入力したとする.
+-----+-----+-----+-----+--...
| 'a' | 'b' | 'c' | 'd' |
+-----+-----+-----+-----+--...
↑
ここから始まったとする.
↓ 'a'を読み取って1つ前へ
+-----+-----+-----+-----+--... 読み込み終了.変換エラー.
| 'a' | 'b' | 'c' | 'd' | 戻り値: 0
+-----+-----+-----+-----+--...
↑
↓ 使わなかった'a'を読み戻す
+-----+-----+-----+-----+--...
| 'a' | 'b' | 'c' | 'd' |
+-----+-----+-----+-----+--...
↑
次に読み込むときはここから
再度scanf("%d", ...)が呼ばれても,同じことの繰返しになってしまう.
scanf()は,1文字単位で入力を操作しているので,
不適当な入力を除去することには無理がある.
そこで,fgets(),
もしくは,getline.cで使われている
getline 関数を用いて1行分をまとめて文字列に入力し,
その後,sscanf()を使って,その文字列の中から数値を読み取るのがいい.
もし,不適当な入力が検出された場合は,入力された行を全部棄てて,
新たな行の入力を求めるようにする.