2017-04-11 16 views
2

Pre-history:我試圖確保一些功能foo(std::stringstream&)消耗流中的所有數據。是否正在調用`stringstream :: str()`來獲取打印的內容實際上是合法的?

回答於previous question表明使用stringstream::str()是獲取stringstream內容的正確方法。我也看到了它正在使用任意類型轉換爲string這樣的:

std::stringstream sstr; 
sstr << 10; 
assert(sstr.str() == std::string("10")); // Conversion to std::string for clarity. 

然而,「內容」的概念是有些模糊。例如,考慮下面的代碼片段:

#include <assert.h> 
#include <sstream> 
#include <iostream> 

int main() { 
    std::stringstream s; 
    s << "10 20"; 
    int x; 
    s >> x; 
    std::cout << s.str() << "\n"; 
    return 0; 
} 

On Ideone(以及我的系統上)這個片斷輸出10 20,這意味着從stringstream讀不修改什麼str()回報。所以,我的假設是,str()返回一些內部緩衝區,它可以達到stringstream(或者,也可能是其內部的rdbuf,默認爲stringbuf)來處理「該緩衝區中的當前位置」。這是一個known thing

綜觀stringbuf::overflow()函數(其重新分配,如果沒有足夠的空間中的緩衝液),我可以看到:

這可以修改指針輸入和輸出控制的序列(高達eback,gptr,egptr,pbase,pptr,epptr的全部六個)。

所以,基本上沒有理論保證寫入stringstream不會分配更大的緩衝區。因此,即使使用stringstream::str()來轉換intstring存在缺陷:assert(sstr.str() == std::string("10"))從我的第一個片段可能會失敗,因爲內部緩衝區不能保證精確地具有必需的大小。

問題是:獲得stringstream「內容」的正確方法是什麼,其中「content」被定義爲「可以從steream消耗的所有字符」?

當然,人們可以閱讀逐字符,但我希望有一個不太詳細的解決方案。我對stringstream(我的第一個片段)沒有讀到任何內容感興趣,因爲我從未看到它失敗。

+0

'string str; s >> str;'讀正確的東西? –

+1

你爲什麼期望'>> x'會改變's'的內容? – pergy

+1

@LapshinDmitry它的行爲與標準流類似,僅讀取第一個「標記」。 – yeputons

回答

0

您可以使用tellg()函數(繼承自std::basic_istream)查找當前輸入位置。如果它返回-1,則不會消耗更多字符。否則,您可以使用s.str().substr(s.tellg())返回stringstream s中未消耗的字符。

+0

聽起來不錯。你確定沒有必要用'tellg'來替代「指向緩衝區結尾的指針」(['egptr'](http://www.cplusplus.com/reference/streambuf/streambuf/egptr/),大概是這樣嗎?) – yeputons

+1

'streambuf'中的這些函數可以在不復制任何數據的情況下做你想做的事情,但它們是受保護的,所以你不能訪問它們。如果您不介意複製數據(如上所述),則返回的字符串會在緩衝區末尾終止,因此您不需要「指向緩衝區結束的指針」 – GuyRT

相關問題