C及C++不定参数log输出方法(printf风格)
一.C语言方式
1.宏定义
#define LOG(fmt, ...) printf("[%s,%s,line=%d,%s %s] " fmt "\r\n", __FILE__, __func__, __LINE__, __DATE__,__TIME__, ##__VA_ARGS__)
宏名称:
LOG - 这是宏的标识符,用于在代码中调用日志功能。
参数:
fmt - 格式化字符串,类似于printf的第一个参数。
... - 可变参数列表,允许传递任意数量的额外参数。
输出格式:
[文件名,函数名,行号,日期 时间] 消息内容
2.代码示例
#include <stdio.h>
#define LOG(fmt, ...) printf("[%s,%s,line=%d,%s %s] " fmt "\r\n", __FILE__, __func__, __LINE__, __DATE__,__TIME__, ##__VA_ARGS__)
int main()
{
int value = 0;
LOG("hello");
LOG("程序启动,值为 %d\n", value);
}
输出内容:
[D:\30.VS\frm\frm.cpp,main,line=15,May 16 2025 15:56:03] hello
[D:\30.VS\frm\frm.cpp,main,line=16,May 16 2025 15:56:03] 程序启动,值为 0
二.C++方式
1.C++11引入了变参模板(template<typename... Args>),使得我们能够创建接受不定个数模板参数的模板。
template<typename T,typename ...Args>
AI写代码
T代表一个任意类型的参数,...Args代表可变参数
2.代码示例
#include <iostream>
void Printf()
{
std::cout << std::endl;
}
template<typename T, typename ...Args>
void Printf(const T& v, Args && ...args)
{
std::cout << v;
if (sizeof ...(args) > 0)
{
Printf(std::forward<Args>(args)...);
}
else
{
Printf();
}
}
int main()
{
Printf("开始A");
Printf("开始A", "开始B");
Printf("开始", "开始", 123ABC);
}
输出内容:
开始A
开始A开始B
开始开始123
3.如果你编写代码的c++版本为C++17及以上,你可以使用下面这段代码简化操作:
template<typename... Args>
void Printf(Args&&... args) {
(std::cout << ... << args) << std::endl;
}
三.frm库方式
1.fmtlib(简称 fmt)是一个现代化的 C++ 格式化库,提供了安全、高效且易用的字符串格式化功能。它被设计为 C++ 标准库 std::format(C++20 引入)的基础实现,并且在性能和功能上超越了传统的 printf 和 iostream。
注意:c++20以前的版本要单独安装,且性能不如C++20版本
性能对比:
2.字符串格式化示例
#include <fmt/core.h>
std::string message = fmt::format("Hello, {}! You have {} messages.", "Alice", 3);
// 输出:Hello, Alice! You have 3 messages.