在讲空缓冲区之前我觉得有必要了解一下标准输入输出?
- 标准输入(stdin)设备:键盘,对应标准输入函数为scanf
- 标准输出(stdout)设备:屏幕,对应标准输出函数为printf
- 以上两个函数都包含在头文件stdio里
当我们从键盘中输入数据时,输入的数据不会直接存到你所定义的变量中,而是存在缓冲区中,当按下回车键后,scanf()函数才会将数据从缓冲区中取走,遵循先输入的数据先取走的原则,这里可以把缓冲区看成一个先进先出的队列。然而就在这时,出现了一个问题,当我们输入的是非字符或字符串类型的数据时,是否清空缓冲区对我们编程序想要的结果到时没什么影响,但是当我们想要在程序中多次输入字符类型数据时,第一次输入数据时以回车键作为结束,回车键是没有被清除的,还依然保存在缓冲区中!
有图有真相,看吧,第一个图为源码,第二个图为程序执行结果,其中i,j为字符类型变量,j为整形变量,当依次输入i和k之后,系统是不会给你输入字符j的机会i的直接输出结果,幸好我在这里输出的是它们的ascll码值,才将它们的原形显示出来,不难看出,i和k我输的是a和4,显示的没毛病,但是我没来的及输入j程序就已经退出了,那它怎么能输出个10呢,10的ascll码是什么!对,就是回车键,因为在输入字符i值即a后,回车作为结束,标准输入函数将a取走存在i中,缓冲区中的回车键还存在,由于(回车键为字符常量,不是整型常量,所以标准输入函数并不会将回车键取出赋给k,而是暂停一下等待用户往缓冲区中输入整形常量)(上面括号纯属个人猜测,逻辑上感觉是对的,所以写出来,若有错误,欢迎指出,嘻嘻)当输入整型常量4后,按回车结束,标准输入函数将4取走存在k中,下一个j为字符型变量,所以不用你输入标准输入函数就自动将缓冲区中的回车键存在j中。所以j的ascll码值为回车键的ascll码值。
好了bb了这么多,说下这个咋解决吧!
在Windows下写C程序时,用fflush(stdin);通过刷新缓冲区就很轻易将缓冲区清空,在linux下使用这个函数是没有用的,为了解决这个问题,我试了好长时间竟没试出一个靠谱的方法,为了不让大家浪费时间,我还是将我的方法分享一下,该怎样清空缓冲区呢?
- 方法一
setbuf(stdin,NULL);
这个操作可以理解为将控制输入流的文件指针指向了缓冲区重新设置为空,当下次再输入数据时就缓冲区就又从输入流指针处开始存,字符或字符串变量就不会取到回车符了。这个方法我是不常用的,直觉总觉得不靠谱!
观察程序运行结果,当程序结束后,总会留下一个尾巴,即回车符,导致总是自动在终端执行处执行一个回车键,很难受!反正不完美!
- 方法二
先看图吧:
好吧,既然这个讨厌的回车键总喜欢往缓冲区跑,就直接将它拒之门外,这样当取数据时,就不会担心回车键捣乱了!Ok,完美!从此,我养成了一个编程的习惯,在输入函数后面总喜欢跟一个while(‘\n’!=getchar());这样讨厌的回车键永远也别想进我的缓冲区了! - 那scanf(“%*[^\n]”);这个字符串扫描集看似也有这一功能,如何解释呢!它看起来也是不让回车键进入缓冲区呀!貌似也有2的功能,然而实践一下,我们会得到真相
请相信你的眼睛,它并没有将,回车键当在缓冲区外!所以j的ascll码仍为10,即回车键。
总算将这个问题弄清除了!真香,哈哈!
- 方法二