向string stream流缓冲区写入覆盖原有内容的原因及解决方法
问题:将ostream关联到stringstream后输出会覆盖原有数据,如何实现追加?
我想创建一个stringstream和一个ostream,把stringstream的缓冲区传给ostream,让ostream向stringstream输出数据。但输出时原有数据被覆盖了,请问这是为什么?怎么实现数据追加而非覆盖的效果?
我的代码如下:
#include <iostream> #include <iomanip> #include <string> #include <sstream> using namespace std; int main () { stringstream s1("hello I am string stream"); streambuf *s1_bfr = s1.rdbuf(); ostream my_stream (s1_bfr); my_stream <<"hey"<<endl; cout <<s1.rdbuf()<<endl; //输出结果为: " hey o I am string stream"(看起来是被覆盖了) return 0; }
为什么原有数据会被覆盖?
当你用stringstream s1("hello I am string stream");初始化时,stringstream的输出位置指针(put pointer)默认指向缓冲区的起始位置。后续通过关联的ostream写入"hey"时,是从指针当前位置开始覆盖写入,自然就把开头的"hel"替换成了"hey",加上endl的换行,最终呈现出你看到的覆盖效果。
另外,stringstream默认是输入输出模式(ios::in | ios::out),这种模式下初始化后,put指针并不会自动移到缓冲区末尾,而是停在开头。
如何实现追加效果?
有两种简单的方法可以实现数据追加:
方法1:初始化后手动将put指针移到缓冲区末尾
在创建ostream之前,调用s1.seekp(0, ios::end);把输出指针移到缓冲区最后,后续写入就会从末尾开始追加:
#include <iostream> #include <iomanip> #include <string> #include <sstream> using namespace std; int main () { stringstream s1("hello I am string stream"); s1.seekp(0, ios::end); // 将输出指针移到缓冲区末尾 streambuf *s1_bfr = s1.rdbuf(); ostream my_stream (s1_bfr); my_stream <<"hey"<<endl; cout <<s1.rdbuf()<<endl; // 输出:hello I am string streamhey\n return 0; }
方法2:用ios::app模式打开stringstream
初始化stringstream时指定ios::app(追加模式),这样put指针会自动定位到缓冲区末尾,所有后续写入操作都会强制追加到数据末尾:
#include <iostream> #include <iomanip> #include <string> #include <sstream> using namespace std; int main () { stringstream s1("hello I am string stream", ios::in | ios::out | ios::app); streambuf *s1_bfr = s1.rdbuf(); ostream my_stream (s1_bfr); my_stream <<"hey"<<endl; cout <<s1.rdbuf()<<endl; // 输出:hello I am string streamhey\n return 0; }
注意:ios::app模式会强制所有输出操作前都将指针移到末尾,即使中途手动移动了指针,下次写入还是会回到末尾追加。如果需要灵活控制指针位置,优先选择方法1。
内容的提问来源于stack exchange,提问作者Parviz Pirizade
相关产品推荐
相关产品推荐

