【问题标题】:Appending an ostream which is the empty string prevents further appends附加一个空字符串 ostream 可防止进一步附加
【发布时间】:2020-03-27 10:14:16
【问题描述】:

这个程序没有像我预期的那样工作。它输出“abc”,但我期望“abcxyz”。将包含空字符串的流附加到流中,会导致 streampos 设置为 -1,并且不能向其附加更多数据。 我正在使用来自C++ - Send data in one ostream to another ostream 的技术,但如果其中一个流恰好是空的,它就不起作用。我原以为在这种情况下 rdbuf() 可能会返回 nullptr,所以我检查了一下。它不是空值,但无论它返回什么都不会让下游感到高兴。注释掉该行:out << b.rdbuf(); 使其按预期输出“abcxyz”。附加可能碰巧为空的 ostream 的正确方法是什么?

#include <iostream>
#include <sstream>

int main(int argc, const char * argv[]) {
    std::stringstream a, b, c, out;

    a << "abc";
    b << "";
    c << "xyz";

    out << a.rdbuf();
                printf("after A out.tellp = %qd\n", (int64_t)out.tellp());
    out << b.rdbuf();
                printf("after B out.tellp = %qd\n", (int64_t)out.tellp());
    out << c.rdbuf();
                printf("after C out.tellp = %qd\n", (int64_t)out.tellp());

    std::cout << out.rdbuf() << std::endl;

    return 0;
}

输出是:

after A out.tellp = 3
after B out.tellp = -1
after C out.tellp = -1
abc
Program ended with exit code: 0

edit:固定版本。有没有更好的办法?

#include <iostream>
#include <sstream>

template <class T, class U>
void append(T& a, U& b) 
{
    if (int64_t(b.tellp()) <= 0) return;
    a << b.rdbuf();
}

int main(int argc, const char * argv[]) {
    std::stringstream a, b, c;

    a << "abc";
    b << "";
    c << "xyz";

    append(std::cout, a);
    append(std::cout, b);
    append(std::cout, c);
    std::cout << std::endl;

    return 0;
}

【问题讨论】:

  • 你看std::ostream::operator&lt;&lt;的文档了吗? "如果没有插入字符,则执行setstate(failbit)" b.rdbuf () 中有多少个字符?
  • 我会假设这意味着由于实际失败而没有插入任何字符,而不是因为流合法地为空。所以每次你想使用'
  • 我的回答是:阅读文档;不要假设任何事情。如果您阅读所提供文档的链接,则只有接受 std::basic_streambuf&lt;CharT, Traits&gt;* 作为参数的重载才能执行此操作。如果不希望出现这种行为,请使用不同的重载。
  • 为什么不直接使用str() 而不是rdbuf()
  • 谢谢。 str() 是中间字符串的额外分配。对我目前的使用来说可能没什么大不了的。但我想我还是会使用上面的tellp() 检查。

标签: c++ append ostream


【解决方案1】:

您可以使用std::basic_ios::good()std::basic_ios::clear() 来实现您想要实现的目标。

以下是示例代码。见it working here:

#include <iostream>
#include <sstream>

int main(int argc, const char * argv[]) 
{
    std::stringstream a;
    std::stringstream b;
    std::stringstream c;
    std::stringstream out;

    a << "abc";
    b << "";
    c << "xyz";

    out << a.rdbuf();
    printf("after A out.tellp = %qd\n", (int64_t)out.tellp());

    out << b.rdbuf();
    if( ! out.good() )
    {
        std::cout<< "It is not good!!!" << std::endl;
        out.clear();
    }
    printf("after B out.tellp = %qd\n", (int64_t)out.tellp());

    out << c.rdbuf();
    printf("after C out.tellp = %qd\n", (int64_t)out.tellp());

    std::cout << out.rdbuf() << std::endl;

    return 0;
}

【讨论】:

  • 这会清除/忽略任何失败,而不仅仅是空流。
猜你喜欢
  • 2018-09-26
  • 2011-05-02
  • 1970-01-01
  • 1970-01-01
  • 2016-01-13
  • 1970-01-01
  • 2019-07-10
  • 2013-12-16
  • 1970-01-01
相关资源
最近更新 更多