2012-01-09 36 views
0

免責聲明:不要使用::feof()作爲你的循環條件。例如,看到答案:file reading: feof() for binary files爲什麼:: feof()與:: _ eof(:: fileno())不同?

不過,我有「真實」的代碼,演示了不使用::feof()作爲我的循環條件的問題,但在邏輯上,這是爲了說明問題的最簡單的方法。

考慮以下情況:我們遍歷一個字符流一在-A-時間:

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::feof(my_file)) 
{ // We are not at EOF 
    c = ::getc(my_file); 
    // ...process "c" 
} 

上面的代碼按預期工作:文件處理單字符-AT-A-時間,並在EOF,我們退出。

然而,下面有意外的行爲

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::_eof(::fileno(my_file))) 
{ // We are not at EOF 
    c = ::getc(my_file); 
    // ...process "c" 
} 

我本來期望他們執行相同。 ::fileno()每次都正確地返回(整數)文件描述符。然而,測試::_eof(::fileno(my_file))工作恰好一次,然後在第二次嘗試返回1(指示EOF)。

我不明白這一點。

我想可以設想::feof()是「緩衝」(所以它工作正常),而::_eof()是「未緩衝」,並認爲整個文件已被「讀入」(因爲整個文件將適合從磁盤讀入的第一個塊)。但是,鑑於這些功能的目的,這不可能是真實的。所以,我真的很茫然。

發生了什麼事?

(文件被打開的 「文字」,是ASCII文本文件與大約十幾行,MSVS2008中,Win7/64)。

+1

您應該檢查getc()的返回值以檢查EOF。 if(c!= EOF)http://www.cplusplus.com/reference/clibrary/cstdio/getc/ – 2012-01-09 03:13:35

+0

您的代碼仍然不正確。您必須在*閱讀後檢查EOF *,但在*處理之前檢查。直到遇到它,纔會看到文件結尾。 – 2012-01-09 03:14:06

+0

同意上面的兩條評論(@Rajendran && @Kerrek)。但是,這些問題在我的用例中不存在:文件不是空的,並且有多行; 'feof()'正常工作; '_eof(fileno())'在第一個字符被讀取後失敗(返回'1')。所以,關於我的「不正確的情況」的合理投訴不適用於這種情況。 (這就是爲什麼我帶着一個免責聲明來領導。) – charley 2012-01-09 03:26:42

回答

5

我想這是可以想象:: FEOF()的「緩衝「(所以它正常工作 ),而:: _ eof()是」未緩衝「,並且認爲整個文件 已經是」已讀入「(因爲整個文件將適合從磁盤讀入的第一個塊 )。但是,考慮到這些功能的目的,這不可能是真實的 。所以,我真的很茫然。

我不知道爲什麼你會認爲它「考慮到這些功能的目的不可能是真的」。這兩個功能是爲了操作打開並以不同方式操作的文件,因此它們不兼容。

事實上,這正是發生的情況。試試這個:

FILE* my_file; 
// ...open "my_file" for reading... 

int c; 
while(0 == ::_eof(::fileno(my_file))) 
{ // We are not at EOF 
    c = ::getc(my_file); 

    long offset1 = ftell(my_file); 
    long offset2 = _tell(fileno(my_file)); 

    if (offset1 != offset2) 
    { 
    //here you will see that the file pointers are different 
    //which means that _eof and feof will fire true under different conditions 
    } 
    // ...process "c" 
} 

我會盡量根據您的意見詳細闡述一下。

當您打電話給fopen時,您將回到一個指向文件的指針。基礎流對象保留它自己的文件指針,它與基本文件描述符關聯的文件指針獨立於實際的。

當您調用_eof時,您在詢問您是否已達到實際文件的末尾。當你打電話給feof時,你問你是否已經到達文件末尾。由於文件流通常被緩衝,文件的末尾在流結束之前到達。

我還是想知道,下面你的答案,什麼目的 是_EOF(),如果它總是返回1,即使你沒看過 什麼(第一個字符後)。

要回答這個問題,_EOF的目的是爲了確定您是否使用_open和_read直接與文件描述符工作的時候到達了文件的末尾,而不是當您使用的fopen和FREAD或GETC工作與文件流。

+0

我花了一些時間來總結/理解@傑拉德在他的回答中是正確的。謝謝,@傑拉德! – charley 2013-04-20 14:54:11