我们使用函数向某个文件从当前流标签所在位置,读取n个字符。我们也会使用函数想文件的某个流位置写如n字符。但是,当这种写的动作小、而频繁。每次写又必须反映到硬盘上,也就是说需要频繁的操作硬盘,写一些小的更改,这是非常耗损效率。所以自然我们想到了,我们设立一个缓冲区,将那些要写如的数据先写到缓冲区中,当缓冲区满,或者其他情况发生的是否,我们在一起将他们写入到硬盘上。这样可以大大提高应用程序读写文件的速度。
这就是为什么需要缓冲,根本原因我认为是磁盘等外设的数据还和内存的速度相差甚远,所以我们不希望由于操作外设的原因让本来很快的内存和CPU跟着一起慢,我们想的办法:一是异步写(但这有时候不能符合应用要求),二就是缓冲读写。
而我们通常所理解的就是,read体系,就是那种无缓冲读写,不管是读还是写,调用这个体系的函数,会马上启动一次外设操作,读取数据或者写入数据。而fread体系则,使用了缓冲读写的方式,一定时间才调用read体系的函数。
清空stdin中的缓存
int c;
while((c = getchar()) != EOF && c != '\n');
会把缓存清空,但是会遗留下'\n' (10)
读取时,可以使用 scanf("%[^\n]",c);来空过\n。
或 scanf("\n%d",c);
失败的解决方案:
1,
while(!feof(stdin)){
getchar();
}
结果:程序会卡在这段,永远出不了while循环。
因为feof(FILE* file )函数必须等下一次读取不到数据使,才会返回非0;如读取空文件时,直接用feof(file)返回的是0,而用一下
fread()函数后,虽然什么都没有读到,但是feof(file)就返回非0了;
所以就会造成虽然到了结尾了,但是feof(stdin)返回的还是0,然后程序就会卡在getchar(),等待输入。
2,
fflush(stdin);
//使用后无效,查了一下,此函数不是标准函数,VC编译器可以使用,但是其他的编译器如gcc是不支持的(注:fflush(stdout)是标准函数)
linux下是刷新缓存,在VC下是清除缓存
3,
while((c = getchar()) != EOF && c != '\n');此时缓冲区第一个字符是'\n'。
scanf("%*[\n]%d",c); 此时c读取的是\n,没有读到后面的输入,导致程序错误。
没想明白为什么,%【\n】不是读到第一个非\n时停止吗,加上星号忽略这个,然后%d就可以读到输入。但是结果不对,请大侠解答谢谢!
4,
用setbuf(stdin, NULL);清空缓存
setbuf的函数原型是
事实上,read体系也有自己的缓冲机制,但是我们可以通过设置(open函数中DIRECT标志),放弃这种方式。
我们可以说,fread是在用户应用程序空间中,自己建立了一个缓冲机制,这种缓冲机制和内核read的缓冲机制并不冲突。
事实上,当我们使用read体系的是否,我们放弃了应用程序空间中的缓冲机制,但是如果不设置DIRECT标志,内核中的缓冲机制依然存在。
我们还有一种特殊的读写应用程序,叫着自缓冲读写,其实fread就是这样一种方式。只是它没有放弃内核的缓冲机制。但是对于复杂应用程序,例如数据库,这种对读写效率要求高的地方,他们使用了自己定义缓冲机制并且毅然放弃了内核的缓冲方式,为什么呢?因为内核缓冲方式,对缓冲数据何时应该存入到硬盘上,那些数据应该留下来更久没有应用背景相关的信息,所以它所出来的决策,通常是盲目的。但是,如果应用程序自己设置这种缓冲,可以很大程度上弥补这一问题。
缓冲I/O绝对有它的好处,这种机制的使用不仅在用户空间中,也在内核实现时会使用。当然有是否我们为了最求某些特别的需求,会使用直接I/O方式。当然事实上,这种I/O方式,与缓冲与否不是对立的。但是往往这样做了之后,缓冲就不够。我们要使用直接I/O要慎重考虑,你应用程序的需求,例如,你需要存取大块数据。这个是否“多拷贝”无疑是一个问题。 其中取舍需要仔细考虑、权衡。
http://www.cnblogs.com/blogoflee/archive/2012/02/01/2334433.html