そもそも 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() でチェックする程度でよいと思います。