当前位置: 首页 > article >正文

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门!


http://www.kler.cn/a/414800.html

相关文章:

  • Docker pull镜像拉取失败
  • 【Linux打怪升级记 | 报错02】-bash: 警告:setlocale: LC_TIME: 无法改变区域选项 (zh_CN.UTF-8)
  • 简单好用的折线图绘制!
  • AI潮汐日报1128期:Sora泄露引发争议、百度早期研究对AI领域Scaling Law的贡献、Meta发布系列AI开源项目
  • shell脚本基础学习_总结篇(完结)
  • Unity3D 截图
  • c++基础开发环境vscode+mingw-w64
  • 【Oracle11g SQL详解】WHERE 子句的条件筛选及常用操作符
  • Seata使用ZooKeeper作为注册中心
  • 【面向对象的程序设计——集合框架】主要接口
  • java charAt()返回数值型 详解
  • python之Flask入门—路由参数
  • 从数据孤岛到数据协同:企业如何构建安全的数据共享生态?
  • php 导出excel 带图片
  • 基于Matlab的图像去噪算法仿真
  • 用 llama.cpp 体验 Meta 的 Llama AI 模型
  • 软件工程头歌实训作业:Junit实训入门篇
  • 一个高效的Java对象映射库Orika
  • SpringBoot 接口加密SM2非对称加密算法 国密算法 公钥加密 私钥解密
  • 使用Alpine镜像作为基础镜像的Dockerfile配置
  • 154. tweenjs相机运动动画
  • sqlmap使用过程中的每个步骤及其相关命令
  • 3D格式转换工具HOOPS Exchange如何保证不同CAD数据准确性和一致性?
  • js:函数
  • 【Db First】.NET开源 ORM 框架 SqlSugar 系列
  • Github 2024-11-28 Go开源项目日报Top10