c - 为什么 scanf() 会导致此代码中的无限循环?

标签 c gcc scanf

我有一个小型 C 程序,它只从标准输入读取数字,每个循环周期读取一个数字。如果用户输入一些 NaN,则应将错误打印到控制台,并且输入提示应再次返回。输入“0”时,循环应结束,并且给定正/负值的数量应打印到控制台。程序如下:

#include <stdio.h>

int main()
{
    int number, p = 0, n = 0;

    while (1) {
        printf("-> ");
        if (scanf("%d", &number) == 0) {
            printf("Err...\n");
            continue;
        }
        
        if (number > 0) p++;
        else if (number < 0) n++;
        else break; /* 0 given */
    }

    printf("Read %d positive and %d negative numbers\n", p, n);
    return 0;
}

我的问题是,在输入一些非数字(如“a”)时,这会导致无限循环一遍又一遍地写入“-> Err ...”。我猜这是一个 scanf() 问题,我知道这个函数可以用更安全的函数代替,但这个例子是针对初学者的,只了解 printf/scanf、if-else 和循环。

我已经阅读了问题scanf() skips every other while loop in C的答案并浏览了其他问题,但没有真正回答这个具体问题。

最佳答案

scanf 仅消耗与格式字符串匹配的输入,返回消耗的字符数。任何与格式字符串不匹配的字符都会导致其停止扫描并将无效字符保留在缓冲区中。正如其他人所说,在继续之前,您仍然需要将无效字符从缓冲区中清除。这是一个相当肮脏的修复,但它会从输出中删除有问题的字符。

char c = '0';
if (scanf("%d", &number) == 0) {
  printf("Err. . .\n");
  do {
    c = getchar();
  }
  while (!isdigit(c));
  ungetc(c, stdin);
  //consume non-numeric chars from buffer
}

编辑:修复了代码以一次性删除所有非数字字符。不会再为每个非数字字符打印出多个“Errs”。

Here是对 scanf 的很好的概述。

关于c - 为什么 scanf() 会导致此代码中的无限循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54296442/

相关文章:

c - 初始化指向结构体的指针的元素

c - 我应该为成功的函数返回 0 还是 1?

c - 在没有虚拟节点的链表前面插入

c - GCC 提示缺少对同一文件中函数的引用

c - gcc: __fread_chk_warn 警告

c++ - snprintf 变量列表不会将枚举转换为 char*

c - 我真的需要 libgcc 吗?

c - 如何使用 scanf 保持程序运行

c - 使用 sscanf 验证十六进制格式的命令字符串

c - 我如何读取 C 中的文本文件并将其打印到屏幕上?