簡體   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