带前缀的C ++ cout [英] C++ cout with prefix
问题描述
我希望在cout上重定向的每行开头都有一个带前缀的ostream;
我尝试这样做:
I want a ostream with a prefix at the beginning of every line redirected on cout; I try this:
#include <iostream>
#include <thread>
class parallel_cout : public std::ostream
{
public:
parallel_cout(std::ostream& o):out(o){}
template <typename T>
std::ostream& operator<< (const T& val)
{
out << "prefix " << val;
return *this;
}
std::ostream& out;
};
int main()
{
parallel_cout pc(std::cout);
pc<<"a\nb"<<"c\n";
}
但我有输出
prefix a
b
不带c 。为什么?
推荐答案
修改 std :: ostream $ c $行为的方式通过重载任何输出运算符来不!而是从
std :: streambuf
派生一个类,并覆盖 virtual
函数 overflow( )
和 sync()
。在这种情况下,您可能会创建一个过滤流缓冲区,即,将另一个 std :: streambuf
作为参数,并以某种方式将修改过的字符流写入此流中
The way you modify the behavior of std::ostream
is not by overloading any of the output operators! Instead, you derive a class from std::streambuf
and override the virtual
functions overflow()
and sync()
. In you case you'd probably create a filtering stream buffer, i.e., you'd take another std::streambuf
as argument and write a somehow modified stream of characters to this stream buffer.
这里是一个简单的示例:
Here is a quick example:
#include <iostream>
class prefixbuf
: public std::streambuf
{
std::string prefix;
std::streambuf* sbuf;
bool need_prefix;
int sync() {
return this->sbuf->pubsync();
}
int overflow(int c) {
if (c != std::char_traits<char>::eof()) {
if (this->need_prefix
&& !this->prefix.empty()
&& this->prefix.size() != this->sbuf->sputn(&this->prefix[0], this->prefix.size())) {
return std::char_traits<char>::eof();
}
this->need_prefix = c == '\n';
}
return this->sbuf->sputc(c);
}
public:
prefixbuf(std::string const& prefix, std::streambuf* sbuf)
: prefix(prefix)
, sbuf(sbuf)
, need_prefix(true) {
}
};
class oprefixstream
: private virtual prefixbuf
, public std::ostream
{
public:
oprefixstream(std::string const& prefix, std::ostream& out)
: prefixbuf(prefix, out.rdbuf())
, std::ios(static_cast<std::streambuf*>(this))
, std::ostream(static_cast<std::streambuf*>(this)) {
}
};
int main()
{
oprefixstream out("prefix: ", std::cout);
out << "hello\n"
<< "world\n";
}
从概念上讲,流缓冲区保留内部缓冲区,但是内部缓冲区未设置上面的例子。每次没有空间将字符写入输出缓冲区时, virtual
函数 overflow()
为用字符调用(也可以用特殊值 std :: char_traits< char> :: eof()
调用,该值通常用于刷新缓冲区)。由于没有缓冲区,因此将为每个字符调用 overflow()
。此功能的全部作用是查看是否需要写入前缀,如果需要,则写入前缀
。如果编写了换行符'\n'
,该函数会记住,如果另外一个,则需要编写前缀
。字符被写入。然后,它将字符的写入转发到基础流缓冲区。
Stream buffers conceptually keep an internal buffer which is, however, not set up in the example above. Every time there is no space for a character to be written to the output buffer, the virtual
function overflow()
is called with a character (it may also be called with the special value std::char_traits<char>::eof()
which is typically used to flush the buffer). Since there is no buffer, overflow()
will be called for every character. All this function does is to see if it needs to write a prefix and, if so, writes the prefix
. In case a newline '\n'
is written, the function remembers that it needs to write the prefix
if another character is written. It then just forwards writing of the character to the underlying stream buffer.
虚拟
函数 sync()
用于将流与其外部表示同步。对于保留缓冲区的流缓冲区,请确保写入任何缓冲区。由于 prefixbuf
并没有真正保留缓冲区,因此所需要做的就是将 sync()
请求委托给通过调用 pubsync()
底层流缓冲区。
The virtual
function sync()
is used to synchronize the stream with its external representation. For a stream buffer keeping a buffer it makes sure that any buffer is written. Since the prefixbuf
doesn't really keep a buffer, all it needs to is to delegate the sync()
request to the underlying stream buffer by calling pubsync()
.
这篇关于带前缀的C ++ cout的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!