きちんとしたプログラムでは,
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()
を使って,その文字列の中から数値を読み取るのがいい.
もし,不適当な入力が検出された場合は,入力された行を全部棄てて,
新たな行の入力を求めるようにする.