目录

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

前言

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

实现

思路

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

设置控制台属性

介绍

主要使用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. 你知道这些 985、211 院校的隶属吗?
  2. 「完结」你对深度学习模型的理解是否足够深刻,这12篇文章了解下
  3. cocos2d-x游戏实例(1)-视角跟随主角
  4. html效果属性是,htmltransition属性
  5. linux 管理mysql,Linux上MySQL的管理配置
  6. Ubuntu12 10下安装JDK7
  7. 基于bootstrap框架在ie8以下,兼容媒体查询[css样式]
  8. HoloLens 2开发:HoloLens开发VS安装与配置
  9. 1000以内的回文数_杭城有学校带学生玩扑克、数糖果... “云课堂”下的数学很有趣!这些数学游戏,居家玩起来~...
  10. 物流管理系统(SSM+vue+shiro)【前后台】
  11. 基于C++的Qt网络编程——聊天客户端
  12. 模拟器搭建之二:如何搭建 MTK 6589模拟器
  13. [足式机器人]Part3机构运动微分几何学分析与综合Ch01-1 平面运动微分几何学——【读书笔记】
  14. 计算机用户删除文件找回,电脑回收站清空删除的文件该怎么找回
  15. Android开发之Path详解
  16. 有类与无类路由下的路由匹配原则(转载)
  17. 用python画五角星、填充不了颜色_python的turtle画五角星内部不能填充的解决办法...
  18. 数据库定义语言(DDL)详解
  19. JAVA开发常用英语单词总结四
  20. mysql的sqlyog学习笔记(高级查询部分)(代码用命令行显示 )

热门文章

  1. 基于mqtt 的温湿度检测系统
  2. 010.MODBUS与台达变频器通讯1
  3. 昆仑通态TPC1071Gt/Gi无法下载程序的问题
  4. 编译x264:avisynth_c.h:825:3: error: unknown type name ‘HMODULE‘
  5. 微型计算机2009,微型计算机及接口技术2009年10月真题试题(04732)
  6. superuser root 原理详细分析
  7. WPS中在任务栏显示MathType的标志
  8. 数字化转型提速 用友、浪潮、金蝶、SAP谁将抢到头啖汤?
  9. MPF源码分析之资源文件加载
  10. SQL零基础投喂(复杂⼀点的查询)