忽略 while 循环中的 scanf 值

Ignoring scanf value in while loop

我正在学习 C,但在这个循环中遇到了问题 运行。我写了一个 while 循环来提示用户输入包裹及其数量。我尝试验证数量的输入以检查它是否为整数(当用户键入一个字符时,它会提示用户再次键入)

对于第一个 运行,一切都很好。

但是当第二次循环运行s等等时,我尝试输入一个字符作为包裹的数量,不会弹出消息告诉用户再次输入.

忽略 scanf 的值,tempQtty 的值等于用户之前输入的数量。

有什么方法可以解决这个问题,或者有其他方法可以验证用户输入是整数吗?

抱歉我的英语不好:")[输入,预期输入和实际输入][1]

while(skip != 'x')
        {
            printf("\n\n%27sPACKAGE A/B/C/D  ( x = skip ) : ", "");
            rewind(stdin);
            package = getchar();

            switch (package)
            {
            case'x':case'X': skip = tolower(package); break;
            case'A':case'a':case'B':case'b': case'C':case'c':case'D':case'd':
                printf("%27sQUANTITY%21s: ", "", "");
                rewind(stdin);
                scanf("%d", &tempQtty);   //here's the problem

                while (tempQtty < 0)
                {
                    printf("%27s(PLEASE KEY IN A CORRECT VALUE!)\n", "");
                    printf("%27sQUANTITY%21s: ", "", "");
                    rewind(stdin);
                    scanf("%d", &tempQtty);
                }
                switch (package)
                {
                case 'A':case 'a': qttyA = tempQtty; totalQttyA += tempQtty; break;
                case 'B':case 'b': qttyB = tempQtty; totalQttyB += tempQtty; break;
                case 'C':case 'c': qttyC = tempQtty; totalQttyC += tempQtty; break;
                case 'D':case 'd': qttyD = tempQtty; totalQttyD += tempQtty; break;
                    
                }
                break;
                default:
                    printf("%27s(NO SUCH PACKAGE! PLEASE KEY IN AGAIN!)\n", "");
            }
        }
printf("\nA = %d", qttyA);
printf("\nB = %d", qttyB);


  [1]: https://i.stack.imgur.com/hBD82.png

I try to key in a character for the quantity of the package, the message won't pop up to tell the user to key in again.

The value of the scanf is ignored and the value of tempQtty is equal to the previous quantity that the user keyed in.

Is there any way to fix this, or is there another way to validate the user input is integer?

如果您输入 z,您认为 tempQtty 会收到负值的假设是没有根据的。事实上,C 标准规定如果转换失败 tempQtty 不受影响。 解决这个的方法是而不是忽略scanf return值,它告诉输入是否有效。

首先,正如我在评论中提到的,这是一个异常复杂的问题,面对它的并不只有你一个人。这不是你的问题,也不是C语言的问题;这基本上只是 scanf 函数本身的问题。

部分答案:

(1) 随处可见

scanf("%d", &tempQtty);
while (tempQtty < 0)
    ...

这是错误的。如果您使用 %d 请求整数输入,并且如果用户键入非数字内容,则 scanf 所做的 而不是 所做的是填写 tempQtty作为-1。它所做的是return一个值,表示它无法转换您(程序员)所要求的内容。所以你想把它改成更像

的东西
while (scanf("%d", &tempQtty) != 1)
    ...

(2) 如果用户没有键入您要求的整数,而如果 scanf returns 0 告诉您,则存在问题:用户键入的非数字输入可能仍然坐在输入流上。看起来您可能已经意识到这一点,并且您正在尝试通过调用 rewind(stdin) 来删除未读输入。但那是行不通的;那不是做事的方式。

你想要做的是写一个像这样的小“帮助”函数:

void flush_unread_input()
{
    int c;
    do {
        c = getchar();
    } while(c != EOF && c != '\n');
}

然后,只要检测到错误(即 scanf return 编辑了 1 以外的其他内容),而不是调用 rewind(stdin),只需调用 flush_unread_input().

再补充几点:

  • 您可能需要试验在何处调用 flush_unread_input 以及在何处不调用。你不能盲目地将它到处洒,因为它基本上读取并丢弃该行的其余部分,但这意味着它也可以读取并丢弃整行,有时这可能是你真正想要的行。
  • 编写flush_unread_input函数的方法有很多种。我已经展示了一种应该很容易理解的方式,但您经常会看到更紧凑的方式,例如 while((c = getchar()) != EOF && c != '\n');。 (我还没有测试我在这里展示的版本。)
  • 我的回答可能表明 scanf return 如果成功则为 1,如果失败则为 0,但它比这更复杂。 scanf 实际上是 return 成功转换和存储的项目数,如果您的格式说明符中包含多个 % 符号,则可能会超过 1。

关于这个话题还有很多话要说,但今天早上我没有时间写更长的答案。