在做實驗的時候遇到這個問題,找原因的時候發現出處除了講明原因,還舉了例子,所以記下來。
其實在循環判斷文件是否結束的時候可以直接就流輸入放在循環條件那裏,但是這裏補充使用eof()的一些細節問題。其實這是關於到底什麼時候標誌位纔會變化的問題。總結起來就是隻有使用一次流變量來輸入輸出,標誌位纔會更新一次。
正文:
fstream流的eof() 判斷有點不合常理
按正常邏輯來說,如果到了文件末尾的話 ,那eof()應返回真
但是,c++輸入輸出流如何知道是否到末尾呢?
原來是根據的是: 如果fin>>不能再讀入數據了,才發現到了文件結尾,這時纔給流設定文件結尾的標誌,此後調用eof()時,才返回真。
假設
fin>>x; //此時文件剛好讀完最後一個數據(將其保存在x中)
但是, 這時 fin.eof()仍未假 因爲,fin流的標誌eofbit是FALSE, fin流此時認爲文件還沒有到末尾
只有當流再次讀寫時
fin>>x; 發現已無可讀寫數據,此時流才知道到達了結尾,這時纔將標誌eofbit修改爲TRUE
此時流才知道了文件到底了末尾
也就是說,eof在讀取完最後一個數據後,仍是False,
當再次試圖讀一個數據時,由於發現沒數據可讀了 才知道到末尾了,此時才修改標誌,eof變爲TRUE
以下例子:
1 ifstream fin("D://line.txt"); 2 3 ofstream fout("D://T_line.txt",ios::trunc); 4 5 6 list<tag_Point> test_list; 7 8 tag_Point test; 9 10 11 12 while (!fin.eof()) 13 { 14 15 16 17 fin>>test.x; 18 fin>>test.y; 19 fin>>test.z; 20 21 22 23 24 test_list.push_back(test); 25 26 27 } 28 29 fin.close(); 30 31
在運行時 發現 test_list中的數據比文本中的數據多一行,也就是 文本中最後一行的數據寫了兩遍
始終無法理解
現在明白了:》
再讀完最後一行後,
因爲fin.eof()仍爲假, 所以會繼續while循環
當執行到while的第一個語句 fin>>test.x時,發現無可讀數據了,此時修改流屬性,fin.eof ()變爲TRUE
再執行 fin>>test.y; fin>>test.z;時,因爲已經到文件末尾了 ,所以 test保留了上次的值,也即test中的值爲變,還是文本最後一行
的數據
此時再push_back(test),壓入列表的仍是最後一行數據
由此導致了,列表中的數據比文本中的數據多一行
---------------------
知道了原因 ,便很好作出修改了
修改爲:
1 while ( fin>>test.x&&fin>>test.y&& fin>>test.z) 2 { 3 4 5 test_list.push_back(test); 6 7 8 } 9 10 fin.close();
這樣便沒問題了 ,當讀取完最後一行數據後,將其放入列表中,此時判斷while條件,也就是再次讀取數據,發現無數據可讀,讀取不成功 fin>>test.x返回False 由此結束循環。
參考資料:
http://zhidao.baidu.com/question/121339522.html?fr=im