【问题标题】:print out ostringstream buffer打印出 ostringstream 缓冲区
【发布时间】:2019-11-16 01:23:03
【问题描述】:

这是一段简单的代码,它应该打印一个std::ostringstream 缓冲区,而缓冲区又是通过rdbuf() 获得的。我希望通过istreambuf 迭代器或直接通过<< 运算符将此缓冲区打印到std::cout。令人惊讶的是,没有任何东西可以打印这个缓冲区。更有趣的是,<< 运算符清除了这个缓冲区。

#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>

using namespace std;

int main()
{
    std::ostringstream buf_ref;
    buf_ref << "bgdgdgdfg" << std::endl;

    auto buff = buf_ref.rdbuf();


    std::cout << "1 " << buf_ref.str() << std::endl;

    std::copy(std::istreambuf_iterator<char>(buff), std::istreambuf_iterator<char>(), std::ostream_iterator<char>(std::cout));

    std::cout << "2 " << buf_ref.str() << std::endl;

    std::cout << buff << std::endl; /*Why it clears the buffer? Why it doesn't output anything?*/

    std::cout << "3 " << buf_ref.str() << std::endl;

    return 0;
}

有什么想法吗? BTS,这是描述

【问题讨论】:

  • 大部分我都不太确定,但buff 应该是指向std::basic_stringbuf 的指针,所以这实际上应该输出一个地址。
  • buff 变量采用std::stringbuf* 类型,因此,正如@n314159 所说,您会期望写入一个指针值。也许字符串流/字符串缓冲区指针有一个特定的重载。无论如何,这将起作用:std::cout &lt;&lt; buff-&gt;str() &lt;&lt; std::endl;
  • 不,这里是描述 cplusplus.com/reference/ostream/ostream/operator%3C%3C 重载的参考所以它应该是 streambuf 的内容

标签: c++ std ostream streambuf


【解决方案1】:

好吧,&lt;&lt; 从流中读取数据,直到流变空,默认情况下它将数据块读取到第一个空格。

令人惊讶的是,没有任何东西可以打印此缓冲区。

最简单的就是把buff.str()打印出来。通过这种方式,您可以获得数据的副本,因此不会从原始流中删除。

我希望这个缓冲区被打印到 std::cout

也许这个小例子可以让我们了解它的工作原理。

stringstream buf;
streambuf *backup;

backup = cout.rdbuf();
cout.rdbuf(buf.rdbuf());
buf << "normal buf" << endl;
cout << "cout to buf" << endl;
cout.rdbuf(backup);
cout << "normal cout" << endl;
cout << buf.str() << endl;

导致以下输出:

normal cout
normal buf
cout to buf

但可能您的意思类似于此的功能:

stringstream buf;
streambuf *ptr;
ptr = buf.rdbuf();
// cout << buf.rdbuf(); // if you do it, check error state flags
// cout.clear(); // and/or clear it
buf << 'A' << endl;
cout << buf.rdbuf();
buf << 'B' << endl;
cout << ptr;

打印出来的:

A
B

【讨论】:

  • ostream::rdbuf(streambuf*) 函数实际上替换了接收流的缓冲区。不要那样做!
  • 你也可以从这个缓冲区(stringstream)中读取,比如从cin,例如。 G。 int by int、char by char 不带空格等。但是,如果您使用ostringstream,那么您只能像cout 一样使用它。
  • 为什么?我已经制作了一个备份指针,完成工作后我将cout 恢复到原来的状态。请详细说明,为什么不呢?您可以使用任何其他流来做到这一点。
  • 这虽然作为答案是正确的,但会使两个不同的流写入同一个缓冲区。我担心有人会在几个月后出现并从中复制代码并在他们的应用程序中使用,并想知道为什么他们会看到输出数据损坏。
  • Stefan,你更正了你的第二个变体,我想在我的代码中做同样的事情。我看到你的第二个变种和我的完全一样。它从字符串流中获取 streambuf 并将其打印到 cout。但请注意,您使用的是 stringstream,而我使用的是 ostringstream。我知道了,谢谢!
【解决方案2】:

如果您的目标是通过其rdbuf() 成员打印输出字符串流的流缓冲区,那么这是行不通的。您无法将输出字符串流缓冲区转换为输入字符串流缓冲区,因为 openmode 是在构造时设置的,并且无法更改。如果一个流被打开用于输出(在一个字符串流上),那么它就不能用于输入,反之亦然。您必须将所有内容复制到 std::istringstreamstd::stringbuf

std::ostringstream oss("abc");

std::istringstream iss(oss.str()); // 1
std::stringbuf buffer(oss.str()); // 2

std::cout << iss.rdbuf(); // 1
std::cout << &buffer; // 2

或者只使用std::stringstream

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 1970-01-01
    • 2012-07-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多