还剩3页未读,继续阅读
文本内容:
C语言缓冲区缓存详解缓冲区Buffer又称为缓存Cache,是内存空间的一部分也就是说,在内存中预留了一定的存储空间,用来暂时保存输入或输出的数据,这部分预留的空间就叫做缓冲区缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区为什么要引入缓冲区比如从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情现在你基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作缓冲区的类型缓冲区分为三种类型全缓冲、行缓冲和不带缓冲1全缓冲在这种情况下,当填满缓冲区后才进行实际I/O操作全缓冲的典型代表是对磁盘文件的读写2行缓冲在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作典型代表是标准输入stdin和标准输出stdouto3不带缓冲也就是不进行缓冲,标准错误文件stderr是典型代表,这使得出错信息可以直接尽快地显示出来ANSI CC89要求缓存具有下列特征•当且仅当标准输入和标准输出并不涉及交互设备时,它们才是全缓存的•标准出错决不会是全缓存的但是,这并没有告诉我们如果标准输入和输出涉及交互作用设备时,它们是不带缓存的还是行缓存的,以及标准输出是不带缓存的,还是行缓存的大部分系统默认使用下列类型的缓存•标准出错是不带缓存的•如果是涉及终端设备的流,则它们是行缓存的;否则是全缓存的我们经常要用到标准输入输出流,而ANSI C对stdin、stdout和stderr的缓存特征没有强行的规定,以至于不同的系统可能有不同的stdin、stdout和stderr的缓存特征目前主要的缓存特征是stdin和stdout是行缓存;而stderr是无缓存的缓冲区的大小如果我们没有自己设置缓冲区的话,系统会默认为标准输入输出设置一个缓冲区,这个缓冲区的大小通常是512个字节的大小缓冲区大小由stdio.h头文件中的宏BUFSIZ定义,如果希望查看它的大小,包含头文件,直接输出它的值即可
1.printf〃%d〃,BUFSIZ;缓冲区的大小是可以改变的,也可以将文件关联到自定义的缓冲区,详情可以查看setvbuf和setbuf函数缓冲区的刷新清空下列情况会引发缓冲区的刷新•缓冲区满时;•行缓冲区遇到回车时;•关闭文件;•使用特定函数刷新缓冲区深入理解缓冲区请查看结合缓冲区谈谈C语言getcharO、getcheO、getch的区别scanf的缓冲区问题scanfO是带有缓冲区的遇到scanf函数,程序会先检查输入缓冲区中是否有数据•如果没有,就等待用户输入用户从键盘输入的每个字符都会暂时保存到缓冲区,直到按下回车键,输入结束,scanf再从缓冲区中读取数据,赋值给变量•如果有数据,哪怕是一个字符,scanf也会直接读取,不会等待用户输入请看下面的例子
1.ttinclude stdio.h
2.#include stdlib.h
3.int main
4.
5.int a,b,c;
6.scanf,,%d,/,a;
7.scanfb;
8.scanf c;
9.printf,,a=%d,b=%d,c=%d\n〃,a,b,c;
10.
11.systempause;
12.return0;
13.运行结果100200300/a=100,b=200,c=300程序执行到第一个scanf0,由于缓冲区中没有数据,所以会等待用户输入从键盘输入100200300后按下回车键,输入就结束了,scanf开始从缓冲区中读取数据由于控制字符串是线d〃,所以它会读取一个整数,这里匹配到的整数是100接下来将100赋值给变量a,并将100从缓冲区中删除,此时缓冲区中剩下200300o注意scanf匹配到想要的数据后,会将匹配到的数据从缓冲区中删除,而没有匹配到的数据仍然会留在缓冲区中执行到第二个scanf时,检测到缓冲区中有内容,所以不会等待用户输入,而是直接从缓冲区中读取此时缓冲区中的内容为200300,scanf会匹配到整数200,并将•200从缓冲区中删除,剩下300执行到第三个scanf0时,同理会匹配到300,并将300赋值给变量c再来看一个例子
1.nc1ude stdio,h
2.ttinclude stdlib.h
3.int main
4.
5.int a,b=999;
6.char str
[30];
7.printf/,b=%d\n/,,b;
8.scanf,,%d,/,a;
9.scanfb;
10.scanf,,%s,/,str;
11.printf〃a=%d,b=%d,str=%s\nz,,a,b,str;
12.
13.systempause;
14.return0;
15.运行结果b二999100c.biancheng.net/a=100,b=999,str=c.biancheng.net程序执行到第一个scanf时等待用户输入从键盘输入100c.biancheng.net,按下回车键,scanf0匹配到100,赋值给变量a,同时将100从缓冲区中删除执行到第二个scanf时,缓冲区中有数据,会直接读取由于此时缓冲区中的内容为c.biancheng.net,并不是scanf想要的整数,所以匹配失败,不会给变量b赋值,这就是两次输出变量b的值相同的原因匹配失败也意味着不会从缓冲区中删除任何数据执行到第三个scanf时,缓冲区中的内容仍然是c.biancheng.net,明显是字符串,所以匹配成功并赋值给stro值得一提的是,在控制台中输入的任何内容本质上都是字符串,都会被如所匹配对于上面的程序,不妨换成下面的输入内容b二999100200300/a=100,b=200,str=300看,300也被%s匹配成功缓冲区引发的问题缓冲区虽然能够让输入更加方便,但有时也会引发奇怪的问题例如
1.#include stdio.h
2.ttinclude stdlib.h
3.int main
4.
5.int a=0,b=0;
6.scanf z,a=%dz,,a;
7.scanf〃b=%d〃,b;
8.printf,za=%d,b=%d\n〃,a,b;
9.
10.system pause;
11.return0;
12.运行结果a=100/a=100,b=0遇到第一个scanfO,输入a=100并回车,就会将100赋值给a,并将a=100从缓冲区中删除遇到第二个scanfO时,缓冲区中不是没有内容了吗,为什么不会等待用户输入呢?其实当用户按下回车键时,回车换行符也会被保存到缓冲区,只是大多数情况下scanfO会忽略,前面的两个例子就是这样但是当控制字符串不是以%xxx开头时,回车换行符就起作用了,scanfO会对它进行匹配,只是匹配失败而已该例中第二个scanfO就是匹配回车换行符失败,所以既不等待用户输入,也不给b赋值将第二个scanfO的控制字符串改成下面的样子scanf〃%d〃,b;运行结果a=100/200/a=100,b=200此时scanfO就会忽略缓冲区中的回车换行符,等待用户输入。
个人认证
优秀文档
获得点赞 0