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