47 C语言清空缓冲区


C学习网:链接->C学习网

C训练网:链接->C训练网

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

fflush(stdin)

fflush() 函数用来清空文件缓冲区,它的原型为:
int fflush(FILE *stream)
stream 为流指针,可以理解为一个文件指针。在C语言中,为了便于操作,键盘和显示器也被看作是文件,这样对硬件的操作就等同于对文件的操作。键盘称为标准输入文件(stdin),显示器称为标准输出文件(stdout),这在《C语言文件概述》一节中有详细讲解。

如此就可以使用 fflush() 来清空输入缓冲区中的数据,具体用法为:
fflush(stdin);
请看下面的代码:
   
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. int a, b;
  6. scanf("%d", &a);
  7. fflush(stdin);
  8. scanf("%d", &b);
  9. printf("a=%d, b=%d\n", a, b);
  10. system("pause");
  11. return 0;
  12. }
运行结果:
100 200↙
300↙
a=100, b=300

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

如果把第7行代码注释掉,运行结果为:
100 200↙
a=100, b=200

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

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

循环读取缓冲区中的数据

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

1) 使用 getchar() 读取数据:
   
  1. int c;
  2. while((c = getchar()) != '\n' && c != EOF);
该代码不停地使用 getchar() 获取缓冲区中的字符,直到获取的字符是换行符\n或者是文件结尾符EOF为止。这个方法可以完美清空输入缓冲区,并且具备可移植性。

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

请看下面的例子:
   
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. int a, b;
  6. char c;
  7. scanf("%d", &a);
  8. scanf("%*[^\n]%*c");
  9. scanf("%d", &b);
  10. printf("a=%d, b=%d\n", a, b);
  11. scanf("%d", &a);
  12. while((c = getchar()) != '\n' && c != EOF);
  13. scanf("%d", &b);
  14. printf("a=%d, b=%d\n", a, b);
  15. system("pause");
  16. return 0;
  17. }
运行结果:
100 200↙
300↙
a=100, b=300
9 99↙
999↙
a=9, b=999

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

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

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告