|
蓝森林 http://www.lslnet.com 2006年6月6日 10:18
[疑惑]关于fflush在切换文件读写模式中作用
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
char buf[132];
int get_line(char *buf, int bufsize, FILE *fp){
if(fgets(buf,bufsize,fp) == NULL){
if(feof(fp)){
printf("We meet the end of file.\n");
return EOF;
}else{
perror("fgets failed");
return 0;
}
}
printf("call fgets: %s", buf);
return 1;
}
int
main(void)
{
FILE *fp;
if((fp = fopen("testfile", "w+")) == NULL){
perror("fopen failed");
exit(1);
}
fprintf(fp, "this is the first line.\n");
fprintf(fp, "this is the second line.\n");
fclose(fp);
if((fp = fopen("testfile", "r+")) == NULL){
perror("file open failed");
exit(1);
}
get_line(buf, sizeof(buf), fp);
/* fflush(fp); 由读变为写*/
fprintf(fp, "I hope this line become the new second line.\n");
/* fflush(fp); 由写变为读*/
get_line(buf, sizeof(buf), fp);
fclose(fp);
}
"fflush.c" 55L, 846C 46,0-1 35%
书中说 fflush的作用如我注释中所写那样
但是在实际中 不管我注释掉fflush和不注释掉fflush
结果都是一样的
$ output
call fgets: this is the first line.
We meet the end of file.
$ more testfile
this is the first line.
I hope this line become the new second line.
请大家帮我解释一下 ^_^ |
It's recommended by the standard. Here is the appropriate section of the Standard (n1124 to be exact):
7.19.5.3p6
--> |
Thanks
but i wanna know the difference between using fflush function and not using
I programmed as the book describes, but i didn't find the difference -_-!
how amazing i am! |
胡乱猜测一下,可能是因为你的get_line调用了feof的缘故
也许你的feof是通过某个"file positioning function"实现的
把feof去掉再试试看有没有书上要的效果 |
是的 我的get_line()包括了feof(FILE *fp)函数
不过不是通过某个"file positioning function"实现的
暂时不去深究了 毕竟在读写转换的时候添加fflush()函数是一个好习惯^_^ |
首先,标准没有规定有没有fflush一定就对错,是没有定义的.
因为这个过程比较麻烦,最好去看看fflush的代码.下面是我以前看到的一个实现,我注释了,但是不一定全对(比如我理解错误),但是大概的细节都能看出来.
希望有点帮助
ssize_t _write(int d, const char *buf, size_t nbytes);
off_t _lseek(int fildes, off_t offset, int whence);
int
fflush(FILE *stream)
{
int count, c1, i, retval = 0;
if (!stream) {//stream 为NULL,清空所有的流,FOPEN_MAX为操作系统允许打开文件个数最大的值
for(i= 0; i < FOPEN_MAX; i++)
if (__iotab[i] && fflush(__iotab[i]))
retval = EOF;
return retval;
}
if (!stream->_buf
|| (!io_testflag(stream, _IOREADING)
&& !io_testflag(stream, _IOWRITING))) //缓冲区为空,或者没有读也没有写(可以以读写方式打开,但是还没有读写过)
//此时无所谓,不用清空
return 0;
if (io_testflag(stream, _IOREADING)) {//读过的状态
/* (void) fseek(stream, 0L, SEEK_CUR); */ //这个英文作者注。意思是下面的功能等价与fseek
//你知道,如果以读与写方式打开的话,读写交替的时候必须使用fseek
//为什么呢,因为fseek可以用来清除_IOREADING与_IOWRITING,为什么要清空那两个标志呢,因为 读文件时候有个这样的语句
/******** 如下:
if (io_testflag(stream, _IOWRITING))//文件在写状态的话为错误
{ stream->_flags |= _IOERR; return EOF; }*/
//所以写过的时候要读的话必须清除_IOWRITING标志,fseek可以做到,当然你可以自己操作流FILE结构,但是这样将不可移植
//下面 就相当于fseek
int adjust = 0;
if (stream->_buf && !io_testflag(stream,_IONBF))
adjust = stream->_count;
stream->_count = 0;
_lseek(fileno(stream), (off_t) adjust, SEEK_CUR);
if (io_testflag(stream, _IOWRITE))
stream->_flags &= ~(_IOREADING | _IOWRITING);
stream->_ptr = stream->_buf;
return 0;
}//fseek功能到此结束
else if (io_testflag(stream, _IONBF)) return 0;//没有缓冲则不用清空
if (io_testflag(stream, _IOREAD)) /* "a" or "+" mode */ //作者注,到这里就说明以读写方式打开,事实却没有_IOREADING读过
//则清空"写",
stream->_flags &= ~_IOWRITING;
count = stream->_ptr - stream->_buf;
stream->_ptr = stream->_buf;
if ( count <= 0 )//如果是输入流,条件为真
return 0;
if (io_testflag(stream, _IOAPPEND)) {//仅仅追加方式清空的话就直接到文件末尾
if (_lseek(fileno(stream), 0L, SEEK_END) == -1) {
stream->_flags |= _IOERR;
return EOF;
}
}
c1 = _write(stream->_fd, (char *)stream->_buf, count);//输出流写入
///////////////////////////////////////注意这个语句了,如果stream为输入流,写输入流意味着什么!!!!!!!!!
//
stream->_count = 0;
if ( count == c1 )//_write成功
return 0;
stream->_flags |= _IOERR;
return EOF;
}
void
__cleanup(void)//清空所有 2005525
{
register int i;
for(i= 0; i < FOPEN_MAX; i++)
if (__iotab[i] && io_testflag(__iotab[i], _IOWRITING))
(void) fflush(__iotab[i]);
} |
| |