[英]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.