关于缓冲区残留问题

目录

问题

1. 问题根源:输入缓冲区残留

2. 解决方法:清空缓冲区残留

方式 1:用 getchar 吃掉换行符

方式 2:用循环批量清空(更彻底)

3. 完整修正

4. 总结


问题

我们先来看道题目

这道题其实并不难,但是如果我们使用下面这段代码就会出现一个问题

#include <stdio.h>
int main()
{
    int n, a[10] = { 0 }, m;
    char c;
    scanf("%d", &n);
    for (int i = 0; i < n; i++)
    {
        while ((c = getchar()) != '\n')
        {
            if (c >= '0' && c <= '9')
            {
                m = c - 48;
                a[m]++;
            }
        } 
    }

    for (int i = 0; i < 10; i++)
    {
        if (a[i] > 0)
            printf("%d:%d\n", i, a[i]);
    }
    return 0;
}

那就是明明我们让n=3,但是在接下来输入数据时只能输入两个,然后回车就输出结果了,但这并不是我们想要的结果,可是按逻辑而言上面代码没啥问题,说明这个bug可能比较隐蔽、比较底层

这是因为 scanf 读取完n后,输入缓冲区中会留下换行符(\n,ASCII 码值为 10 ),导致后续 getchar 直接读取到了这个残留的换行符。

以下详细分析并给出解决办法:

1. 问题根源:输入缓冲区残留

  • 当执行 scanf("%d", &n); 时,假设你输入 n 的值(比如 3)后按了 回车键,此时输入的内容是 3\n3 是给 n 的数据,\n 是回车键产生的换行符)。
  • scanf 只会读取 %d 匹配的整数部分(即 3),但 换行符 \n 会残留在输入缓冲区 中。
  • 进入 for 循环的第一次迭代后,执行 while ((c = getchar()) != '\n'),此时 getchar 会直接从缓冲区中读取到残留的 \n(ASCII 码对应 10 ),所以 c 一开始就被赋值为 10 。

2. 解决方法:清空缓冲区残留

在 scanf 读取 n 之后、for 循环之前,手动清空输入缓冲区,避免残留的 \n 干扰后续 getchar。常用两种方式:

方式 1:用 getchar 吃掉换行符

在 scanf("%d", &n); 后加一行:

​// 吃掉 scanf 残留的换行符
getchar(); 

​

这样会单独读取并丢弃缓冲区中残留的 \n,后续 getchar 就能正常等待用户输入了。

方式 2:用循环批量清空(更彻底)

如果担心缓冲区残留多个字符(比如用户输入 abc 这类非数字内容导致 scanf 失败,缓冲区残留更多垃圾),可以用循环清空:

int ch;
// 持续读取并丢弃字符,直到遇到换行或文件结束
while ((ch = getchar()) != '\n' && ch != EOF); 

这种方式会把缓冲区中 \n 之前的所有残留字符都清空,更适合复杂输入场景。

3. 完整修正

#include <stdio.h>

int main() {
    int n, m;
    // 假设 a 是统计数字的数组,这里简单定义长度
    int a[10] = {0}; 
    char c;

    // 读取 n
    scanf("%d", &n);
    // 关键:清空缓冲区残留的换行符
    getchar(); 

    for (int i = 0; i < n; i++) {
        // 读取一行中的字符,直到遇到换行
        while ((c = getchar()) != '\n') { 
            if (c >= '0' && c <= '9') {
                m = c - '0'; 
                a[m]++; 
            }
        }
    }

    // 输出统计结果(示例)
    for (int i = 0; i < 10; i++) {
        printf("数字 %d 出现 %d 次\n", i, a[i]);
    }

    return 0;
}

4. 总结

  • 问题核心是 scanf不会自动清理缓冲区的换行符,导致 getchar 误读残留内容。
  • 解决关键是在 scanf 后手动清空缓冲区,用 getchar() 或循环都能实现,根据场景选其一即可。
  • 修正后,getchar 就会正常等待用户输入,而非直接读取残留的 \n 了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值