fflush(stdio)

发布于 2023-05-11  164 次阅读


提出一个问题

先放一个代码:

#include <stdio.h>
int main()
{
    int a;
    char b;
    scanf_s("%d", &a);
    scanf_s("%c", &b);
    printf("a=%d\n", a);
    printf("b=%d\n", b);
    return 0;
}

在这里我使用visual studio2022学生版来运行一下这个代码

注意我只会输入一个字符

我们发现,虽然只输入一个1赋值给a,但是b也能输出!

为了解决这个问题,我们要更加深入了解一下原理~

缓冲区的理解

定义

缓存区是内存的一部分。在内存中预留一定的存储空间,在这些空间来输入和输出数据,这部分存储空间就是缓冲区啦。与之对应的,缓冲区被分为输入缓冲区输出缓冲区

如果无法理解“内存”,可以看看这个文章:

Q:为什么要有缓冲区?

  1. 减少磁盘读写次数
  2. 计算机对缓冲区的操作远远大于对磁盘操作速度

Q:缓冲区的类型

全缓冲/行缓冲/不带缓冲

Q:缓冲区会一直保留吗?

不一定,遇到以下情况会刷新

  1. 缓冲区满了
  2. 执行flush语句(flush:冲走)
  3. 执行endl语句(end line)
  4. 关闭文件

理解开头的输入输出问题

在我们输入“1”后在物理键盘上按了回车,当然这个回车被留在缓冲区了

计算机在读写给b时候因为没有输入就把刚刚的回车丢给b了

而回车的ASCLL码为10,所以输出的b就是字符10啦!

再次举例

这次我们依旧用上面的代码,但是输入“1 2”,也就是中间留了个空格

这样的话我们难以得到自己想要的b的值,于是我们就得使用fflush语句了

修改后的代码

#include <stdio.h>
int main()
{
    int a;
    char b;
    scanf_s("%d", &a);
    fflush(stdin);
    scanf_s("%c", &b);
    printf("a=%d\n", a);
    printf("b=%d\n", b);
    return 0;
}

注意,这个只有在vs2015前的版本才能有效,得到以下结果:

现代版本解决缓冲区的问题

途径一

使用rewind(stdin);

不过还是看编译器,我的编译器就无法完成清楚缓冲区... ...

途径二

使用scanf("%*c"),这个代码作用就是清除缓冲区最后一个字符