实战项目中的脑补能力
- 实现调试信息 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