C语言根据字符串变量获取/设置结构体成员值
一、背景
在项目中需要根据从数据库中获取的字段与对应的键值付给对应结构体成员上,而c语言中没有类似的反射机制,所以需要实现类似功能。例,从表中查到a = 10,在结构体t中,需要将 t.a = 10。
二、实现
感谢ChatGPT,借助其提示,采用宏形式,共用一份宏描述实现结构体数据类型定义与根据字符串值获得/设置结构体成员值。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 定义结构体成员列表
#define STRUCT_MEMBERS \
MEMBER(int, id) \
MEMBER(float, score) /*分数*/\
MEMBER(char , name[10])/*姓名*/
// 定义结构体
typedef struct {
#define MEMBER(type, name) type name;
STRUCT_MEMBERS
#undef MEMBER
} MyStruct;
// 枚举结构体成员名称
void list_members()
{
#define MEMBER(type, name) printf("%s\n", #name);
STRUCT_MEMBERS
#undef MEMBER
}
// 获得结构体成员指针
void* get_member(const char * key, MyStruct * s)
{
char tmp_str[128];
#define MEMBER(type, name) {\
if(strncmp(key, #name, strlen(key)) == 0)\
{\
if(strlen(key) == strlen(#name))\
return &s->name;\
else\
{\
int index = 0;\
return sscanf(#name, "%[^[][%d]", tmp_str,&index) == 2 ? &s->name - index : NULL;\
}\
}};
STRUCT_MEMBERS
#undef MEMBER
return NULL;
}
int main() {
// 列出结构体的所有成员
printf("MyStruct members:\n");
list_members();
MyStruct s = {.id = 1,.score = 95.5};
strcpy(s.name, "zhangsan");
// 根据字符串获得成员指针
printf("s.name = %s\n", (char *)get_member("name", &s));
return 0;
}
三、结果
四、注意
sscanf(#name, "%[^[][%d]", tmp_str,&index) == 2 ? &s->name - index : NULL;
之所以采用&s->name - index
的形式是为了兼容定义成员为数组时,在上面的例子中,成员name的#name 是 "name[10]“而不是"name”,因此,&s->name就是&s->name[10],需要减掉偏移使其为基地址,sscanf是在解析这个10把它放在index中,%[^[][%d]
是一个正则表达式,来解析数组定义格式的变量,这里再次感谢AI,(/•ิ_•ิ)/ A门!