gpt4 book ai didi

C++ 流 : Insert string after newline

转载 作者:行者123 更新时间:2023-11-30 01:54:26 24 4
gpt4 key购买 nike

原始问题是:如何在出现换行符后将内容自动插入到流中。只有在之后将某些内容(手动)插入到流中时才会发生插入。

下面是更详细的解释。


作为练习,我正在编写自己的记录器类。此代码段提供了基本的日志记录功能。

class Logger {
public:
static std::ostream & log( LogLevels::LogLevel level );
};

// Use it:
Logger::log( LogLevels::WARNING ) << "Something serious happened!" << std::endl;

这个例子打印出类似的东西

[ WARNING: 0 ] Something serious happened!

I would like to extend this functionality such that after insertion of a newline into the stream all debug messages are indented by the width of the logging header until Logger::log is called again. This is best explained by showing an example:

// Example (1)
Logger::log( LogLevels::WARNING ) << "Something happened!"
<< std::endl
<< "Some More information: "
<< 42
<< " (Still on the same line)"
<< std::endl;

Logger::log( LogLevels::INFO ) << "Merely a status code"
<< std::endl
<< "Which reads: "
<< 21
<< " (Also on the same line)"
<< std::endl;

// Example (2)
std::ostream & os = Logger::log( LogLevels::WARNING );
os << "First line"
<< std::endl;

os << "Second line"
<< std::endl;

// Example (3)
// [...]
// Some code is executed
Logger::log( LogLevels::WARNING ) << "A new error"
<< std::endl
<< "The code strikes back"
<< std::endl
<< "The return of the bugs"
<< std::endl ;

这会产生:

[ WARNING: 0 ] Something hapened!                 Some More information: 42 (Still on the same line)[ INFO: 1 ] Merely a status code            Which reads: 21 (Also on the same line)[ WARNING: 2 ] First line               Second line// [...][ WARNING: 99998 ] A new error                   The code strikes back                   The return of the bugs

这种行为能否实现,如果可以,如何实现?

最佳答案

只需在 ostream 和最终目标 streambuf。像下面这样的事情应该做诀窍:

class HeaderInserter : public std::streambuf
{
std::streambuf* myDest;
bool myIsAtStartOfLine;
protected:
int overflow( int ch ) override
{
int retval = 0;
if ( ch != traits_type::eof() ) {
if ( myIsAtStartOfLine ) {
std::string header = getHeader();
myDest->sputn( header.data(), header.size() );
}
retval = myDest->sputc( ch );
myIsAtStartOfLine = ch == '\n';
}
return retval;
}
public:
HeaderInserter( std::streambuf* dest )
: myDest( dest )
, myIsAtStartOfLine( true )
{
}
};

创建其中之一,并指向您的最终目的地( std::cerr.rdbuf() ,或您打开的 std::filebuf),然后使用 std::ostream指向它。

我在自己的记录器类中使用它;我添加额外的功能开始和完成新的记录器记录:之后的第一个输出开始一条记录输出一个时间戳,加上 __FILE____LINE__我传下来的;以下标题是只是任意数量的空白,缩进。和finish 函数还将确保记录以一个'\n' , 并且脸红了。

最后,一些更笼统的评论:首先,您不希望要调用的客户端代码 Logger::log ,而是一些宏,在命令自动传__FILE____LINE__进入实际创建的对象。对象本身可能应该是一个临时的,其析构函数调用上面的完成例程。最后,如果您处于多线程环境中,您将可能想要定位 streambuf实际上无限缓冲区(例如 std::vector<char> ),其中忽略来自用户的任何刷新,然后做任何事情有必要在完成时以原子方式写入整个缓冲区例程被调用,当然,确保每个线程都有它的拥有上述所有组件的实例。 (如果你在Unix 平台,例如 Posix 函数 write是保证原子性,所以你不需要任何锁。)

关于C++ 流 : Insert string after newline,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22042414/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com