一、缓冲区的作用
- 一般缓冲区的作用是为了防止频繁的读写。
- A:往缓冲区里写,这里会有一个写的等待时间,并不总是有数据需要写;
- B: 从缓冲区里读,这里就有一个读间(没有数据或数据不全)的等待时间;
使用缓冲区可以减小程序输入时的等待,程序线程可以腾出CPU时间做其它的工作;
二、缓冲区的问题
缓冲区在提升了程序效率的同时,也带来了一些问题。
在项目的编写的工程中,很多时候并不需要用户的输入,这时如果用户输入,输入的信息就会被存入缓冲区中,当程序真的需要输入时,这些之前输入的信息,会被传入程序。造成程序获取错误信息,甚至是崩溃。
三、解决方案
1.使用fflush(stdin)
- 优点:使用这种方法清除缓冲区,简单快捷,只需将这条语句放入程序的输入语句的前面。
- 缺陷:但是这个方法有很大缺陷,因为在c语言得标准中没有明确规定这种用法,所以并不是所有的编译器都支持。
- 如果编译器支持,那么清除缓冲区就很简单了。
- 如果编译器不支持,它并不会报错,只是执行完这条语句后,缓冲区的内容依然存在。
2.getch()的连续获取
while(getchar()!='\n')
continue;
- 优点:使用这种方法进行缓冲区的清除,通用性好,任何系统和编译器都支持。
- 缺陷:缓冲区清除的不彻底,这种缓冲区清除方法,依据判断获取字符为“换行符”来停止。
- 如果缓冲区中有换行符,但不是最后一个字符,这时缓冲区中第一个换行符之前(包括换行符)被清掉,但是第一个换行符的后面字符不会被清掉。
- 如果缓冲区中没有换行符,那么while会进入死循环,程序会停下来,这时只有按下回车键,程序才会向后运行,这样很影响用户体验。
- 在无法判断是否需要清除缓冲区时,无法使用这个方法,因为这会导致程序无故停顿等待用户输入回车键
3.setbuf()
- 原理:使stdin输入流由默认缓冲区转为无缓冲区。
- 优点:使用这种方法清除缓冲区,简单快捷,只需将这条语句放入程序的输入语句的前面。
- 缺陷:通用性不好,这种方法只适用于Windows的大部分编译器,linux和Windows的少量编译器使用时没有反应。
4.scanf(“%*[^\n]%*c”)
原理:%*〔^\n〕将逐个读取缓冲区中的’\n’字符之前的其它字符,%后面的*表示将读取的这些字符丢弃,前遇到’\n’字符时便停止读取操作,此时,缓冲区中尚有一个’\n’字符遗留,所以后面的%*c将读取并丢弃这个遗留的换行符,这里的星号和前面的星号作用相同。由于所有从键盘的输入都是以回车结束的,而回车会产生一个’\n’字符,所以将’\n’连同它之前的字符全部读取并丢弃之后,也就相当于清除了输入缓冲区。
- 优点:使用这种方法进行缓冲区的清除,通用性好,任何系统和编译器都支持。
- 缺陷:缓冲区清除的不彻底,这种缓冲区清除方法,依据判断获取字符为“换行符”来停止。
- 在无法判断是否需要清除缓冲区时,无法使用这个方法,因为这会导致程序无故停顿等待用户输入回车键
5.判断键盘输入
while (_kbhit())
{
getch();
}
kbhit()是一个C和C++函数,用于非阻塞地响应键盘输入事件。
这是一个我自己发现的一个清缓冲区方法:
* 使用kbhit()判断是否有键盘输入,即判断缓冲区内是否有内容。
* 如果缓冲区有内容,就使用getch()去获取,直到缓冲区内的所有输入都被清掉。
ps:使用这种方法,简单快捷,只需把这几行复制到需要的输入的代码之前,应对用户的各种诡异输入,都可以清除干净。同时它可以自动判断是否需要进行清除操作,避免了程序的意外停止。很好用!!!