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("") 是清空內部緩沖區.
測試程序:
[cpp]
<P>#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());</P><P> n=2;
ss.clear();
ss<<n;
ss>>result;
printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());</P><P> n=3;
ss.str("");
ss<<n;
ss>>result;
printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());</P><P> n=4;
ss.clear();
ss.str("");
ss<<n;
ss>>result;
printf("result : %s, str : %s\n", result.c_str(), ss.str().c_str());
}</P>
#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()的內部實現:
[cpp]
/**
* @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);
}
/**
* @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);
}
[cpp]
// 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;
}