当我想检查输入的数字时,我遇到了这个问题。如果我成功输入数字,scanf函数将返回1。所以这就是我写的:
int argu;
while(scanf("%d",&argu)!=1){
printf("Please input a number!\n");
}
但是当我输入像abcd这样的东西时,循环会永远存在而不会停止提示。
我在网上查了一下,发现它与缓存有关,我需要清理它,所以scanf可以获得新数据。所以我尝试了fflush,但它没有用。
然后我看到了这个:
int argu,j;
while(scanf("%d",&argu)!=1){
printf("Please input a number!\n");
while((j=getchar())!='\n' && j != '\n');
}
然后,当我输入'abcd'这样的东西时,它运作良好,并提示我输入。但是当我输入像“12ab”这样的东西时,它就不会再起作用了。
那么有没有办法可以检查scanf的输入(“%d”,& argu)实际上是一个数字,如果不是,则提示另一个输入?
修改:
我看到了答案并使用while(*eptr != '\n')
解决了我的问题。
请注意,fgets
函数实际上读取数组的'\ n',而fget
没有。所以要小心。
答案 0 :(得分:4)
最好使用fgets()
读取整行,然后检查它,而不是尝试从输入流中“动态”解析。
以这种方式忽略无效输入更容易。
使用fgets()
然后只需strtol()
转换为数字,就可以轻松查看数字后是否有跟踪数据。
例如:
char line[128];
while(fgets(line, sizeof line, stdin) != NULL)
{
char *eptr = NULL;
long v = strtol(line, &eptr, 10);
if(eptr == NULL || !isspace(*eptr))
{
printf("Invalid input: %s", line);
continue;
}
/* Put desired processing code here. */
}
答案 1 :(得分:2)
但是当我输入像abcd这样的东西时,循环会永远存在而不会停止提示。
那是因为如果scanf
遇到与转换说明符不匹配的字符,它会将其留在输入流中。基本上,正在发生的事情是scanf
从输入流中读取字符a
,确定它不是%d
转换说明符的有效匹配,然后将其推回到输入流。下一次循环它会做同样的事情。然后再次。然后再次。然后再次。
fflush
不是一个好的解决方案,因为它没有定义为适用于输入流。
对于输入"12ab"
,scanf
将读取并转换"12"
,并在输入流中保留"ab"
。
最佳解决方案是将所有输入作为文本读取,然后使用strtol
(对于整数值)和strtod
(对于实数值)转换为数字类型。例如:
char input[SIZE]; // assume SIZE is big enough for whatever input we get
int value;
if (fgets(input, sizeof input, stdin) != NULL)
{
char *chk;
int tmp = (int) strtol(input, &chk, 10);
if (isspace(*chk) || *chk == 0)
value = tmp;
else
printf("%s is not a valid integer string\n", input);
}
chk
指向输入流中不是十进制数字的第一个字符。如果此字符不是空格或0终止符,则输入字符串不是有效整数。这将检测并拒绝"12ab"
以及"abcd"
等输入。
scanf
是一个很好的解决方案,如果你知道你的输入总是正确形成并且表现良好。如果您的输入有可能表现良好,请使用fgets
并根据需要进行转换。
答案 2 :(得分:1)
我建议将输入作为字符串并检查其中的非数字字符。如果输入有效,则将字符串转换为sscanf(str,"%d",&i);
或者diplay错误。
答案 3 :(得分:1)
只需在循环中调用scanf(“%* [^ \ n] \ n”),它就会丢弃“缓存”。
答案 4 :(得分:0)
在循环内调用scanf("%*[^\n]\n")
。这应该足以丢弃与缓存相关的任何内容。