带前缀的C ++ cout [英] C++ cout with prefix

查看:149
本文介绍了带前缀的C ++ cout的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望在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 不!而是从 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆