c - 输入一个字符作为整型变量的输入,给出无限循环

标签 c

#include<stdio.h>
#include<ctype.h>
int main()
{
    int number, sum = 0;

    // loop body is executed at least once
    do
    {
        printf("Enter a number: ");
        scanf("%d", &number);
        sum += number;
    }
    while(number != 0);

    printf("Sum = %d",sum);

}

这段代码应该打印用户输入的所有整数的总和。但是,当用户输入一个字母作为输入时,它不会抛出错误,而是进入无限循环,打印“输入数字”语句,但不运行循环中的任何其他语句。

谁能告诉我为什么会发生这种情况?

最佳答案

scanf 很奇怪。它有一个内部缓冲区,并且仅当该缓冲区为空时才会从流中读取。在代码的开头,没有任何内容,因此从标准输入读取一行。然后 scanf 尝试在那里找到一个整数。如果找到整数,它将报告已成功读取一项(通过返回1)并将读取的值放入提供的指针位置。但是,如果未找到整数,它将返回“0”,表示“成功读取零项”,并且它不会消耗缓冲区中的任何内容。这意味着,下次调用 scanf 时,缓冲区不会为空,因此不会再次提示用户输入新行,并且 scanf 将再次尝试读取与上次尝试完全相同的位置的整数(并且会因完全相同的原因而失败)。因此,无限循环。

为了说明这个“缓冲区”的事情,试试这个:

scanf("%d", &a);
scanf("%d", &b);
printf("a: %d, b: %d\n", a, b);

并在一行中输入 12 53,作为第一个 scanf 的输入。神奇的是,a 最终为 12b 最终为 53。对这个魔法的解释是 - 第一个 scanf 发现缓冲区为空,从用户那里读取该行,并找到一个整数,正如它被告知的那样;第二个 scanf 发现缓冲区中仍有一些内容,并继续从上次停止的地方读取,而无需要求用户换行。

正如其他人已经评论的那样,通常最好自己读取一行(fgets)并自己解析它(strtol),或者如果您绝对需要使用 scanf,请确保通过检查其返回码来检查 scanf 是否读取了您期望的内容。请参阅here关于如何在 scanf 失败时清除输入缓冲区。

关于c - 输入一个字符作为整型变量的输入,给出无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51718925/

相关文章:

检查输入和标准错误

c++ - execv() 关于参数的怪癖

c - 返回指向局部变量的指针

c - 在 C 中使用硬件定时器

c - c 中的 fprintf() 是将输出逐一打印还是批量打印到文件中?

c - 如何在 C 中正确创建二维 int 数组的数组?

c - 如何使用 LLVM-C 对浮点恒等函数进行 JIT 编译

c - 如何在Flex(词法分析器)中定义数字格式?

c - 将匹配的字符存储在flex中

C输出问题