【问题标题】:Extending C++ ostream扩展 C++ ostream
【发布时间】:2012-06-06 20:30:00
【问题描述】:

我正在尝试通过扩展std::streambuf 来了解有关 C++ I/O 流库的工作原理的更多信息。作为一个学习实验,我的目标是简单地创建一个自定义流,将所有输出定向到std::cerr。看起来很简单:

#include <iostream>
using namespace std;

class my_ostreambuf : public std::streambuf
{
    public:

    protected:

    std::streamsize xsputn(const char * s, std::streamsize n)
    {
        std::cerr << "Redirecting to cerr: " << s << std::endl;
        return n;
    }

};

int main()
{
    my_ostreambuf buf;
    std::ostream os(&buf);
    os << "TEST";
}

这似乎工作,因为它打印Redirecting to cerr: TEST。问题在于,当通过std::ostream::sputc单个字符(而不是字符串)插入流中时,它不起作用。例如:

int main()
{
    my_ostreambuf buf;
    std::ostream os(&buf);
    os << "ABC"; // works
    std::string s("TEST");
    std::copy(s.begin(), s.end(), std::ostreambuf_iterator<char>(os)); // DOESN'T WORK
}

我猜的问题是xsputn 不处理单字符插入。 (我猜sputc 不会在内部调用xsputn?)但是,查看std::streambuf 中的list of virtual protected functions,我看不到任何我应该重写的处理单个字符插入的函数。

那么,我该怎么做呢?

【问题讨论】:

    标签: c++ iostream


    【解决方案1】:

    单字符输出由overflow 处理。如果xsputn 进行实际输出,那么您可以根据xsputn 来实现overflow

    int_type overflow(int_type c = traits_type::eof())
    {
        if (c == traits_type::eof())
            return traits_type::eof();
        else
        {
            char_type ch = traits_type::to_char_type(c);
            return xsputn(&ch, 1) == 1 ? c : traits_type::eof();
        }
    }
    

    【讨论】:

    • 那么sputc处理的是什么?
    • @0x499602D2: sputc 将一个字符写入由 streambuf 维护的内部缓冲区。当缓冲区已满或使用 endlflush 操纵器时(以及在其他一些情况下),此缓冲区将被刷新。当缓冲区被刷新时,overflow 被调用,下一个字符在缓冲区未满时将进入缓冲区(如果缓冲区未满时被刷新,则使用 eof)。这个想法是overflow 将缓冲区的内容以及作为参数传递的字符(如果不是eof)写入实际目的地。 (在下一条评论中继续)
    • @0x499602D2:因此,只需重写 overflow 即可编写一个正常工作的 streambuf 实现。一次输出字符串时使用xsputn。它的默认实现只是将每个字符写入内部缓冲区,就像sputc 一样(最终它们将由overflow 处理)。但是,xsputn 可以被覆盖做一些更有效的事情,比如绕过缓冲区并将字符串直接写入目标。
    猜你喜欢
    • 2019-01-19
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多