2012-11-26 40 views
12

考慮:差異<< a_value

std::string  s_a, s_b; 

std::stringstream ss_1, ss_2; 

// at this stage: 
//  ss_1 and ss_2 have been used and are now in some strange state 
//  s_a and s_b contain non-white space words 

ss_1.str(std::string()); 
ss_1.clear(); 

ss_1 << s_a; 
ss_1 << s_b; 

// ss_1.str().c_str() is now the concatenation of s_a and s_b, 
//     <strike>with</strike> without space between them 

ss_2.str(s_a); 
ss_2.clear(); 

// ss_2.str().c_str() is now s_a 

ss_2 << s_b; // line *** 

// ss_2.str().c_str() the value of s_a is over-written by s_b 
// 
// Replacing line *** above with "ss_2 << ss_2.str() << " " << s_b;" 
//     results in ss_2 having the same content as ss_1. 

問題:

  1. 是什麼stringstream.str(a_value)之間的區別;和 stringstream < < a_value;具體來說,爲什麼第一個不是 允許通過< <連接,但第二個呢?

  2. 爲什麼SS_1自動獲得S_A和S_B之間的空白,但 我們需要在可能 取代線***行明確添加空格: ss_2 << ss_2.str() << " " << s_b;

+0

在你身邊例如,你的字符串是空的。 's_a和s_b'之間自動獲得空白是什麼意思? –

+0

@JesseGood'// s_a和s_b包含非空白字' –

回答

4

您遇到的問題是因爲std::stringstream默認構建爲ios_base::openmode mode = ios_base::in|ios_base::out這是一個非附加模式。

你感興趣的輸出模式在這裏(即:ios_base::openmode mode = ios_base::out

std::basic_stringbuf::str(const std::basic_string<CharT, Traits, Allocator>& s)工作在兩種不同的方式,這取決於openmode

  1. mode & ios_base::ate == false:(即:無追加輸出流):

    str將設置pptr() == pbase(),以便後續輸出將覆蓋從s中複製的字符

  2. mode & ios_base::ate == true:(即:追加輸出流):

    str將設置pptr() == pbase() + s.size(),使得隨後的輸出將是所附到最後一個字符從s複製

(請注意,由於C這追加模式是新++ 11)

更多細節見here

如果你想追加行爲,創建你stringstreamios_base::ate

std::stringstream ss(std::ios_base::out | std::ios_base::ate) 

簡單的示例應用程序的位置:

#include <iostream> 
#include <sstream> 

void non_appending() 
{ 
    std::stringstream ss; 
    std::string s = "hello world"; 

    ss.str(s); 
    std::cout << ss.str() << std::endl; 

    ss << "how are you?"; 
    std::cout << ss.str() << std::endl; 
} 

void appending() 
{ 
    std::stringstream ss(std::ios_base::out | std::ios_base::ate); 
    std::string s = "hello world"; 

    ss.str(s); 
    std::cout << ss.str() << std::endl; 

    ss << "how are you?"; 
    std::cout << ss.str() << std::endl; 
} 

int main() 
{ 
    non_appending(); 
    appending(); 

    exit(0); 
} 

在上面解釋了兩種不同的方式這將輸出:

hello world 
how are you? 
hello world 
hello worldhow are you? 
+2

另一種在不修改'openmode'的情況下做到這一點的方法是在插入前尋找流的末尾。 'ss.str(一個或多個); ss.seekp(0,std :: ios_base :: end); ss <<「你好嗎?」;' – Praetorian

+0

謝謝;小調整:在non_appending()中,如果第一次初始化時間更長,例如std::string s = "A very long hello world!";,那麼第二行輸出將是:「你好嗎?你好,世界!」 – user1823664

+1

@ user1823664 - 瞭解這裏發生了什麼,你需要明白''stringstream's'使用streambuffer'內部指針存儲在緩衝區中的位置。 'str()'使用這些指針來創建一個新的'std :: string' - 並且根據'egptr'或'pptr'的位置,你會得到一個由這些構建的字符串。 –

4

建議你讀stringstream的參考:http://en.cppreference.com/w/cpp/io/basic_stringstream

std::stringstream::str()替換底層字符串的內容

operator<<將數據插入到流中。

+0

仍然不解釋爲什麼'str()'後跟'<<'具有這樣的行爲,除非我誤讀了某些東西 –

+2

另一件事是在使用' str()',ththings不同步。例如,在新實例上使用'str()',接着使用'operator <<'將在開頭插入第二部分,覆蓋第一部分。 http://ideone.com/OPR9Ps – chris

+1

他問爲什麼調用'operator << ** **之後使用'str'替換內容不會**追加**到最後 - 答案是因爲' openmode'沒有'ate'設置 –