当您输入12ab到scanf(“%d”,& argu)之类的内容时会发生什么?

时间:2012-06-21 13:19:21

标签: c scanf

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

5 个答案:

答案 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")。这应该足以丢弃与缓存相关的任何内容。