std::带有颜色和标题的 clog 包装器无法正确打印整数
std::clog wrapper with color and header fails to print integers properly
我需要一个类来包装对std::clog
的调用,以便:
- 每条消息都以一个标头为前缀,该标头包含时间和生成消息的实体的名称。 消息根据错误
- 类型(例如调试、警告、错误(着色。
- 使用它的方式完全等同于
std::clog << "..."
的所有功能(即具有隐式的基本类型到字符串转换、流操纵器、刷新等的能力(。
我的尝试是基于在这个论坛(*(中找到的许多例子,但我想以一种错误的方式,因为我的类有点错误。 本质上,我尝试的是通过使用覆盖overflow
和xputn
方法来扩展std::streambuf
,最终它们会调用clog
的operator<<
。
注意:我发现很难同时保持我的问题完整(**(,最小和可验证,因此任何建议/意见将不胜感激。不过,对我来说最重要的是我采取的方法,而不是特定的错误或实现缺陷。
class LogStream : public std::streambuf
{
public:
enum class Color { RED_BRIGHT, RED_DARK, /* ...others */ NO_COLOR };
LogStream(void);
LogStream(std::basic_ostream<char>& out, std::string cname, char c, Color icon_color, Color text_color = Color::NO_COLOR);
/* Non-copiable. */
LogStream(const LogStream&) = delete;
LogStream& operator=(const LogStream&) = delete;
static void setNameLength(int l);
protected:
int_type overflow(int_type c = traits_type::eof());
std::streamsize xsputn(const char* s, std::streamsize n);
private:
/* Important stuff: */
std::basic_ostream<char>& m_out;
bool m_new_line;
void conditionalPrintHeader(void);
void endLine(void);
/* For message decoration purposes: */
Color m_color_icon;
Color m_color_text;
char m_icon;
std::string m_cname;
static std::map<Color, const std::string> m_color_lut;
};
/* A macro to create static instances of a logger later in each CPP file. */
#define CREATE_LOGGER(klass)
namespace Log {
static std::ostream dbg(new LogStream(
std::clog,
#klass,
'>',
LogStream::Color::RED_BRIGHT,
LogStream::Color::NO_COLOR));
static std::ostream err(new LogStream(
std::clog,
#klass,
'e',
LogStream::Color::RED_BRIGHT,
LogStream::Color::RED_DARK));
}
我的覆盖函数是这样实现的:
std::streamsize LogStream::xsputn(const char* s, std::streamsize n)
{
conditionalPrintHeader();
if(s[n - 1] == 'n') {
m_new_line = true;
endLine();
}
m_out << s;
return n;
}
LogStream::int_type LogStream::overflow(int_type c)
{
if(c == traits_type::eof()) {
return traits_type::eof();
} else {
char_type ch = traits_type::to_char_type(c);
return xsputn(&ch, 1) == 1 ? c : traits_type::eof();
}
}
void LogStream::conditionalPrintHeader(void)
{
if(m_new_line) {
m_out << "... header and color escape codes ...";
m_new_line = false;
}
}
void LogStream::endLine(void)
{
m_out << "color escape code for no color.";
}
函数conditionalPrintHeader
和endLine
本质上尝试实现以下基本结构:
[header string] [ANSI color code] [<the log message>] [end color code]
这样当我这样做时:
Log::warn << "Integer: " << 123 << ", Bool: " << std::boolalpha << true << ", Float: " << 3.1415f << "n";
终端输出:
HEADER + [START COLOR] Integer: 123, Bool: true, Float: 3.1415 [END COLOR]
大多数时候,除了我需要打印整数值外,一切正常。我得到的不是数字,而是额外的垃圾,如下所示:
[ ... ] Integer: 123�~c, Bool: true, Float: 3.1415
笔记:
(*( 启发或直接促成我的解决方案的类似问题:
- https://stackoverflow.com/a/10921803/1876268 --我把大部分的实现概念带到了这里。
- 使用 std::cout 添加时间戳
- 声明/定义自定义类 cout 对象的正确方法
- https://codereview.stackexchange.com/a/187373/176115
- 正确实现 std::streambuf::overflow
(**( 我粘贴了整个头文件和源文件,以便尽可能完整,以防我在其他地方错过错误:Log.hpp、Log.cpp。
现在我认为问题在于xsputn
的字符串参数(我假设它不是以 null 结尾的(。我解决了整数的问题,如下所示,但我仍然不清楚这种方法是否好。
std::streamsize LogStream::xsputn(const char* s, std::streamsize n)
{
conditionalPrintHeader();
if(s[n - 1] == 'n') {
m_new_line = true;
endLine();
}
std::string str;
for(int c = 0; c < n; c++) {
str += s[c];
}
m_out << str;
return n;
}
相关文章:
- 在一定长度后从数组中打印时缺少整数
- 如何打印boost多精度128位无符号整数
- std::带有颜色和标题的 clog 包装器无法正确打印整数
- 无法在 Visual Studio 2019 中打印整数
- C++,尝试打印整数时cout的奇怪行为
- 打印整数总和 > 0
- 如何以相反顺序C 打印整数的单个数字
- 打印整数指针元素时的结果不同
- 使用数组从文件打印整数
- gdb ptype 打印整数后缀以指示它是有符号的、无符号的、无符号的长整型等
- 以幂形式 (^) 打印整数的质因数
- Python和Floats-只打印整数
- 有没有办法通过 int 指针一次打印整数
- 为什么我不能扫描和打印整数?
- 如何在net-snmp中打印整数和Counter32值
- 比scanf和printf更有效的扫描和打印整数的方法
- 使用递归以正确的顺序打印整数的数字
- 为什么控制台在使用运算符的地址时只打印整数变量的1个唯一地址
- 用C/C++打印整数
- 如何不打印整数列表的最后一个逗号