实战项目中的脑补能力

  • 实现调试信息 LOG日志打印功能
  • 实现 EXPECT系列封装
  • 实现 COLOR系列封装
  • 使用 __attribute__ 完成函数注册
  • 完善功能:测试框架初养成

实现调试信息 LOG日志打印功能

从理解 LOG 日志功能需求开始

预测处理命令-宏定义

// 定义符号常量:
#define PI 3.1415926
#define MAX_N 10000

// 定义傻瓜表达式
#define MAX(a, b) (a) > (b) ? (a) : (b)
#define S(a, b) a * b

// 定义代码段
#define P(a) {
  printf("%d\n", a);
}

预处理命令-预定义的宏

说明
__DATE__日期:Mmm dd yyyy
__TIME__时间:hh:mm:ss
__LINE__行号
__FILE__文件名
__func__函数名/非标准
__FUNC__函数名/非标准
__PRETTY_FUNCTION__更详细的函数信息/非标准
#include<stdio.h>
int main() {
    printf("__LINE__ = %d\n", __LINE__);
    printf("__FILE__ = %s\n", __FILE__);
    printf("__func__ = %s\n", __func__);
    printf("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
    return 0;
}

//__LINE__ = 3
//__FILE__ = /Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp
//__func__ = main
//__PRETTY_FUNCTION__ = int main()
#include<stdio.h>

// '\' 表示换行符,宏定义只有一行
#define LOG(frm, args...) { \
    printf("\033[0;33m[%s : %s : %d] \033[0m", __FILE__, __func__, __LINE__);\
    printf(frm, ##args);\
    printf("\n");\
}

void test() {
    LOG("hello world");
    return ;
}

int main() {
    LOG("Hello World");
    test();
    return 0;
}
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : main : 16] Hello World
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : test : 11] hello world
#include<stdio.h>

// ## 表示连接的作用
#define CAT(a, b) a##_##b

int main() {
    int kaikeba_var = 9973;
    CAT(kaikeba, var) = 1000;
    LOG("kaikeba_var = %d", kaikeba_var);
    return 0;
}
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : main : 20] kaikeba_var = 1000

开启或关闭日志

  • 第一种方法:设置判断变量
#include<stdio.h>

int log_flag = 1; // 1 输出日志; 0 关闭日志
// '\' 表示换行符,宏定义只有一行
#define LOG(frm, args...) do { \
    if (log_flag == 0) break; \
    printf("\033[0;33m[%s : %s : %d] \033[0m", __FILE__, __func__, __LINE__);\
    printf(frm, ##args);\
    printf("\n");\
} while (0);

void test() {
    LOG("hello world");
    int a = 1, b = 2;
    printf("%d %d\n", a, b);
    return ;
}

int main() {
    LOG("Hello World");
    int a = 1, b = 2;
    test();
    return 0;
}
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : main : 20] Hello World
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : test : 13] hello world
// 1 2
  • 第 2 种方法:删除宏定义,并修改宏定义
#include<stdio.h>

// '\' 表示换行符,宏定义只有一行
#define LOG(frm, args...) do { \
    printf("\033[0;33m[%s : %s : %d] \033[0m", __FILE__, __func__, __LINE__);\
    printf(frm, ##args);\
    printf("\n");\
}

// 删除宏定义,并重新定义宏
#undef LOG
#define LOG(frm, args...) 

void test() {
    LOG("hello world");
    int a = 1, b = 2;
    printf("%d %d\n", a, b);
    return ;
}

int main() {
    LOG("Hello World");
    int a = 1, b = 2;
    test();
    return 0;
}
// 1 2

预处理命令-条件式编译

函数说明
#ifdef DEBUG是否定义了 DEBUG 宏
#ifndef DEBUG是否没定义 DEBUG 宏
#if MAX_N == 5宏 MAX_N是否等于 5
#elif MAX_N == 4否则宏 MAX_N 是否等于 4
#else否则
#endif条件判断结束
  • 第 3 种方法:条件式编译
#include<stdio.h>

#define DEBUG

#ifdef DEBUG
// '\' 表示换行符,宏定义只有一行
#define LOG(frm, args...) {\
    printf("\033[0;33m[%s : %s : %d] \033[0m", __FILE__, __func__, __LINE__);\
    printf(frm, ##args);\
    printf("\n");\
}
#else
#define LOG(frm, args...)
#endif

void test() {
    LOG("hello world");
    int a = 1, b = 2;
    printf("%d %d\n", a, b);
    return ;
}

int main() {
    LOG("Hello World");
    int a = 1, b = 2;
    test();
    return 0;
}
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : main : 24] Hello World
// [/Users/harrytsz/Documents/Workspaces/harrytsz-cpp/ShaoFaBook/main.cpp : test : 17] hello world
// 1 2
//
// Created by harrytsz on 2021/1/4.
//

#ifndef SHAOFABOOK_KTEST_H
#define SHAOFABOOK_KTEST_H

#define EXPECT(a, cmp, b) { \
    if(!((a) cmp (b))) { \
        printf("error\n"); \
    }\
}

#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);

#endif //SHAOFABOOK_KTEST_H

实现 COLOR系列封装

ktest.h

//
// Created by harrytsz on 2021/1/4.
//

#ifndef SHAOFABOOK_KTEST_H
#define SHAOFABOOK_KTEST_H

#define EXPECT(a, cmp, b) { \
    if(!((a) cmp (b))) { \
        printf("error\n"); \
    }\
}

#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);


#define COLOR(msg, code) "\033[0;1;" #code "m" msg "\033[0m"
#define RED(msg) COLOR(msg, 31)
#define GREEN(msg) COLOR(msg, 32)
#define YELLOW(msg) COLOR(msg, 33)
#define BLUE(msg) COLOR(msg, 34)


#endif //SHAOFABOOK_KTEST_H
#include<stdio.h>
#include "ktest.h"

int main() {
    printf("hello world\n");
    printf(RED("hello world\n"));
    printf(GREEN("hello world\n"));
    printf(YELLOW("hello world\n"));
    printf(BLUE("hello world\n"));
    return 0;
}

使用 __attribute__ 完成函数注册功能

#include<stdio.h>

__attribute__((constructor)) void test() {
    printf("test : hello world\n");
    return ;
}

int main() {
    printf("main : hello world\n");
    return 0;
}

// test : hello world
// main : hello world

完善功能:测试框架初养成

//
// Created by harrytsz on 2021/1/4.
//

#ifndef SHAOFABOOK_KTEST_H
#define SHAOFABOOK_KTEST_H

#define EXPECT(a, cmp, b) { \
    __typeof(a) __a = (a), __b = (b); \
    if(!((__a) cmp (__b))) { \
        printf(YELLOW("%s:%d: Failure\n", __FILE__, __LINE__)); \
        printf(YELLOW("Expected: (%s) %s (%s), actual : %d vs %d\n", \
        #a, #cmp, #b, __a, __b)); \
    }\
}

#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);
#define EXPECT_EQ(a, b) EXPECT(a, ==, b);


#define COLOR(msg, code) "\033[0;1;" #code "m" msg "\033[0m"
#define RED(msg) COLOR(msg, 31)
#define GREEN(msg) COLOR(msg, 32)
#define YELLOW(msg) COLOR(msg, 33)
#define BLUE(msg) COLOR(msg, 34)

#define TEST(a, b) \
void kaikeba_##a##_##b(); \
__attribute__((constructor)) \
void reg_##a##_##b() { \
    add_test_func(kaikeba_##a##_##b, #a "." #b); \
} \
void kaikeba_##a##_##b()

struct {
    void (*func)();
    const char *func_name;
} func_arr[100];

int func_cnt = 0;

void add_test_func(void (*func)(), const char *str) {
    func_arr[func_cnt].func = func;
    func_arr[func_cnt].func_name = str;
    func_cnt++;
    return ;
}

int RUN_ALL_TESTS() {
    // 遍历所有的测试用例
    // run each test case
    for(int i = 0; i < func_cnt; i++) {
        printf(GREEN("[     RUN    ]") " %s\n", func_arr[i].func_name);
        func_arr[i].func();
    }
    return 0;
}

#endif //SHAOFABOOK_KTEST_H
Last modification:March 18th, 2021 at 04:17 pm
如果觉得我的文章对你有用,请随意赞赏