我想要定义一个类MyStream,以便:
MyStream myStream;
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;给予输出
[blah]123
[blah]56
[blah]78基本上,我希望在前面插入一个"blah“,然后在每个不终止的std::endl之后插入。
这里的困难不是逻辑管理,而是检测和重载std::endl的处理。有什么优雅的方法吗?
谢谢!
编辑:我不需要关于逻辑管理的建议。我需要知道如何检测/过载打印std::endl。
发布于 2010-02-06 11:38:14
您需要做的是编写您自己的流缓冲区:当流缓冲区被刷新时,您需要输出前缀字符和流的内容。
以下操作是因为std::endl导致以下情况。
'\n'添加到流中。flush()pubsync()。1. This calls the virtual method `sync()`
2. Override this virtual method to do the work you want.#include <iostream>
#include <sstream>
class MyStream: public std::ostream
{
// Write a stream buffer that prefixes each line with Plop
class MyStreamBuf: public std::stringbuf
{
std::ostream& output;
public:
MyStreamBuf(std::ostream& str)
:output(str)
{}
~MyStreamBuf() {
if (pbase() != pptr()) {
putOutput();
}
}
// When we sync the stream with the output.
// 1) Output Plop then the buffer
// 2) Reset the buffer
// 3) flush the actual output stream we are using.
virtual int sync() {
putOutput();
return 0;
}
void putOutput() {
// Called by destructor.
// destructor can not call virtual methods.
output << "[blah]" << str();
str("");
output.flush();
}
};
// My Stream just uses a version of my special buffer
MyStreamBuf buffer;
public:
MyStream(std::ostream& str)
:std::ostream(&buffer)
,buffer(str)
{
}
};
int main()
{
MyStream myStream(std::cout);
myStream << 1 << 2 << 3 << std::endl << 5 << 6 << std::endl << 7 << 8 << std::endl;
}> ./a.out
[blah]123
[blah]56
[blah]78
>发布于 2010-02-06 10:20:01
MyStream类的重载运算符必须设置一个以前打印的令牌即endl标志。
然后,如果打印下一个对象,则可以将[blah]插入到它的前面。
std::endl是一个函数,接受并返回对std::ostream的引用。要检测它被转移到您的流中,您必须在您的类型和这样一个函数之间重载operator<<:
MyStream& operator<<( std::ostream&(*f)(std::ostream&) )
{
std::cout << f;
if( f == std::endl )
{
_lastTokenWasEndl = true;
}
return *this;
}发布于 2010-02-06 11:30:02
在原则上同意尼尔的观点。
您希望更改缓冲区的行为,因为这是扩展iostreams的唯一方法。endl这样做:
flush(__os.put(__os.widen('\n')));widen返回一个字符,因此不能将字符串放在其中。put调用putc,这不是一个虚拟函数,只是偶尔与overflow挂钩。您可以在flush拦截,后者调用缓冲区的sync。您需要截取和更改所有换行符,因为它们是overflow编辑的或手动的synced,并将它们转换为您的字符串。
设计一个覆盖缓冲区类很麻烦,因为basic_streambuf希望直接访问它的缓冲区内存。这使您无法轻松地将I/O请求传递给预先存在的basic_streambuf。您需要跳出一个分支,假设您知道流缓冲区类,并从中派生出来。(据我所知,cin和cout不能保证使用basic_filebuf。)然后,只需添加virtual overflow和sync。(见第27.5.2.4.5/3和27.5.2.4.2/7节)执行替换可能需要额外的空间,所以要小心提前分配。
-或-
只需在您自己的名称空间中声明一个新的endl,或者更好的是,一个根本不称为endl的操作器!
https://stackoverflow.com/questions/2212776
复制相似问题