5

当我想检查我输入的是数字时,我遇到了这个问题。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' 读入数组而gets没有。所以要小心。

4

5 回答 5

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. */
}
于 2012-06-21T13:21:34.057 回答
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根据需要使用和转换。

于 2012-06-21T14:29:02.443 回答
1

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

于 2012-06-21T13:24:21.733 回答
0

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

于 2012-06-21T13:57:55.633 回答
-1

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

于 2012-06-24T08:26:50.763 回答