2012-09-30 252 views
1

我有一個涉及流的C++課程的編程任務,我試圖更好地理解爲什麼某些功能以他們的方式工作。從輸入流中讀取

我正在讀取文本後面帶有空白的istringstream的輸入。爲什麼最後一個單詞在輸出中重複?

istringstream is; 
string inputstring = "The cliched statement regarding the big brown dog and foobar or something "; 
string outputstring; 
is.str(inputstring); 
while (is.good()) 
{ 
    is >> outputstring; 
    cout << outputstring << endl; 
} 

因此,而不是循環的良好標記,我現在做提取的,而條件:

while (is >> outputstring) 
... 

這種運作良好,並沒有重複的最後一個字。這個語句在完成閱讀時突然從while循環中得到了什麼?提取返回對同一個流的引用,但會檢查標誌或其他內容嗎?

是否有單個標題可讓您包含所有流?

+0

對不起格式。我把每一行放在一個單獨的行上,但似乎沒有正確解析它。 – duffsterlp

回答

1

爲什麼最後一個單詞在輸出中重複?

這是發生了什麼:因爲你在inputstring到底有空格,讀最後一個字不翻轉的好()位。程序在最後一個單詞後面找到空格字符,認爲有更多單詞,因此is.good()仍然會返回trueis.good()只在程序試圖讀取字符串末尾時才返回false;這還沒有發生。

然後,下次去通過循環和is讀取時間,該程序實現,有沒有更多的話,不會覆蓋outputstring,所以你寫一次什麼是outputstring之前,這是最後一個字。

嘗試打印的is.good()結果之前,你從is讀取之後,並在inputstring結尾刪除空格字符來看看有什麼變化?

+0

你現在有足夠的信譽留下評論他人的答案。我恰巧相信你對'.good()'是正確的(儘管Dietmar是一位真正的專家,我不希望犯這樣的錯誤),但這*不是真正的答案。 –

0

你總是需要經過閱讀檢查,因爲流可處於良好狀態,但嘗試閱讀某些內容可能會失敗:畢竟,該流不能知道您要閱讀的內容。因此,當您在最後一個元素之後檢查流時,它仍然是good()。然後,您嘗試讀取哪一個失敗,並且good()false,但仍然會打印該值。

此外,您想用.good()作爲一個條件,因爲這可能會轉向false即使在讀取成功,如果是到達流的末尾。例如,如果讀取了一個數字,並且該文件末尾的數字後沒有空格,則設置爲std::ios_base::eofbit。只需使用idomatic循環是這樣的:

while (in >> value) { 
    std::cout << "read value='" << value << "'\n"; 
} 

它看起來過於簡單是正確的,但實際上做正確的事!

+0

實際上,當流以空白結束時,'eofbit'沒有在最後一次成功讀取時設置,因爲然後空白結束了先前的提取操作,然後下一個跳過空白並且找不到任何內容,所以流直接進入失敗狀態。如果沒有尾隨空格(輸入的最後一行沒有換行符),那麼提取操作由EOF條件結束,並且'good()'由於成功讀取而變爲假。 –

+0

這就是我的意思:可能有一個成功的讀取,但'std :: ios_base :: eofbit'被設置,因爲提取只在到達文件結尾時終止。一個沒有空格的值就是這樣一個例子。另一個例子是使用'std :: getline()'而沒有終止的換行符。我試圖澄清答案。 –

+0

@ BenVoigt:這很有道理。還有一個問題,在上一次提取中,爲什麼流不會向字符串變量寫入空字符串?我期望一個EOF就像一個空字符串或什麼...... – duffsterlp

2

這是什麼關於這條語句在完成閱讀時脫離while循環?提取返回對同一個流的引用,但會檢查標誌或其他內容嗎?

提取操作符返回流的引用是絕對正確的。任何用作while循環(還有fordo-while循環和if語句)的控制條件的表達式被強制爲bool類型。它計爲explicit轉換,因此調用ios_base::operator bool(),它將返回!this->fail()。這就是檢查標誌的方式。

+0

感謝您的幫助!但是這如何解釋EOF? fail()只檢查錯誤位和失敗位,它不檢查eof。另外,ios_base的文檔中記錄了bool()函數嗎?我沒有看到它在任何地方...... – duffsterlp

+0

@ user1590960:如果由於在流尾部而導致提取失敗,將會設置'failbit'。即如果讀取了一些數據併到達結尾,它就成功並設置了「eofbit」,所以'good()'爲false,'fail()'也爲false。所以它處理數據並循環並再次嘗試。現在,沒有數據被讀取,並且'failbit'被設置,這結束了循環。 –