Zlog


1 日志打印

  测试时通常需要打印日志来确定整个流程是否按需执行,而完成测试后则是不希望日志仍然被打印出来。

  1. 直接注释与反注释
#include <stdio.h>

void main(){
    printf("starting...\n");

    // TODO

    printf("Process1\n");

    // TODO

    printf("Process2\n");

    // ...

    printf("end\n");
}

  这种方式简单有效,但是完成测试后需要手动将每一行与日志打印相关的代码进行注释,低效、麻烦。

  1. 宏定义
#include <stdio.h>

#define OPEN_LOG 1

void main(){
    #ifdef OPEN_LOG
    printf("starting...\n");
    #endif

    // TODO

    #ifdef OPEN_LOG
    printf("Process1\n");
    #endif

    // TODO

    #ifdef OPEN_LOG
    printf("Process2\n");
    #endif

    // ...

    #ifdef OPEN_LOG
    printf("end\n");
    #endif
}

  这种方式通过将#define OPEN_LOG 1注释与否即可决定日志打印的功能是否开放,但是需要在每一句日志打印开头和结尾各加上一句代码,同样也较为麻烦。

  1. 修改printf()
#include <stdio.h>
#include <stdarg.h>

#define OPEN_LOG 1              // 开放日志打印功能

#define LOG_LEVEL LOG_DEBUG     // 设置日志等级

// 枚举所有日志类型
typedef enum{   
    LOG_DEBUG = 0, 
    LOG_INFO,
    LOG_WARNNING,
    LOG_ERROR,
}E_LOGLEVEL;

// 获取日志类型,返回字符串
char *EM_LOGLevelGet(const int level){
    if(level == LOG_DEBUG){
        return "DEBUG";
    }else if(level == LOG_INFO){
        return "INFO";
    }else if(level == LOG_WARNNING){
        return "WARNING";
    }else if(level == LOG_ERROR){
        return "ERROR";
    }
    return "UNKNOWN";    
}

// 日志打印主函数
void EM_LOG(const int level, const char *fun, const int line, const char *fmt,...){
    #ifdef OPEN_LOG     // 用于日志打印功能的启闭
    va_list arg;
    va_start(arg, fmt); // 实现arg和fmt的链接
    char buf[1 + vsnprintf(NULL, 0, fmt, arg)];
    vsnprintf(buf, sizeof(buf), fmt, arg);
    va_end(arg);
    if(level >= LOG_LEVEL){ // 当日志等级高于设置的等级时才会打印日志
        printf("[%s]  [%s  %d] %s\n", EM_LOGLevelGet(level), fun, line, buf);
    }
    #endif
}

// 宏定义,用系统宏获取日志产生的行号以及函数名
#define EMLog(level, fmt...) EM_LOG(level, __FUNCTION__, __LINE__, fmt)   

int main(void){
    int a = 10, b = 15;
    EMLog(LOG_DEBUG, "app start...");   // 不定参数函数
    return 0;
}

文章作者: Vyron Su
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Vyron Su !