如何重用ostringstream?


Answers:


156

过去,我使用了一系列clear和str:

// clear, because eof or other bits may be still set. 
s.clear();
s.str("");

这样做对输入和输出字符串流都起作用。或者,您可以手动清除,然后从头开始寻找适当的顺序:

s.clear();
s.seekp(0); // for outputs: seek put ptr to start
s.seekg(0); // for inputs: seek get ptr to start

这将str通过覆盖当前输出缓冲区中的内容来防止某些重新分配。结果是这样的:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b";
assert(s.str() == "bello");

如果要将字符串用于c函数,则可以使用std::ends,放置一个终止null,如下所示:

std::ostringstream s;
s << "hello";
s.seekp(0);
s << "b" << std::ends;
assert(s.str().size() == 5 && std::strlen(s.str().data()) == 1);

std::ends是deprecated的遗留物std::strstream,它可以直接写入您在堆栈上分配的char数组。您必须手动插入终止null。但是,std::ends我不认为它已被弃用,因为它在上述情况下仍然很有用。


我正在尝试将s.str()与ostream一起使用。大小弄乱了它(我可以看到第一个字符为null,但打印得更多)。是否有固定str长度的好方法?我正在使用s.str()。c_str(); 自动取款机,它工作得很好

实际上,即使这样也不正确。我只是做了s.str("");auto str = s.str(); auto cstr = str.c_str(); file << cstr; s.clear(); s.seekp(0); s << ends;

std :: ends在Google测试中对我不起作用boost::any a = 1; std::ostringstream buffer; buffer << a << std::ends; EXPECT_EQ( buffer.str(), "any<(int)1>" ); TestUtilsTest.cpp:27: Failure Expected: buffer.str() Which is: "any<(int)1>\0" To be equal to: "any<(int)1>" ,如果我使用不同长度的字符串重复使用,我会被遗忘

如果您要避免重新分配,则“替代方案”是正确的答案。如果您想真正地“从头开始”而不进行重新分配,只需在发送std :: end之后再次调用seekp(0)。s.seekp(0); s << std::ends; s.seekp(0);
Chip Grandits

5

似乎是ostr.str("")电话能解决问题。


9
值得指出的是,这不会重复使用ostringstream中的基础缓冲区-它只是分配一个新缓冲区。因此,当您重用ostringstream对象时,您仍在分配两个缓冲区。我不认为ostringstream旨在按您期望的方式进行重用。
razlebe

2
它还不会清除状态,而.clear()会执行此操作。我同意,这确实不是要像这样使用。只需创建一个新的即可。仅当您配置文件时,您才会发现它是否有所不同。
布赖恩·尼尔

1
同意,布莱恩,是的。但是请注意,上面的litb的方法如何要求使用std :: ends。它会重用缓冲区,但会使您使用字符串流的代码与往常不同(通常不使用std :: ends)。
圣地亚哥塞维利亚

2

如果要以某种方式清除缓冲区,以使其在首次使用前就被清除,则需要先使用MSVC向缓冲区中添加一些内容。

struct Foo {
    std::ostringstream d_str;
    Foo() { 
        d_str << std::ends;   // Add this
    }
    void StrFunc(const char *);
    template<class T>
    inline void StrIt(const T &value) {
        d_str.clear();
        d_str.seekp(0);  // Or else you'll get an error with this seek
        d_str << value << std::ends;
        StrFunc(d_str.str().c_str());  // And your string will be empty
    }
};

我没有在VS2012上看到失败的行为。此外,要求clear导致failbit是一套,如果流为空。seekp如果没有流,则只调用即可返回。
乔纳森·梅2014年

0

你不知道 为了清楚起见,使用两个不同名称的流,让优化编译器确定它可以重用旧的流。


4
考虑一下用例,其中代码遍历输入数据,写入ostringstream(基于读取的数据),然后必须ostringstream不时写入某个地方(例如,在读取某些字符序列之后)内置的字符串,然后开始建立一个新的字符串。
安德烈·
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.