如何向流运算符添加缩进 我们在项目中使用C++流运算符(不好的方法是添加全局变量,它告诉缩进。 std::string OwnClassIndentation; std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) { oStream << "[SomeMember1:" << OwnClassIndentation << iOwnClass._ownMember1 << "]\n"; oStream << "[SomeMember2:" << OwnClassIndentation << iOwnClass._ownMember2 << "]\n"; } std::string OwnClassIndentation; std::ostream&operator
您可以创建自己的具有缩进变量的流类,并覆盖该类的endl,插入缩进。这可以使用自定义流操纵器完成,该操纵器将所需缩进级别存储在流的内部可扩展数组的字中。您可以使用函数如何向流运算符添加缩进 我们在项目中使用C++流运算符(不好的方法是添加全局变量,它告诉缩进。 std::string OwnClassIndentation; std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) { oStream << "[SomeMember1:" << OwnClassIndentation << iOwnClass._ownMember1 << "]\n"; oStream << "[SomeMember2:" << OwnClassIndentation << iOwnClass._ownMember2 << "]\n"; } std::string OwnClassIndentation; std::ostream&operator,c++,stream,operator-overloading,indentation,C++,Stream,Operator Overloading,Indentation,您可以创建自己的具有缩进变量的流类,并覆盖该类的endl,插入缩进。这可以使用自定义流操纵器完成,该操纵器将所需缩进级别存储在流的内部可扩展数组的字中。您可以使用函数ios\u base::xalloc。此函数将为您提供单词索引。您可以使用ios\u base::iword访问它。实现此功能的一种方法是: struct indent { indent(int level) : level(level) {} private: friend std::ostream& op
ios\u base::xalloc
。此函数将为您提供单词索引。您可以使用ios\u base::iword
访问它。实现此功能的一种方法是:
struct indent {
indent(int level) : level(level) {}
private:
friend std::ostream& operator<<(std::ostream& stream, const indent& val);
int level;
};
std::ostream& operator<<(std::ostream& stream, const indent& val) {
for(int i = 0; i < val.level; i++) {
stream << " ";
}
return stream;
}
std::ostream& operator<<(std::ostream & oStream, const OwnClass& iOwnClass) {
oStream << indent(oStream.iword(index)) << "[SomeMember1: " <<
iOwnClass._ownMember1 << "]\n";
oStream << indent(oStream.iword(index)) << "[SomeMember2: " <<
iOwnClass._ownMember2 << "]\n";
}
您可以这样使用它:
void some_func() {
indent_guard(2, std::cout, index);
// all output inside this function will be indented by 2 spaces
some_func(); // recursive call - output will be indented by 4 spaces
// here it will be 2 spaces again
}
最简单的解决方案是在
ostream
和实际的streambuf。类似于:
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的实例:
IndentingOStreambuf indent( std::cout );
// Indented output...
当缩进超出范围时,一切恢复正常
(对于日志记录,我有一个稍微复杂一点的:
LoggingOStreambuf
将\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
和\uuuuuuu
myIndent
到带有这些参数的格式化字符串,再加上时间
在每次输出后,将其重置为缩进字符串
std::ostringstream中的所有输出,并以原子方式输出
到析构函数中的myDest
。不会缩进第一个输出(可能是功能,也可能不是功能),将在最后一行后插入空格(如果文件以文本模式打开,则未定义行为),并且在输出'\n'
时不会缩进。当然,您必须定义所有,我也考虑过这一点,但是我必须写入的ostream不在我手中,所以我不能更改它的“类型”。我必须使用日志库中的ostream。streambuf工作了。@W.Goeman:您可以从ostream派生,它有虚拟方法s、 @Dani:我知道我可以派生ostream,假设我实现了“myostream”从中,我将要写入的流将永远不会是mystream。我正在写入另一个库提供给我的ostream。@W.Goeman:如果您只想在输出特定类型(其operator@JamesKanze:这一点很好-这同样适用于我的solution-没有想到。这当然会起作用,但我真的不喜欢全局变量,尤其是当它们只需要格式化我的日志时:)至少你知道iostream
:-)。这显然是处理自定义类的任何特殊操纵器的方法。如果第一个输出不是您自己定义的类型,则没有帮助;在这种情况下,您需要在streambuf
级别截取输出。这并没有完全解决我的问题,但肯定是一个“好消息”。谢谢。您的某些函数()
将导致堆栈溢出。工作正常!不过我做了一些更改,比如添加了increaseIndent和decreseindent方法。我的日志现在看起来正是我想要的。谢谢。@James:请您也提供更复杂的代码好吗?
void some_func() {
indent_guard(2, std::cout, index);
// all output inside this function will be indented by 2 spaces
some_func(); // recursive call - output will be indented by 4 spaces
// here it will be 2 spaces again
}
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 );
}
}
};
IndentingOStreambuf indent( std::cout );
// Indented output...