stringstream常用來安全的格式化若干個字串,數值到一個緩衝區, 而不用擔心溢出, 可以用來取代snprintf.
但是很多人都在使用stringstream的時候遇到因為stringstream內部的緩衝區沒有正確的清空導致的問題.
那麼把stringstream類內部的緩衝區正確的清空方式是什麼呢?
stringstream ss;
答案是: ss.str("") 方法.
另外,如果需要把格式化後的字串通過>>輸出到字串, 必須每次都調用clear()方法!
所以, 保險期間, 每次緩衝區格式化後, 都通過clear(), str("") 兩個函數都調用, 把stingstream類複位.
PS1: 網上有一些討論, 說ss.str("")方法不管用, 而通過 ss.str().clear(); 這可能是c++標準庫的實現方法不一致導致. 可以自行看下程式碼程式庫引用的sstream檔案的源碼.
在我的linux機器上, /usr/include/c++/4.1.0/sstream, 以及vs2008的實現, 都是和本文是一致的.
PS2: 注意str() 和 str("") 的區別
str() 是返回內部緩衝區的一個copy, str("") 是清空內部緩衝區.
測試程式:
#include <sstream>#include <stdio.h>using namespace std;int main(){ stringstream ss; string result; int n=1; ss.clear(); ss<<n; ss>>result; printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());
n=2; ss.clear(); ss<<n; ss>>result; printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());
n=3; ss.str(""); ss<<n; ss>>result; printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());
n=4; ss.clear(); ss.str(""); ss<<n; ss>>result; printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());}
測試結果:
result : 1, str : 1
result : 2, str : 12 // 調用了clear(), 沒有調用str(""), 結果錯誤.
result : 2, str : // 調用了 str(""), 沒有調用clear(), 結果錯誤.
result : 4, str : 4 // 調用了 clear()和str(""), 結果正確.
附上str("")和str()的內部實現:
/** * @brief Setting a new buffer. * @param s The string to use as a new sequence. * * Deallocates any previous stored sequence, then copies @a s to * use as a new one. */ void str(const __string_type& __s) { // Cannot use _M_string = __s, since v3 strings are COW. _M_string.assign(__s.data(), __s.size()); _M_stringbuf_init(_M_mode); }
// Get and set: /** * @brief Copying out the string buffer. * @return A copy of one of the underlying sequences. * * "If the buffer is only created in input mode, the underlying * character sequence is equal to the input sequence; otherwise, it * is equal to the output sequence." [27.7.1.2]/1 */ __string_type str() const { __string_type __ret; if (this->pptr()) { // The current egptr() may not be the actual string end. if (this->pptr() > this->egptr()) __ret = __string_type(this->pbase(), this->pptr()); else __ret = __string_type(this->pbase(), this->egptr()); } else __ret = _M_string; return __ret; }