C++好用的打印日志类

在项目中,调试打印十分重要,这里分享一个自己写的简单但是实用的打印日志类,控制台打印时间戳+具体内容+保存文件

1.相关库介绍及其基本用法

a.<iostream>

功能 :提供基本的输入输出流功能,如std::cout用于控制台输出,std::cin用于控制台输入。

基本用法示例

复制代码
#include <iostream>

int main() {
    std::cout << "Hello, World!" << std::endl;
    return 0;
}
b. <fstream>

功能 :用于文件的输入输出操作,包含std::ofstream(用于写入文件)和std::ifstream(用于读取文件)等类。

基本用法示例

复制代码
#include <fstream>
#include <iostream>

int main() {
    std::ofstream outfile("example.txt");
    if (outfile.is_open()) {
        outfile << "This is a test." << std::endl;
        outfile.close();
    } else {
        std::cerr << "Unable to open file" << std::endl;
    }
    return 0;
}
c. <string>

功能 :提供std::string类,用于处理字符串,支持字符串的拼接、查找、替换等操作。

基本用法示例

复制代码
#include <iostream>
#include <string>

int main() {
    std::string str1 = "Hello";
    std::string str2 = " World";
    std::string result = str1 + str2;
    std::cout << result << std::endl;
    return 0;
}
d. <iomanip>

功能 :提供输入输出流操作符,用于格式化输出,如std::put_time用于格式化时间输出。

基本用法示例

复制代码
#include <iostream>
#include <iomanip>
#include <ctime>

int main() {
    std::time_t now = std::time(nullptr);
    std::cout << std::put_time(std::localtime(&now), "%Y-%m-%d %H:%M:%S") << std::endl;
    return 0;
}
e. <chrono>

功能:提供时间处理功能,用于获取当前时间、计算时间间隔等。

基本用法示例

复制代码
#include <iostream>
#include <chrono>
#include <ctime>

int main() {
    auto now = std::chrono::system_clock::now();
    auto now_time = std::chrono::system_clock::to_time_t(now);
    std::cout << std::put_time(std::localtime(&now_time), "%Y-%m-%d %H:%M:%S") << std::endl;
    return 0;
}

f.<sstream>

功能 :提供了用于字符串流处理的类和函数。字符串流是一种非常有用的工具,它允许你像操作输入输出流(如 std::cinstd::cout)一样操作字符串。主要包含以下三个类:

std::istringstream :用于从字符串中读取数据,类似于 std::cin 从标准输入读取数据,常被用于将字符串解析为不同类型的数据。

std::ostringstream :用于向字符串中写入数据,类似于 std::cout 向标准输出写入数据,常被用于将不同类型的数据组合成一个字符串。

std::stringstream :既可以用于读取数据,也可以用于写入数据,结合了 std::istringstreamstd::ostringstream 的功能。

基本用法示例

复制代码
#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::string input = "123 Hello";
    std::istringstream iss(input);

    int number;
    std::string word;

    // 从字符串流中读取整数
    iss >> number;
    // 从字符串流中读取字符串
    iss >> word;

    std::cout << "Number: " << number << std::endl;
    std::cout << "Word: " << word << std::endl;

    return 0;
}

#include <iostream>
#include <sstream>
#include <string>

int main() {
    int age = 25;
    std::string name = "Alice";

    std::ostringstream oss;
    // 向字符串流中写入数据
    oss << "Name: " << name << ", Age: " << age;
    // 获取组合后的字符串
    std::string output = oss.str();

    std::cout << output << std::endl;

    return 0;
}

#include <iostream>
#include <sstream>
#include <string>

int main() {
    std::stringstream ss;

    // 向字符串流中写入数据
    ss << "456 World";

    int num;
    std::string str;
    // 从字符串流中读取数据
    ss >> num;
    ss >> str;

    std::cout << "Number: " << num << std::endl;
    std::cout << "String: " << str << std::endl;

    return 0;
}

2.日志demo运行结果

demo是在Linux系统下进行运行

3.实现代码

实现代码包括详细注释,最后使用宏定义方便调用

复制代码
//
// Created by Administrator on 2025/4/30.
//

#ifndef LOGDEMO_LOGGER_H
#define LOGDEMO_LOGGER_H

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <chrono>
#include <sstream>

/**
 * @brief 日志记录类,提供不同级别的日志输出功能
 *
 * 使用单例模式确保全局唯一日志实例
 * 支持不同级别的日志输出:INFO, WARNING, ERROR
 * 自动添加时间戳和日志级别前缀
 * 日志除了打印到控制台,还会保存到以当天日期命名的txt文件中
 */
class Logger {
public:
    // 日志级别枚举
    enum class Level {
        INFO,
        WARNING,
        ERROR
    };

    // 获取单例实例
    static Logger& getInstance() {
        static Logger instance;
        return instance;
    }

    // 禁用拷贝和赋值,确保单例的正确性
    Logger(const Logger&) = delete;
    Logger& operator=(const Logger&) = delete;

    // 日志输出方法
    void log(Level level, const std::string& message) {
        auto now = std::chrono::system_clock::now();
        auto now_time = std::chrono::system_clock::to_time_t(now);

        // 使用 std::ostringstream 格式化时间戳
        std::ostringstream timestamp_stream;
        timestamp_stream << std::put_time(std::localtime(&now_time), "%Y-%m-%d %H:%M:%S");
        std::string timestamp = timestamp_stream.str();

        std::string logLevel;

        switch (level) {
            case Level::INFO: logLevel = "[INFO]"; break;
            case Level::WARNING: logLevel = "[WARNING]"; break;
            case Level::ERROR: logLevel = "[ERROR]"; break;
        }

        std::string logMessage = "[" + timestamp + "] " + logLevel + " " + message;

        // 打印到控制台
        std::cout << logMessage << std::endl;

        // 使用 std::ostringstream 格式化文件名
        std::ostringstream filename_stream;
        filename_stream << std::put_time(std::localtime(&now_time), "%Y-%m-%d") << ".txt";
        std::string filename = filename_stream.str();

        std::ofstream outfile(filename, std::ios::app);
        if (outfile.is_open()) {
            outfile << logMessage << std::endl;
            outfile.close();
        } else {
            std::cerr << "Unable to open file: " << filename << std::endl;
        }
    }

private:
    Logger() = default; // 私有构造函数确保单例
};

// 日志宏定义,方便使用
#define LOG_INFO(msg) Logger::getInstance().log(Logger::Level::INFO, msg)
#define LOG_WARNING(msg) Logger::getInstance().log(Logger::Level::WARNING, msg)
#define LOG_ERROR(msg) Logger::getInstance().log(Logger::Level::ERROR, msg)


#endif //LOGDEMO_LOGGER_H
相关推荐
禺垣19 分钟前
GBDT算法原理及Python实现
人工智能·python·算法·机器学习·数据挖掘·集成学习
橙子1991101630 分钟前
请简述一下什么是 Kotlin?它有哪些特性?
android·开发语言·kotlin
jiunian_cn1 小时前
【c++】【STL】list详解
数据结构·c++·windows·list·visual studio
虾球xz1 小时前
游戏引擎学习第250天:# 清理DEBUG GUID
c++·学习·游戏引擎
martian6651 小时前
信创系统图形界面开发指南:技术选择与实践详解
开发语言·科技·系统架构·系统安全·创业创新
我命由我123451 小时前
STM32 开发 - stm32f10x.h 头文件(内存映射、寄存器结构体与宏、寄存器位定义、实现点灯案例)
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·嵌入式
xyd陈宇阳1 小时前
嵌入式开发高频面试题全解析:从基础编程到内存操作核心知识点实战
c语言·数据结构·stm32·算法·面试
ghost1431 小时前
C#学习第20天:垃圾回收
开发语言·学习·c#
oioihoii1 小时前
C++23 std::invoke_r:调用可调用 (Callable) 对象 (P2136R3)
开发语言·c++23
一眼青苔2 小时前
conda添加新python版本环境,如何激活和销毁
开发语言·python·conda