2016-05-18 81 views
0

我有一個文件,我只想輸出最後一行到控制檯。使用seekg()從文件末尾搜索char C++

這是我的想法,我該怎麼做。使用file.seekg(0, ios::end)將自己置於文件的末尾。

然後,我可以創建一個遞減變量int decrement = -1;和使用while循環

while (joke.peek() != '\n') 
{ 
    decrement--; 

} 

,並得到了首發位置我的最後一行(從最終倒退)。

認識到這一點,joke.seekg(decrement, ios::end);應該設置我到最後一行的開頭,並假設我先前聲明string input; 我認爲

getline(joke, input); 
cout << input << endl; 

將其輸出到控制檯。

的完整代碼

void displayLastLine(ifstream &joke) 
{ 
    string input; 
    int decrement = -1; 


    joke.clear(); 
    joke.seekg(0, ios::end); 


    while (joke.peek() != '\n') 
    { 
     decrement--; 

    } 
    joke.clear(); 

    joke.seekg(decrement, ios::end); 

    getline(joke, input); 
    cout << input << endl; 

} 

的問題是,當我去呼籲文件這種方法,沒有任何反應。當我逐步瀏覽它時,遞減只是減去1,遠遠超出'\n'的位置。舉一個文本文件的例子,它會是這個樣子:

垃圾

垃圾

跳過此行

這就是我們要找的就行了!

回答

1
joke.seekg(0, ios::end); 

這將文件定位在最後。

while (joke.peek() != '\n') 

那麼,這裏的問題#1。當你在文件末尾時,peek()總是返回EOF

decrement--; 

你寫:

當我通過它一步,減量只是不斷減一,

嗯,你是怎麼想到的事情發生,因爲這是唯一的事情循環呢?您的for循環所做的唯一一件事是從decrement中減去1。所以就是這樣。

這是一個常見問題:計算機只做你告訴它做的事情,而不是你想做的事情。

雖然這不是最佳的,但是您的缺失步驟是在您之前peek(),您需要將seek()退回一個字符。然後,peek()向您顯示當前光標位置處的字符。然後,再輸入seek()一個字符,然後再次檢查peek(),依此類推。

但這仍然不足以滿足您的需求。大多數文本文件以換行符結尾。換句話說,換行符是文件中的最後一個字符。因此,即使您在幾乎所有情況下都添加了缺失的seek(),您的代碼最終會執行的操作是找到文件中的最後一個字符,即最終的換行符。

我對你的建議是暫時停止編寫代碼,而是想出一個做你想做什麼的邏輯過程,並用簡單的語言描述這個過程。然後,discuss your proposed course of action with your rubber duck。只有在你的橡皮鴨認同你的建議纔會起作用之後,再將你的簡單語言描述翻譯成代碼。

+0

幾乎所有的觀點都是有效的。但是,我的確從-1開始,因此我開始用下一個字符開始搜索。 – Podo

+0

在來到SO之前,我還會確保在未來諮詢我的橡皮鴨。 – Podo

+0

我必須檢查我的眼睛,對不起。我發誓我在代碼中看到了'joke.seekg(0,ios :: end);',其中有一個很大的零,而不是-1。而且,-1會將文件指針放在文件中的最後一個字符上,而不是最後一個字符的下一個字符。 –

1

peek不移動文件指針,它讀取字符而不提取它。所以,你不斷地偷看相同的值(字符)並最終陷入無限循環。

你需要做的是一樣的東西:

while (joke.peek() != '\n') 
{ 
    joke.seek(-1, ios::cur); 
} 

這將使輸入位置在\n,使用seekg第二超載。

請注意,這不是一個完美的解決方案。你需要檢查錯誤和邊界條件,但它解釋了你觀察到的行爲,並給你一些東西來開始修復你的代碼。

0

您的循環實際上只是遞減「遞減」,並沒有使用它來進行下一個搜索。

while (joke.peek() != '\n') 

{ 
    joke.seekg(decrement, std::ios::end); 
    decrement--; 
}