在实际工程中,随着项目越来越大,调试信息的作用也越来越重要。尤其是调试多线程程序时,详细的调试信息能够帮助我们更加快速地定位问题,因为此时存在线程调度,单步调试的意义已经不大。
我们希望调试信息包含文件名、函数名、行号以及我们自行添加的信息,于是可以这样实现:
printf("["__FILE__"][Line: %d][%s]: error happened!n", __LINE__, __func__);
其中,__FILE__, __LINE__, __func__都是C语言的预定义符号,他们都在头文件"stdio.h"中。
__FILE__: 当前源文件名,表示为字符串常量;
__LINE__: 当前行号,表示为十进制整型常量;
__func__: 当前函数名,表示为字符串常量。
这样已经实现了文件名、行号、函数名的打印。那么,我们真的要每次打印都放上这么长一段代码么,有没有更好的实现方式呢?其实我们可以尝试用宏的方式来避免一些重复性的输入,为了方便,甚至可以加一个宏定义,统一控制是否打印:
#include//调试打印开关 #define __DEBUG #ifdef __DEBUG #define info(format, ...) printf("["__FILE__"][Line: %d][%s]: "format"n", __LINE__, __func__, ##__VA_ARGS__) #else #define info(format, ...) #endif int main() { info("error happened!"); return 0; }
嗯,到这里好像差不多了,但是想想,我还能再进一步,我希望我的程序能够像linux终端那样输出五颜六色的东西,我用颜色区分打印信息的重要程度,红色表示错误、黄色表示警告、绿色表示正常信息,这样,就不用大海捞针一般地一行一行分析了。
#include//调试打印开关 #define __DEBUG #ifdef __DEBUG #define normal_info(format, ...) printf("["__FILE__"][Line: %d][%s]: 33[32m"format"33[32;0mn", __LINE__, __func__, ##__VA_ARGS__) #define warning_info(format, ...) printf("["__FILE__"][Line: %d][%s]: 33[33m"format"33[32;0mn", __LINE__, __func__, ##__VA_ARGS__) #define error_info(format, ...) printf("["__FILE__"][Line: %d][%s]: 33[31m"format"33[32;0mn", __LINE__, __func__, ##__VA_ARGS__) #else #define normal_info(format, ...) #define warn_info(format, ...) #define error_info(format, ...) #endif int main(void) { normal_info("green"); warning_info("yellow"); error_info("red"); return 0; }
__VA_ARGS__是C99规范中新增的可变参数的宏,如果可变参数被忽略或者为空,也就是只让printf打印字符串而不打印变量,则## *** 作将使预处理器去除它前面的逗号。
使printf打印带颜色的语法为:
printf("33[字背景颜色;字体颜色m字符串33[0m" );
"33"表示对颜色的调用,与"e"等价,这里我的背景色没有设置,使用的是默认值,字体颜色31、32、33分别表示红、绿、黄,打印完成之后将字体颜色设置为0,即恢复默认值,防止影响后面的打印颜色。
看一看打印效果吧
咦,Windows terminal上的颜色好像不大对劲,换Windows上的控制台看看
这回颜色正了。
其实"stdio.h"中还有一些其他的预定义符号,比如日期、时间等,我们想要也可以加上。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)