繁体   English   中英

feof()在C中是如何工作的

[英]How feof() works in C

feof()是否为filepointer的当前位置检查eof或检查当前filepointer旁边的位置?

谢谢你的帮助 !

每个FILE流都有一个内部标志,指示调用者是否已尝试读取文件末尾。 feof返回那个标志。 该标志不指示当前文件位置是否作为文件的结尾,仅指示先前的读取是否已尝试读取超过文件的末尾。

作为一个例子,让我们一起阅读包含两个字节的文件。

f = fopen(filename, "r"); // file is opened
assert(!feof(f));         // eof flag is not set
c1 = getc(f);             // read first byte, one byte remaining
assert(!feof(f));         // eof flag is not set
c2 = getc(f);             // read second byte, no bytes remaining
assert(!feof(f));         // eof flag is not set
c3 = getc(f);             // try to read past end of the file
assert(feof(f));          // now, eof flag is set

这就是为什么以下是在阅读文件时使用eof的错误方法:

f = fopen(filename, "r");
while (!feof(f)) {
    c = getc(f);
    putchar(c);
}

由于feof工作方式,文件结束标志仅在getc尝试读取超过文件末尾时设置。 然后getc将返回EOF ,这不是一个字符,并且循环结构导致putchar尝试将其写出,导致错误或垃圾输出。

每个C标准库输入方法都会返回成功或失败的指示:如果getc尝试读取文件末尾或者读取时出错,则返回特殊值EOF 对于文件结束和错误,特殊值是相同的,这是使用feof的正确方法:您可以使用它来区分文件结束和错误情况。

f = fopen(filename, "r");
c = getc(f);
if (c == EOF) {
    if (feof(f))
        printf("it was end-of-file\n");
    else
        printf("it was error\n");
}

对于错误情况, FILE对象还有另一个内部标志: ferror 测试错误通常更清楚,而不是“不是文件结束”。 在C中读取文件的惯用方法是这样的:

f = fopen(filename, "r");
while ((c = getc(f)) != EOF) {
    putchar(c);
}
if (ferror(f)) {
    perror(filename):
    exit(EXIT_FAILURE);
}
fclose(f);

(为简洁起见,此处的示例省略了一些错误检查。)

feof函数很少有用。

通过了解feof的实现方式,您可以更好地了解feof工作原理。 这是第7版Unix stdio库如何实现feof的简化版本。 现代库非常相似,添加了提供线程安全性,提高效率和更清晰实现的代码。

extern  struct  _iobuf {
    char    *_ptr;
    int     _cnt;
    char    *_base;
    char    _flag;
    char    _file;
} _iob[_NFILE];

#define _IOEOF  020

#define feof(p)         (((p)->_flag&_IOEOF)!=0)

#define getc(p)         (--(p)->_cnt>=0? *(p)->_ptr++&0377:_filbuf(p))

int
_filbuf(FILE *iop)
{

    iop->_ptr = iop->_base;
    iop->_cnt = read(fileno(iop), iop->_ptr, BUFSIZ);
    if (iop->_cnt == 0) {
            iop->_flag |= _IOEOF;
            return(EOF);
    }
    return(*iop->_ptr++ & 0377);

}

stdio库为每个文件维护一个包含_base指向的内部缓冲区的结构。 缓冲区中的当前字符由_ptr指向,可用字符数包含在_cnt getc宏是很多高级功能的基础,比如scanf ,它试图从缓冲区返回一个字符。 如果缓冲区为空,它将调用_filbuf来填充它。 _filbuf反过来会调用read 如果read返回0,这意味着没有更多数据可用, _filbuf将设置_IOEOF标志,每次调用它时feof检查返回true。

从上面可以理解, feof将在您第一次尝试读取文件末尾的字符(或库函数代表您尝试)时返回true。 这对各种功能的行为有微妙的影响。 考虑一个包含单个字符的文件:数字1 getc读取该字符后, feof将返回false,因为_IOEOF标志未设置; 没有人试图读过文件的结尾。 再次调用getc将导致调用read_IOEOF标志的设置,这将导致feof返回true。 但是,在使用fscanf("%d", &n)从同一文件中读取数字后, feof将立即返回true,因为fscanf将尝试读取整数的其他数字。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM