そもそも scanf というのは、お節介と言ってもいいくらい、複雑な処理を することが出来る関数なんです。そういう奴が間違った入力を受けとると、ず いぶんと間抜けなことをしてくれます。 scanf() は正常に読みとれた値の個 数を返しますから、それをチェックすればいいと考える人もいるでしょうが、 実は駄目です。
/* とりあえず正しいつもりのプログラム */ #include <stdio.h> int main() { double a; while (1) { if (scanf("%lf", &a) == 0) { fprintf(stderr, " scanf() で 0 個しか正常に読み込めませんでした。\n"); } else { printf("%f\n", a); exit(0); } } return 0; } |
oyabun% test-scanf 1.2 1.200000 oyabun% test-scanf 0.000000 oyabun% scanf 1,2 1.000000 oyabun% scanf ,2 scanf() で 0 個しか正常に読み込めませんでした。 scanf() で 0 個しか正常に読み込めませんでした。 scanf() で 0 個しか正常に読み込めませんでした。 略 scanf() で 0 個しか正常に読み込めませんでした。 scanf() で 0 個しか正常に読み込めませんでした。 ^C scanf() で 0 個しか正常に読み込めませんでした。 oyabun% |
では正しい入力はというと、
#include <stdio.h> #include <stdlib.h> /* atof() のため */ #include <floatingpoint.h> /* strtod() */ int main() { double a; char input[100]; if (fgets(input, sizeof(input), stdin) == NULL) { fprintf(stderr, "input error?\n"); exit(1); } /* atof() の利用 */ a = atof(input); printf("%f\n", a); /* sscanf() の利用 */ if (sscanf(input, "%lf", &a) == 0) { fprintf(stderr, " sscanf() で 0 個しか正常に読み込めませんでした。\n"); } else printf("%f\n", a); /* strtod() の利用 */ { char *p; a = strtod(input, &p); if (input == p) { fprintf(stderr, " strtod() が読み込みに失敗しました\n"); exit(1); } printf("%f\n", a); } return 0; } |
どうですか?めんどい、やってらんない、と思う人が多いと想像します。筆 者は、普通の数値計算実行者が作る、いわゆるシステム・プログラムでないプ ログラムでは、それほど神経質になる必要はなく、「あ、入力を間違えた!し かたないから、最初からやりなおそう」でいいと思います。ただし、長い計算 の後にユーザーのキーボードからの指示を読んで態度を決めるようなプログラ ムでは、それまでの計算結果を無駄にしないように、それなりの注意がいるで しょう。その場合も sscanf() でチェックする程度でよいと思います。