为什么 scanf 在失败一次后不等待用户输入?

3
我在下面的代码中遇到了问题。当我输入任何整数,例如 (0-9),那么它就可以正常运行。但是当我输入其他字符,例如 AB 或任何其他字母时,scanf() 就失败了。它不会继续等待输入。

我附上了一个代码片段。我需要使用 C 标准库来进行错误处理。

#include <stdio.h>

int main()
{
    int choice;
    while(1)
    {
        printf("Enter your choice: ");
        if(0 == scanf("%d", &choice))
          {
              printf("Some error occured\n");
              //break;/*I did not want to break this loop as I use this to show menu*/
          }

        switch(choice)
         {
                      case 0:printf("Case 0\n");break;
                      case 1:printf("Case 1\n");break;
                      case 2:printf("Case 2\n");break;
                      case 3:printf("Case 3\n");break;
                      case 4:printf("Case 4\n");break;
                      case 5:printf("Case 5\n");break;
                      case 6:printf("Case 6\n");break;
                      case 7:printf("Case 7\n");break;
                      case 8:printf("Case 8\n");break;
                      case 9:printf("Case 9\n");break;
                      default:printf("Default case\n");break;

         }
    }
}

更清楚的问题是:为什么它在失败后不等待?
2个回答

4
使用scanf函数时,如果输入与格式规范不匹配,则输入不会被消耗并保留在输入缓冲区中。换句话说,不匹配的字符永远不会被读取。
因此,当您键入例如a字符时,您的代码将无限循环,因为scanf继续在同一字符上失败。
scanf返回错误时,您需要摆脱有问题的字符。
您无法知道将键入多少个字符,但消耗任何有问题的字符的一个简单方法是在scanf失败时尝试读取字符串:
char junkChars[256];

printf("Enter your choice: ");
if (scanf("%d", &choice) == 0)
{
    printf("Some error occured\n");
    scanf("%s", junkChars);
}

这将清除输入缓冲区,但是需要一个上限。如果用户键入的字符数超过256个,scanf 将在下一次迭代中继续消耗它们。

显然,这是一个丑陋的解决方案,但是由于这个原因,scanf 并不是一个很好的输入机制。最好使用 fgets 将输入行作为字符串获取,然后自己控制该字符串的解析。


这个程序运行良好,但是C库是否提供一些清除输入缓冲区的功能?就像他们为输出缓冲区提供fflush()函数一样。 - rajesh6115
没有标准的清空输入缓冲区的方法(尽管有些实现可能会提供它)。只需读取输入,例如使用fgets()。这只是一个函数调用,就像fflush()一样。 - nos
1
“int c; do c = getchar(); while (c != EOF && c != '\n');" 是我读取和丢弃输入的首选方式;它具有不需要一个临时缓冲区(只需要一个 int)并且能够处理任意长度的垃圾输入的优点。 - zwol

1

这是有意为之。

不要使用 break,请使用 continue


我想知道为什么不等待我的输入,以及如何管理错误,以便我可以再次输入。 - rajesh6115
为什么需要等待?当您按Enter键时,即表示要读取字符串。如果出现错误,您需要决定是要重试还是中止程序。 - Steve Wellens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接