ここにはいくつかの問題があります。
1 つ目は、scanf() の戻り値がチェックされていないことです。入力が利用可能な場合、scanf は割り当てられた変数の数を返します。この場合は 0 または 1 になります (変数を 1 つだけ割り当てようとしているため)。ユーザーが数字以外の文字を入力すると、使用可能な入力があるため、ユーザー入力を待たずにループが繰り返し実行されますが、「%d」変換と一致することはありません。scanf() を使用する場合は、戻り値を確認する必要があります。戻り値がゼロの場合は、数値以外の値が入力されています。つまり、行の終わりまで読み取って、入力バッファーからその値をクリアする必要があります。戻り値が EOF と等しい場合は、I/O エラーが発生したか、ストリームの終わりに達したかのいずれかです。
ルーチン isdigit() は整数の引数を取りますが、その整数値が文字を表すことを期待しています。入力を整数に変換するために scanf() を使用しているため、 a に格納されている値はもはや文字を表していません。これは実際の数値を表します。このため、 isdigit() の呼び出しは、ユーザーが数字に対応する数字を入力した場合にのみ true 値を返します。私のロケールでは、これは、ユーザーが 48 から 57 までの数字を入力した場合にのみ検証が成功することを意味します。scanf() を使用している場合、ユーザーが数値を入力した場合にのみ scanf() が値 1 を返すため、isdigit() チェックは必要ありません。
しかし、正直なところ、ユーザーが何か間違ったことを入力した場合に入力バッファーをフラッシュする必要があるため、正確に回避できるのであれば、scanf() を使用してユーザー入力を読み取ることはしません。あなたの要件が何であるかは完全にはわかりませんが、コマンドラインから正の整数を読み取る必要があり、桁数は問題ではないと仮定します。
この場合、おそらく fgets() を使用してユーザー入力を読み取り、次に strtol() を使用して値を符号付き長整数に変換し、同時に検証を実行する必要があります。
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <ctype.h>
#include <string.h>
int main () {
long result;
long len;
int is_valid = 0;
char buf[128];
char *arg;
char *end;
while (!is_valid) {
/* Prompt the user for the integer. */
printf("Enter a non-negative integer: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) {
printf("Giving up so soon?\n");
break;
}
/* Verify that the input doesn't exceed our buffer length. */
len = strlen(buf);
if (buf[len] != '\n') {
printf("Input buffer length exceeded - aborting.\n");
exit(1);
}
/* Skip any leading whitespace. */
for (arg = buf; isspace(*arg); arg++);
/* Attempt to convert the argument. */
errno = 0;
result = strtol(arg, &end, 10);
if (errno == EINVAL) {
printf("Please enter a numeric value.\n");
continue;
}
if (errno == ERANGE) {
printf("Numeric value out of range.\n");
continue;
}
/* Check for non-whitespace characters after the end of the integer. */
for (; isspace(*end); end++);
if (*end != '\0') {
printf("Please enter a numeric value.\n");
continue;
}
/* Verify that the number is non-negative. */
if (result < 0) {
printf("Please enter a positive value.\n");
continue;
}
/* The number is valid. */
printf("Excellent!\n");
is_valid = 1;
}
return 0;
}
これは完璧ではありません。入力バッファの長さを超えた場合の中止は、ユーザーフレンドリーではありません。ただし、検証の問題は処理する必要があります。