主要在於eof()不只是讀取檔案的最後乙個字元,它會接著往後讀取,如果此函式返回ture時,則此時返回的檔案結束符0xff才是真正的結尾。
具體內容如下:
在使用c/c++讀檔案的時候,一定都使用過eof()這個函式來判斷檔案是否為空或者是否讀到檔案結尾了,也會在使用這個函式的過程中遇到一些問題,如不能準確的判斷是否為空或者是否到了檔案尾,以至於有些人可能還會懷疑這個函式是不是本身在設計上就有問題。
先來看看如下這段**:
#include
stream
>
#include
>
using namespace std;
int
main()
while (
!fin.eof())
system(
"pause");
return 0;
}編譯並執行以上**,
如果test.txt不存在,程式會形成死迴圈,fin.eof()永遠返回false,
如果test.txt為空,程式列印出乙個x字元,
當test.txt中存在一字串「abcd」且沒有換行時,程式列印出「abcdd」,
當存在以上字串並且有一新的空行時,程式列印出「abcd」加上一空行。
這種現象可能讓很多人很迷惑,程式執行的結果似乎很不穩定,時對時錯。使用binary模式讀時結果一樣。
在這裡,大家可能有乙個誤區,認為eof()返回true時是讀到檔案的最後乙個字元,其實不然,eof()返回true時是讀到檔案結束符0xff,而檔案結束符是最後乙個字元的下乙個字元。如下圖所示:
因此,當讀到最後乙個字元時,程式會多讀一次(編譯器會讓指標停留在最後乙個字元那裡,然後重複讀取一次,這也就是就上面最後乙個字元會輸出兩次的原因。至於是不是所有的編譯器都這樣處理我就不太清楚了,我使用的vc6,vc8似乎都是這樣的)
問題出來了,就要找出對應的解決之道,要解決以上的問題,只需要調整一下條件語句即可:
fin.peek() == eof 或 fin.get(ch)
再來看一下另外一種情況:
#include
#include
#include
using namespace std;
int main()
system("pause");
return 0;
}上述**在vc8下編譯執行,發現,當檔案結尾沒有空行時,結果正確,當結尾有空行時,最後乙個字串將被重複輸出一次, 而vc6的情況則有所不同,沒有重複輸出,但輸出了乙個空行。
因此,為了保證在不同的編譯器下得到一致的我們期望的結果,將條件語句做一下修改:
fin >> str
綜上所述,我們可以得到以下結論:
1. 判斷檔案是否為空時使用peek函式,若peek返回eof則檔案為空;
2. 讀取檔案過程中,讀取非char型時,使用peek判斷檔案尾將不再適用,迴圈判斷條件應改用》操作符進行讀取,若讀入char型緩衝區,peek函式會表現得很好。
主要在於eof()不只是讀取檔案的最後乙個字元,它會接著往後讀取,如果此函式返回ture時,則此時返回的檔案結束符0xff才是真正的結尾。
具體內容如下:
在使用c/c++讀檔案的時候,一定都使用過eof()這個函式來判斷檔案是否為空或者是否讀到檔案結尾了,也會在使用這個函式的過程中遇到一些問題,如不能準確的判斷是否為空或者是否到了檔案尾,以至於有些人可能還會懷疑這個函式是不是本身在設計上就有問題。
先來看看如下這段**:
#include
stream
>
#include
>
using namespace std;
int
main()
while (
!fin.eof())
system(
"pause");
return 0;
}編譯並執行以上**,
如果test.txt不存在,程式會形成死迴圈,fin.eof()永遠返回false,
如果test.txt為空,程式列印出乙個x字元,
當test.txt中存在一字串「abcd」且沒有換行時,程式列印出「abcdd」,
當存在以上字串並且有一新的空行時,程式列印出「abcd」加上一空行。
這種現象可能讓很多人很迷惑,程式執行的結果似乎很不穩定,時對時錯。使用binary模式讀時結果一樣。
在這裡,大家可能有乙個誤區,認為eof()返回true時是讀到檔案的最後乙個字元,其實不然,eof()返回true時是讀到檔案結束符0xff,而檔案結束符是最後乙個字元的下乙個字元。如下圖所示:
因此,當讀到最後乙個字元時,程式會多讀一次(編譯器會讓指標停留在最後乙個字元那裡,然後重複讀取一次,這也就是就上面最後乙個字元會輸出兩次的原因。至於是不是所有的編譯器都這樣處理我就不太清楚了,我使用的vc6,vc8似乎都是這樣的)
問題出來了,就要找出對應的解決之道,要解決以上的問題,只需要調整一下條件語句即可:
fin.peek() == eof 或 fin.get(ch)
再來看一下另外一種情況:
#include
#include
#include
using namespace std;
int main()
system("pause");
return 0;
}上述**在vc8下編譯執行,發現,當檔案結尾沒有空行時,結果正確,當結尾有空行時,最後乙個字串將被重複輸出一次, 而vc6的情況則有所不同,沒有重複輸出,但輸出了乙個空行。
因此,為了保證在不同的編譯器下得到一致的我們期望的結果,將條件語句做一下修改:
fin >> str
綜上所述,我們可以得到以下結論:
1. 判斷檔案是否為空時使用peek函式,若peek返回eof則檔案為空;
2. 讀取檔案過程中,讀取非char型時,使用peek判斷檔案尾將不再適用,迴圈判斷條件應改用》操作符進行讀取,若讀入char型緩衝區,peek函式會表現得很好。
C 檔案操作 檢查檔案尾 讀取模式
檔案操作 讀取檔案時的讀取模式 fstream類中有個open 函式,其原型為 void open const char filename,int mode int access 引數含義 filename 開啟檔案的名字 mode 開啟檔案的模式 access 開啟檔案的屬性 開啟檔案的屬性在io...
C 是否讀到檔案尾, 怎麼判斷
不是問題的問題,看樣子真成了問題 多年前寫都是直接判斷 eof,現在發現沒有這個方法了 對不起,是寫程式過程中的總結,只是對我做了簡單記錄一下 讀入檔案 streamreader sr filestream fs try catch ioexception e while sr.endofstrea...
fread feof 檔案尾讀取重複的問題
問題 多路歸併排序時,每次通過fread讀取小檔案裡的乙個double資料,通過feof判斷是否讀取結束,結果,在最後總的排序檔案中,每個小檔案的最後一行的資料回重複一遍 原因 feof只是檢查標誌位,如果是good則返回0,是bad就返回1。更改標誌位的fread函式,只有當它讀不到東西了,才會把...