蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 |
 您目前的位置:首页 > 自由软件 > 技术交流 > 应用编程


    

蓝森林 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]);
}



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com