当你输入像12ab这样的东西到scanf(“%d”,&争论)时会发生什么?

当我想检查输入的数字时,我遇到了这个问题。 如果我成功输入数字,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没有。 所以要小心。

最好使用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. */ } 

但是当我输入像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并根据需要进行转换。

我建议将输入作为字符串并检查其中的非数字字符。 如果输入有效,则通过sscanf(str,"%d",&i);将字符串转换为int sscanf(str,"%d",&i); 或者diplay错误。

只需在循环内调用scanf(“%* [^ \ n] \ n”),它就会丢弃“缓存”。

在循环内调用scanf("%*[^\n]\n") 。 这应该足以丢弃与缓存相关的任何内容。