简介
突然想玩一玩,能不能用printf实现slf4j里 的log.xxx 的效果。
性能是完全不考虑的,只要功能可用就好。
期待的效果
类似:info("这是第{}条日志",index);
颜色
一个好的日志打印,应当有对应的颜色。直接抄springboot 对应日志的默认配色。
遇到的问题
尝试使用c中的可变参数去实现,但是发现,可变是可变了,却不知道数据的类型。
而不知道数据的类型,printf 就没法打印。如果强行当做%s打印,那么解析铁定出错,因为它要找\0作为结束标签。
目前暂时没有找到办法,那就只能保留这个输出格式符,但是不要前面的%号。
比较,从键盘上看% 离的还挺远,不好找,可读性也比较差。
实际的效果
类似:info("这是第{d}条日志",index);
代码实现
util.h
#pragma once
void trace(const char * str, ...);
void debug(const char * str, ...);
void info(const char * str, ...);
void warn(const char * str, ...);
void error(const char * str, ...);
util.c
#include"util.h"
#include<stdio.h>
#include<stdarg.h>
#include<string.h>
#define ANSI_COLOR_RED "\033[31m"
#define ANSI_COLOR_GREEN "\033[32m"
#define ANSI_COLOR_YELLOW "\033[33m"
#define ANSI_COLOR_BLUE "\033[34m"
#define ANSI_COLOR_MAGENTA "\033[35m"
#define ANSI_COLOR_CYAN "\033[36m"
#define ANSI_COLOR_RESET "\033[0m"
void resolveAndPrint(va_list args, const char * str);
/*
带颜色的打印
*/
void printC(const char * color, const char * tag) {
printf("%s%s%s", color, tag, ANSI_COLOR_RESET);
}
void trace(const char * str, ...) {
printC(ANSI_COLOR_YELLOW, " [ TRACE ]: ");
//声明
va_list args;
//初始化
va_start(args, str);
//执行遍历
resolveAndPrint(args, str);
va_end(args);
}
void debug(const char * str, ...) {
printC(ANSI_COLOR_YELLOW, " [ DEEBUG ]: ");
//声明
va_list args;
//初始化
va_start(args, str);
//执行遍历
resolveAndPrint(args, str);
//清理
va_end(args);
}
void info(const char * str, ...) {
printC(ANSI_COLOR_CYAN, " [ INFO ]: ");
//声明
va_list args;
//初始化
va_start(args, str);
//执行遍历
resolveAndPrint(args, str);
//清理
va_end(args);
}
void warn(const char * str, ...) {
printC(ANSI_COLOR_MAGENTA, " [ WARN ]: ");
//声明
va_list args;
//初始化
va_start(args, str);
//执行遍历
resolveAndPrint(args, str);
//清理
va_end(args);
}
void error(const char * str, ...) {
printC(ANSI_COLOR_RED, " [ ERROR ]: ");
//声明
va_list args;
//初始化
va_start(args, str);
//执行遍历
resolveAndPrint(args, str);
//清理
va_end(args);
}
void resolveAndPrint(va_list args, const char * str) {
char * ch = str;
char lastCh = 0;
while (*ch != '\0')
{
if ((lastCh != '\\') && (*ch == '{' || *ch == '}'))
{
lastCh = *ch;
ch++;
//跳过即可
continue;
}
//匹配到类似 \\{ \\t \\n 这种,就直接输出原意
if ((lastCh == '\\'))
{
printf("%c", *ch);
lastCh = *ch;
ch++;
continue;
}
if (*ch == '\\')
{
lastCh = *ch;
ch++;
continue;
}
if (lastCh == '{') {
//开始匹配参数了
char symbol = *ch;
//printf("symbol=%c \n", symbol);
switch (symbol)
{
case 's':
printf("%s", va_arg(args, char *));
break;
case 'c':
printf("%c", va_arg(args, char));
break;
case 'd':
printf("%d", va_arg(args, int));
break;
case 'f':
printf("%.2f", va_arg(args, double));
break;
default:
printf("%c", symbol);
break;
}
}
else
{
printf("%c", *ch);
}
lastCh = *ch;
ch++;
}
printf("\n");
}
使用
main.c
#include<stdio.h>
#include"util.h"
int main() {
trace("小明今年{d}岁了 \\{\\} {s}给他祝贺,送了字母{c},体重{f}", 3,"小红",'B',57.3);
debug("hhhh");
info("hhhh");
warn("hhhh");
error("hhhh");
return 0;
}