回答
每個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
嘗試將其寫入 out,導致錯誤或垃圾輸出。
每個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
的工作原理。以下是第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
標誌,並在每次調用它時返回true以檢查。
從上面可以理解,feof
將在您第一次嘗試讀取超過文件末尾的字符(或庫函數代表您嘗試)時返回true。這對各種功能的行爲有微妙的影響。考慮一個包含單個字符的文件:數字1
。在讀取getc
的字符後,feof
將返回false,因爲_IOEOF
標誌未設置;沒有人試圖讀過文件的末尾。再次調用getc
將導致read
的調用,_IOEOF
標誌的設置,這將導致feof
返回true。但是,在使用fscanf("%d", &n)
讀取同一文件中的數字後,feof
將立即返回true,因爲fscanf
將嘗試讀取整數的其他數字。
- 1. Feof error in C
- 2. FEOF,似乎不工作 - 文本文件
- 3. 在C文件處理中的feof()
- 4. C - Feof(stdin) - 如何在Windows中指示輸入結束?
- 5. * restrict/* __ restrict__如何在C/C++中工作?
- 6. char * argv []如何在c/C++中工作?
- 7. feof錯誤的循環在c
- 8. 如何FEOF使用和FERROR用於與fgets(minishell在C)
- 9. 如何在C#上工作
- 10. popen2()如何在c中工作?
- 11. 包括如何在C++中工作?
- 12. #if宏如何在C中工作?
- 13. cin.peek()如何在C++中工作?
- 14. scanf函數在C中如何工作?
- 15. strcat()如何在C++中工作?
- 16. 標誌如何在C中工作?
- 17. 字符串如何在c#中工作?
- 18. fread如何在C中工作?
- 19. fprintf如何在C++中工作?
- 20. 泛型如何在C++/CX中工作
- 21. 串聯如何在C中工作?
- 22. alloc在Objective C中如何工作?
- 23. 標題在Objective-C中如何工作?
- 24. 子對象如何在C中工作?
- 25. #include如何在C++中工作?
- 26. malloc函數如何在C中工作?
- 27. IDataErrorInfo.this [string propertyName]如何在C#中工作?
- 28. 協議如何在Objective C中工作?
- 29. 「return {...};」如何在C++ 11中工作?
- 30. ThrowTerminatingError如何在C#中工作?
簡單而正確:-) – cnicutar
對不起,興奮和擴大了一下。 – 2012-09-09 08:42:33
它更好 – cnicutar