本人也是初步学习缓冲区问题,如下面有不正确或者表达不当的地方还请大佬在评论区斧正!!!
对初学者来说fflush(stdin)被解释为清除输入缓存但在不同的时期它的作用也在不断淘汰。
缓冲区问题也能困扰了不少c语言小白或者一些人学习的脚步,那什么是缓冲区,缓存,以及怎么结决这些问题呢?那我一一给大家介绍,基础懂了就懂了其中的原理(博主可能会发布新的关于缓冲的问题或者其他问题的观点所以给波关注不迷路!!!)
我们将以以下代码作为实例
编辑
一、什么是缓冲区
缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。
缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。
比如图中蓝色是我们a的内存空间,红色是随机的缓存空间。
二、为什么要引入缓冲区
我们为什么要引入缓冲区呢?
编辑
我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。就像是买房者,中介,和卖方者的关系,可以让交易进行的更快更和谐。
缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。
缓冲区分为三种类型:全缓冲、行缓冲和不带缓冲。
1、全缓冲
在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。
2、行缓冲
在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是键盘输入数据。
3、不带缓冲
也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。
现在应该初步了解什么是缓冲区,以及缓冲的作用了吧,下面我们粗说fflush(stdin):
历史我们不要过于深究,大概了解下,它在vs 2013之前的版本以及vc++6.0可以正常使用但是在vs 2015环境下fflush(stdin)不再起作用(使用rewind(stdin)解决)
如果我们运行案例代码,输入类型不同结果如下
编辑
产生原因:在正常情况下,读取时输入缓冲区的内容会被scanf逐个取走,可以根据返回值判断成功读取走的数目。但在发生异常时,比如输入的类型不同读取发生异常,这时输入缓冲区的内容也就是不同类型的内容未被取走,在下次循环时自动从缓冲区中输入到scanf中,不再等待user输入,以至于scanf的返回值一直是0!=EOF,(EOF是一个宏,具体值时-1),进行死循环。(这不能怪缓存,更不能怪编译器,虽然他不会判断内容是否合法!)(这是输入缓冲区出现问题)
如何解决呢?
我们使用scanf(“%*[^\n]%*c)可以很有效的解决这个问题
编辑
让我们看看效果如何
编译
完美运行!
那怎么理解scanf("%*[^\n]%c") 呢?%[^\n]是逐个读取缓冲区’\n‘之前的内容,第一个%后的是丢弃掉这些内容,所以还有\n没有丢弃,我们再用%*c丢弃'\n',两者结合就可以清除掉缓冲区内容,再输入内容。
以上就是我对缓冲区的理解了,可能解决缓冲区的问题不止这一种,如果大佬们还有新的办法请在评论区留言,点赞鼓励一!!!