java输出流缓冲区内容清除,第4章 C语言输入输出 6、C语言清空缓冲区

在《结合C语言缓冲区谈scanf()函数》一节中讲到,scanf() 的缓冲区有时会引发奇怪的问题,多个 scanf() 之间要注意清空缓冲区。清空缓冲区主要有两种思路:一是将缓冲区中的数据丢弃,二是将缓冲区中的数据读取出来,但是却不使用。

fflush(stdin)

fflush() 函数用来清空文件缓冲区,它的原型为:

int fflush(FILE *stream)

int fflush(FILE *stream)

stream 为流指针,可以理解问一个文件指针。在C语言中,为了便于操作,键盘和显示器也被看作是文件,这样对硬件的操作就等同于对文件的操作。键盘称为标准输入文件(stdin),显示器称为标准输出文件(stdout),这在《C语言文件概述》一节中有详细讲解。

如此就可以使用 fflush() 来清空输入缓冲区中的数据,具体用法为:

fflush(stdin);

fflush(stdin);

请看下面的代码:

#include

#include

int main()

{

int a, b;

scanf("%d", &a);

fflush(stdin);

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

system("pause");

return 0;

}

#include

#include

int main()

{

int a, b;

scanf("%d", &a);

fflush(stdin);

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

system("pause");

return 0;

}

运行结果:

100 200↙

300↙

a=100, b=300

100 200↙

300↙

a=100, b=300

第一个 scanf() 读取完成后,将100赋值给变量 a,缓冲区中剩下200。然后调用 fflush() 函数将200从缓冲区中清除。执行到第二个 scanf() 时由于缓冲区中没有数据,所以会等待用户输入,将300赋值给变量 b。

如果把第7行代码注释掉,运行结果为:

100 200↙

a=100, b=200

100 200↙

a=100, b=200

由于没有清空缓冲区,执行到第二个 scanf() 时直接将缓冲区中的200赋值给变量 b。

fflush(stdin) 直接将缓冲区中的数据丢弃,是初学者常用的清空输入缓冲区的方法,它在 Windows 下一般是有效的,但在 Linux GCC 下可能无效,因为C语言标准规定:对于以 stdin 为参数的 fflush() 函数,它的行为是不确定的,fflush() 操作输入流是对标准C语言的扩充。

循环读取缓冲区中的数据

从缓冲区中读取剩余数据的方法也很多,这里讲解常用的两种。

1) 使用 getchar() 读取数据:

int c;

while((c = getchar()) != '\n' && c != EOF);

int c;

while((c = getchar()) != '\n' && c != EOF);

该代码不停地使用 getchar() 获取缓冲区中的字符,直到获取的字符是换行符\n或者是文件结尾符EOF为止。这个方法可以完美清空输入缓冲区,并且具备可移植性。

2) 使用 scanf() 读取:

scanf("%*[^\n]%*c");

scanf("%*[^\n]%*c");

%*[^\n]将逐个读取缓冲区中的 '\n' 字符之前的其它字符,% 后面的 * 表示将读取的这些字符丢弃,遇到 '\n' 字符时便停止读取。此时,缓冲区中尚有一个 '\n' 字符遗留,所以后面的%*c将读取并丢弃这个遗留的换行符,这里的星号和前面的星号作用相同。由于所有从键盘的输入都是以回车结束的,而回车会产生一个 '\n' 字符,所以将 '\n' 连同它之前的字符全部读取并丢弃之后,也就相当于清除了输入缓冲区。

请看下面的例子:

#include

#include

int main()

{

int a, b;

char c;

scanf("%d", &a);

scanf("%*[^\n]%*c");

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

scanf("%d", &a);

while((c = getchar()) != '\n' && c != EOF);

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

system("pause");

return 0;

}

#include

#include

int main()

{

int a, b;

char c;

scanf("%d", &a);

scanf("%*[^\n]%*c");

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

scanf("%d", &a);

while((c = getchar()) != '\n' && c != EOF);

scanf("%d", &b);

printf("a=%d, b=%d\n", a, b);

system("pause");

return 0;

}

运行结果:

100 200↙

300↙

a=100, b=300

9 99↙

999↙

a=9, b=999

100 200↙

300↙

a=100, b=300

9 99↙

999↙

a=9, b=999

虽然两种方法都能起到清空缓冲区的作用,但第一种方法需要额外定义一个 char 类型的变量,略显繁琐,并且 while 循环也会导致效率不高,所以建议使用第二种方法。

综上所述:如果只考虑Windows,建议使用fflush(stdin);,简单明了;如果兼顾移植和效率,建议使用scanf("%*[^\n]%*c");,虽然有点蹩脚,但确实能够奏效。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值