这个模板功能只针对char *,int,double生效,如果你想要实现别的数据类型,甚至自定义类型,可以自行修改功能,或者做个接口出来,这套代码因为我自己用,所以模板写地非常简单,没有任何复杂的功能。
首先我们将char *进行一个宏定义,因为直接用指针看起来总是感觉很麻烦的样子。
#define string char *
现在我们可以愉快地开始进行模板制作的功能了,我这里因为自己需要,还将所有数据类型做成了链表结点,如下。
// 创建基本的数据结构体
#define CREATE_BASE_DATA_STRUCT(TYPE) \
typedef struct \
{ \
TYPE data; \
struct TYPE##_data *next; \
} TYPE##_data;
当然,为了偷懒,宏定义必须要跟上,于是有了一下两个宏定义
#define DO_FOREACH_TYPE(function) function(string) function(int) function(double) // 为三个基本类型进行相同操作
#define DO_FOREACH_STRUCT_TYPE(function) function(string_data) function(int_data) function(double_data) // 为三个结构体类型进行相同操作
第一个宏定义是为了基础的三个基础的数据类型使用的,旨在让三种类型进行相同操作,第二种则是为了所有被做成结点的数据类型使用的。
同时我定义了如下结构体
typedef struct
{
DO_FOREACH_STRUCT_TYPE(CREATE_BASE_DATA_LINK_LIST) // 创建三个基本结构体数据链表
string name; // 角色姓名
string ID; // 角色ID
string comment; // 角色备注
Status status; // 角色状态
} Role;
其中创建链表的宏如下
// 创建基本的数据链表
#define CREATE_BASE_DATA_LINK_LIST(TYPE) \
TYPE *TYPE##_HEAD;
到这里我们可以开始创建我们的模板功能了,首先我们先用宏定义写一个基本的查找函数
#define FIND_TYPE_DATA(TYPE) \
int Find_##TYPE##_Data(Role *role, TYPE data) \
{ \
TYPE##_data *p = role->TYPE##_data_HEAD; \
while (p != NULL) \
{ \
if (!memcmp(&p->data, &data, sizeof(p->data))) \
{ \
return 1; \
} \
p = p->next; \
} \
return 0; \
}
然后结合前面我们的DO_FOREACH_TYPE这个宏,我们就可以这么做
DO_FOREACH_TYPE(FIND_TYPE_DATA)
至此,模板功能实现,一行代码创造出三个基本的查询函数,最后这个宏定义展开后如下。
int Find_string_Data(Role *role, char *data)
{
string_data *p = role->string_data_HEAD;
while (p != ((void *)0))
{
if (!memcmp(&p->data, &data, sizeof(p->data)))
{
return 1;
}
p = p->next;
}
return 0;
}
int Find_int_Data(Role *role, int data)
{
int_data *p = role->int_data_HEAD;
while (p != ((void *)0))
{
if (!memcmp(&p->data, &data, sizeof(p->data)))
{
return 1;
}
p = p->next;
}
return 0;
}
int Find_double_Data(Role *role, double data)
{
double_data *p = role->double_data_HEAD;
while (p != ((void *)0))
{
if (!memcmp(&p->data, &data, sizeof(p->data)))
{
return 1;
}
p = p->next;
}
return 0;
}
后面在写代码时候,这三个函数直接调用即可,至此,模板创建结束,代码正常运行。