且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

如何向流运算符添加缩进

更新时间:2023-12-06 14:57:28

最简单的解决方案是在 ostream和实际的流缓冲.像这样:

The simplest solution is to slip a filtering streambuf between the ostream and the actual streambuf. Something like:

class IndentingOStreambuf : public std::streambuf
{
    std::streambuf*     myDest;
    bool                myIsAtStartOfLine;
    std::string         myIndent;
    std::ostream*       myOwner;
protected:
    virtual int         overflow( int ch )
    {
        if ( myIsAtStartOfLine && ch != '\n' ) {
            myDest->sputn( myIndent.data(), myIndent.size() );
        }
        myIsAtStartOfLine = ch == '\n';
        return myDest->sputc( ch );
    }
public:
    explicit            IndentingOStreambuf( 
                            std::streambuf* dest, int indent = 4 )
        : myDest( dest )
        , myIsAtStartOfLine( true )
        , myIndent( indent, ' ' )
        , myOwner( NULL )
    {
    }
    explicit            IndentingOStreambuf(
                            std::ostream& dest, int indent = 4 )
        : myDest( dest.rdbuf() )
        , myIsAtStartOfLine( true )
        , myIndent( indent, ' ' )
        , myOwner( &dest )
    {
        myOwner->rdbuf( this );
    }
    virtual             ~IndentingOStreambuf()
    {
        if ( myOwner != NULL ) {
            myOwner->rdbuf( myDest );
        }
    }
};

要插入,只需创建一个streambuf的实例:

To insert, just create an instance of the streambuf:

IndentingOStreambuf indent( std::cout );
//  Indented output...

indent超出范围时,一切恢复正常.

When indent goes out of scope, everything returns to normal.

(对于日志记录,我有一个比较复杂的部分: LoggingOStreambuf__FILE____LINE__作为参数,设置 myIndent转换为带有这些参数的加格式的字符串,加上一个时间 标记,在每次输出后将其重置为缩进字符串,收集 所有输出都放在std::ostringstream中,并自动输出 到析构函数中的myDest.

(For logging, I have one that is a bit more complex: the LoggingOStreambuf takes __FILE__ and __LINE__ as arguments, sets myIndent to a formatted string with these arguments, plus a time stamp, resets it to an indentation string after each output, collects all of the output in an std::ostringstream, and outputs it atomically to myDest in the destructor.)