目录

  • 前言
  • 实现
    • 思路
    • 设置控制台属性
      • 介绍
      • 使用示例
    • 旧版
      • 日志类的打印方法
      • 日志类的使用示例
      • 运行效果
    • 新版
      • 改动
      • 日志打印方法
      • 日志使用示例
      • 运行效果
  • 代码下载

前言

在写较大型的程序时,往往不好调试,因为打印的日志信息太多,太繁杂,没办法一眼看到比较重要的信息,因此先写一个比较简单的日志类方便进行调试,以后再进行更新。

实现

思路

目前日志类将日志打印到控制台上,如果程序本身就是控制台程序,那么就打印到该控制台上,如果项目是窗口程序,则日志类将创建一个控制台窗口来打印日志。

设置控制台属性

介绍

主要使用SetConsoleTextAttribute函数来控制cmd窗口里文本的显示,原型如下:
BOOL SetConsoleTextAttribute(HANDLE hConsoleOutput, WORD wAttributes);
其中属性设置靠wAttributes低字节的低四位来控制前景色,高四位来控制背景色。

使用示例
SetConsoleTextAttribute(handle_out_,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY |BACKGROUND_RED);

宏定义如下:

#define FOREGROUND_BLUE      0x0001 // text color contains blue.
#define FOREGROUND_GREEN     0x0002 // text color contains green.
#define FOREGROUND_RED       0x0004 // text color contains red.
#define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
#define BACKGROUND_BLUE      0x0010 // background color contains blue.
#define BACKGROUND_GREEN     0x0020 // background color contains green.
#define BACKGROUND_RED       0x0040 // background color contains red.
#define BACKGROUND_INTENSITY 0x0080 // background color is intensified.

则可表示为:

前景蓝色 前景绿色 前景红色 前景高亮 背景蓝色 背景绿色 背景红色 背景高亮
1 1 1 1 0 0 1 0

即可得出是设置了前景色为白色,因为红绿蓝都是1,所以合成了白色,并且指定了前景色高亮。背景色为红色,不高亮。
效果如下:

旧版

日志类的打印方法
  static void DefaultMsg(std::string msg);static void DefaultMsg(const char* format, ...);static void Notice(std::string msg);static void Notice(const char* format, ...);static void Info(std::string msg);static void Info(const char* format, ...);static void Warning(std::string msg);static void Warning(const char* format, ...);static void Error(std::string msg);static void Error(const char* format, ...);
日志类的使用示例
#include <iostream>
#include "Logger.h"int main()
{Logger::Init(Logger::kLevelError | Logger::kLevelInfo | Logger::kLevelWarning); // Logger::Info("Info:信息");Logger::Notice("Notice:提示 %d", 123);Logger::DefaultMsg("Default:默认");Logger::Error("Error:错误 %s","No such file ...");Logger::Warning("Warning:警告");std::cout << "Hello World!\n";
}
运行效果

新版

改动

* 将其改为Header-Only,只需一个头文件
* 优化了结构设计,减少了重复代码

日志打印方法

日志使用示例

运行效果

代码下载

  • 旧版下载(Win-Logger)
  • 新版代码直接因为只有头文件,直接贴出来:
    #pragma once/* //需要包含的头文件#include <Windows.h>#include <iostream>#include <string>#include <algorithm>#include <ctime>#include <chrono>#include <mutex>
    */
    class Logger {private:inline Logger() { }inline ~Logger() {if (is_console_alloced_) FreeConsole();}public:enum Type {kType_None_Output = 0x0,kType_ErrorMsg = 0x1, /*错误信息*/kType_WarningMsg = 0x2, /*警告信息*/kType_Info = 0x4, /*信息*/kType_Notice = 0x8, /*提示*/kType_Default = 0x10, /*默认配置*/kType_TimeLog = 0x20 /*时间*/};public:inline static void Init(int level = 0x17){if (level) {GetLogger()->log_level_ = level;GetLogger()->is_console_alloced_ = !!AllocConsole(); // 如果没有控制台,那么Alloc一个,如果有,则会失败GetLogger()->handle_out_ = GetStdHandle(STD_OUTPUT_HANDLE);}}template <typename ...Args>static void DefaultMsg(const Args &...args) {GetLogger()->Log(Type::kType_Default, args...);}template <typename ...Args>static void Notice(const Args &...args) {GetLogger()->Log(Type::kType_Notice, args...);}template <typename ...Args>static void Info(const Args &...args) {GetLogger()->Log(Type::kType_Info, args...);}template <typename ...Args>static void Warning(const Args &...args) {GetLogger()->Log(Type::kType_WarningMsg, args...);}template <typename ...Args>static void Error(const Args &...args) {GetLogger()->Log(Type::kType_ErrorMsg, args...);}private:static inline Logger *GetLogger(){static Logger logger;return &logger;}inline bool Check(Type t) {return !!(log_level_ & t);}// 使用模板传递不定参,以支持c风格类型的格式化打印template <typename ...Args>void Log(Type t, const Args &...args) {if (!Check(t)) return;char buf[16 * 1024] = { 0 };sprintf_s(buf, args...);WriteLine(buf, t);}// 特化,打印stringtemplate <>void Log(Type t, const std::string &msg) {if (!Check(t)) return;WriteLine(msg, t);}inline void WriteLine(const std::string &msg, Type type){std::unique_lock<std::mutex> lock(mutex_); // 多线程打印时,确保正常打印Write(msg, type);Out("\n");}void Write(const std::string &msg, Type type){static struct {Type t;std::string t2string;}types[] = {{kType_Info,      "Info"},{kType_Notice,    "Notice"},{kType_Default,   "Default"},{kType_ErrorMsg,  "Error"},{kType_WarningMsg,"Warning"}};switch (type){case kType_Default:SetConsoleTextAttribute(handle_out_,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);break;case kType_Info:SetConsoleTextAttribute(handle_out_,FOREGROUND_BLUE | FOREGROUND_GREEN);break;case kType_Notice:SetConsoleTextAttribute(handle_out_,FOREGROUND_GREEN | FOREGROUND_INTENSITY);break;case kType_ErrorMsg:SetConsoleTextAttribute(handle_out_,FOREGROUND_RED | FOREGROUND_INTENSITY);break;case kType_WarningMsg:SetConsoleTextAttribute(handle_out_,FOREGROUND_INTENSITY |FOREGROUND_RED | FOREGROUND_GREEN);break;default:break;}const auto& i = std::find_if(std::begin(types), std::end(types), [&type](const auto& i) {return type == i.t; });if (i != std::end(types)) {auto end_time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());tm local;localtime_s(&local, &end_time);char line_header[128] = { 0 };if (log_level_ & kType_TimeLog) {char time_now[32] = { 0 };sprintf_s(time_now, "%04d-%02d-%02d %02d:%02d:%02d", local.tm_year + 1900, local.tm_mon + 1, local.tm_mday,local.tm_hour, local.tm_min, local.tm_sec);sprintf_s(line_header, "[%s  %-7s]:", time_now, i->t2string.c_str());} else {sprintf_s(line_header, "[%-7s]:", i->t2string.c_str());}Out(line_header);if (type != kType_ErrorMsg && type != kType_WarningMsg) {SetConsoleTextAttribute(handle_out_,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);}}Out(msg);SetConsoleTextAttribute(handle_out_,FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY);}inline void Out(const std::string &msg){if (!handle_out_) return;DWORD len = msg.length();WriteFile(handle_out_, msg.c_str(), len, &len, 0);}private:int log_level_ = 0x17;HANDLE handle_out_ = nullptr;bool is_console_alloced_ = false;std::mutex mutex_;
    };

编写VC++日志类(Logger) ---- 方便调试相关推荐

  1. muduo网络库学习(九)日志类Logger和LogStream,将日志信息打印到屏幕

    每一个成熟的项目都有大大小小的日志系统,在关键的地方打印日志信息,常用来跟踪程序运行,查找错误原因等,可以节省大量的debug时间 muduo的日志信息有5个级别 TRACE,细粒度最高的日志信息,打 ...

  2. 日志类Logger的基本使用

    Logger的基本使用 java开发过程中经常需要打印日志信息,往往会在每个类的第一行加上形如以下代码: protected static final Logger logger = LoggerFa ...

  3. DrySister看妹子应用(第一版)——5.代码回顾,调整与日志类编写

    DrySister看妹子应用(第一版)--5.代码回顾,调整与日志类编写 标签: DrySister 1.一些BB 说来惭愧,DrySister的上一篇距今已经有一年多了,期间有不少小伙伴 都曾私信过 ...

  4. 怎样用java编写日志_用JAVA写一个日志类程序以供大家学习

    中华网络安全联盟    作者:jacoo    来源:本站原创    时间:2006-4-18 说明: 尽管JAVA类库和其他工具提供了不少的纪录程序运行状态的日志类,我发觉也 不是万能的,有时需要根 ...

  5. 一个由印度人编写的VC串口类

    软件介绍 一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有 ...

  6. Salesforce系列(0):利用salesforce(sfdc)自带的IDE来编写并调试Apex类(入门级-调试篇)

    Salesforce系列(0):利用salesforce(sfdc)自带的IDE来编写并调试Apex类(入门级-调试篇) 前言 今天博主将为大家分享:Salesforce系列(0):利用salesfo ...

  7. Java日志输出Logger,Commons Logging,Log4j的运用

    日志 在编写程序的过程中,常常用System.out.println()打印出执行过程中的某些变量,观察每一步的结果与代码逻辑是否符合,然后有针对性地修改代码.改好之后又要删除打印语句,这样很麻烦. ...

  8. linux下实现 日志类重定向c 代码,log4cplus使用(三)-日志重定向

    本文讲述的是log4cplus日志输出到qt widget,封装了serverSocket.     log4cplus支持用户自定义输出设备,只需要继承自Appender,或者Appender子类, ...

  9. 第十一章 异常,日志,断言和调试

    2019独角兽企业重金招聘Python工程师标准>>> 第十一章 异常,日志,断言,调试 由于程序的错误或一些外部环境的影响造成用户数据的丢失,用户就有可能不再使用这个程序了.为了避 ...

最新文章

  1. 南阳理工大学 gnns 新基准
  2. highcharts如何把图多余的空白页面_如何进行前端性能测试入门篇
  3. rdd数据存内存 数据量_「大数据」(七十七) Spark之IO机制
  4. Spring MVC 到底是如何工作的
  5. linux中服务器之间的跳转,linux之***服务器间ip隧道跳转多ip路由走向分流(系真实案例)...
  6. 矩形并的面积(51Nod-2488)
  7. MATLAB R2021b for Mac 版 支持M1 MacOS12,超级详细步骤。(内附安装包网盘链接)
  8. 程序员学习交流的网站论坛
  9. 一个萌新的学习如何写BUG记录(学无止境,更无止境)
  10. MacOS图标文件 .icns 一键生成脚本
  11. 关于微信表情及输入法emoji显示问题解决方案
  12. 我的世界自定义服务器维护,[机制|娱乐]FixItem —— 良心铁匠铺,高自定义性,让你的玩家常驻服务器[理论全版本]...
  13. 【Vue.js】Vue.js组件库Element中的单选框、多选框、输入框和计数器
  14. Cisco AP-如何识别思科胖瘦AP
  15. jython 引入java.lang_Jython与Java的互相调用
  16. 掌握14种UML图,清晰图示
  17. imperva腾讯云waf部署具体过程(转载)
  18. Linux运维必看!深入掌握 Linux 系统的目录结构就靠本文了
  19. 【问题总结(12)】Cascader 省市区联动 obj[] Object.key() some.() String() forEach() 数组筛选过滤filter
  20. word2vec(嵌入空间)

热门文章

  1. 【Matplotlib】清理axes 和 figure(plt.cla、plt.clf、plt.close)
  2. ZZULIOJ 2829: 闯关游戏
  3. windows下编译xv6
  4. WebView中实现下载DownloadManager
  5. 主板中的Win10/win8.1 WHQL支持是否要开启
  6. 2022年海外版抖音TikTok最新最全攻略(TikTok Shop官方达人号解绑篇)
  7. 华为使用计算机投屏要打开什么,华为P20投屏开启电脑办公模式,键盘鼠标操作更方便...
  8. bash local关键字带来的退出码问题
  9. mysql查询json格式的数据(以key为条件查询)
  10. DC/DC直流12V升400V、12V升350V高压电源模块