我正在尝试用C ++创建一个优雅的日志系统。我目前正在使用printf()
,但cout
也可以选择。
我想要实现的是这样的
console_log( "ClassName", "funcName", "Message." );
我目前的代码是:
static void console_log( const std::string & className, const std::string & funcName, const std::string & message ) {
printf( "%s : %s : %s\n", className.c_str(), funcName.c_str(), message.c_str() );
}
打印得很好,就像这样
// For example:
console_log( "MenuPanel", "selectedThisButton", "Something happened." );
console_log( "MenuPanel", "selectedAnotherButton", "Another thing happened." );
// Output:
MenuPanel : selectedThisButton : Something happened.
MenuPanel : selectedAnotherButton : Another thing happened.
但是,我希望它以类似于表格的方式打印,其中所有“列”都正确对齐。例如:
MenuPanel : selectedThisButton : Something happened.
MenuPanel : selectedAnotherButton : Another thing happened.
如何使第一个和第二个“列”具有完全相同的宽度/字符数,如果需要还有其他空格?它不需要是动态的。将“列”设置为16个字符就可以了。
我不希望使用任何第三方库来做这么简单的事情。如果可能,不要boost
。
答案 0 :(得分:3)
我会使用I / O流而不是C风格printf
,并且对于具有特定宽度的打印内容(任何类型),您可以包含<iomanip>
并设置field width:
some_stream << std::setw(MY_WIDTH) << whatever;
示例:
#include <iostream>
#include <iomanip>
int main()
{
std::cout << std::setw(10) << "hi";
}
输出:
hi
答案 1 :(得分:2)
如果您准备好'保持简单'的方式可以替换:
printf( "%s : %s : %s\n", className.c_str(), funcName.c_str(),
message.c_str() );
到
printf( "%30s : %30s : %30s\n", className.c_str(), funcName.c_str(),
message.c_str() );
无论你喜欢什么样的宽度,你都可以查看printf文档中的对齐修饰符。
答案 2 :(得分:0)
一般的解决方案非常复杂,但如果你可以假设的话 固定宽度字体(每个字符具有相同的宽度), 并且知道前面每列的宽度,例如:
std::string rPad( std::string const& original, int minWidth )
{
return original
+ std::string(
std::max( minWidth - static_cast<int>( original.size() ), 0 ),
' ' );
}
void console_log(
std::string const& className,
std::string const& funcName,
std::string const& message )
{
std::cout << rPad( className, classNameWidth )
<< " : " << rPad( funcName, funcNameWidth )
<< " : " << rPad
<< std::endl;
}
或者,您可以执行以下操作:
void console_log(
std::string const& className,
std::string const& funcName,
std::string const& message )
{
std::cout << alignedText( classNameWidth ) << className
<< " : " << alignedText( funcNameWidth ) << funcName
<< " : " << message << std::endl;
}
操纵者alignedText
通常很有用,而你
无论如何应该在你的工具箱中拥有它:
class alignedText
{
mutable std::ostream* myOwner;
mutable std::ostream::fmtflags myFlags;
int myWidth;
public:
alignedText( int width ) : myOwner myWidth( width ) {}
~alignedText()
{
if ( myOwner != nullptr ) {
myOwner->flags( myFlags );
}
}
void set( std::ostream& dest ) const
{
if ( myOwner == nullptr ) {
myOwner = &dest;
myFlags = myOwner->flags();
}
dest.setf( std::ios_base::left, std::ios_base::adjustfield );
dest.width( myWidth );
}
friend std::ostream& operator<<( std::ostream& dest, alignedText const& manip )
{
manip.set( dest );
return dest;
}
};
(虽然可以使用printf
完成同样的事情,结果
是不太可读,完全不可维护,当然,
你的一般脆弱性为printf
。)