C:是否可以将指针关联到结构成员?

时间:2015-02-12 12:06:15

标签: c struct mapping

我想创建类似于映射数组的东西,以便将来开发某些模块。我们的想法是拥有一个由外部函数执行的字符串,该函数总是返回一个字符串,结果需要解析为正确的格式,然后将其存储在结构的特定成员()中。使用特定的功能很容易做到这一点,但我想使用一些更通用的方法和功能,如atoi(或它的重新创建版本),如果可能的可移植性和未来快速实现的东西。 我创建了以下结构来保存这样的映射数据:

typedef struct sMapping
{
    const char *string;
    int (* function)();
    void *storage;
} tMapping;

然后创建了一个映射到前两个值的数组:

tMapping mapTest[]={
    { .string = "name", .function = te_strcpy},
    { .string = "age", .function = te_atoi},
    { .string = "location", .function = te_parse},
    { .string = "height", .function = te_atoi}
};

我想在代码中使用的内容类似于以下内容:

char *outputstr = NULL;
for(i = 0; i<MAX_LEAFS; i++)
{
    if(mapTest[i].string == NULL)
        break;

    outputstr = fct_lookup_option_string(mapTest[i].string);
    mapTest[i].function(outputstr);
}

到目前为止一切正常,一切都被解析得非常好。请注意,te_atoi函数提取了2个变量。

现在,如果我有另一个结构,如

typedef struct sSave
{
    char* name;
    int age;
    struct geo *location;
    int height;
} tSave;

tSave person;

并希望将某些内容映射到它

(CODE BELOW IS NOT CORRECT, I KNOW, JUST WANT TO PRESENT MY IDEA BETTER)
tMapping mapTest[]={
    { .string = "name", .function = te_strcpy, .storage= &(person.name)}, 
    { .string = "age", .function = te_atoi, .storage= &(person.age)},
    { .string = "location", .function = te_parse, .storage= &(person.location)},
    { .string = "heigth", .function = te_atoi, .storage= &(person.height)},
};

使用类似

的内容
(CODE BELOW IS NOT CORRECT, I KNOW, JUST WANT TO PRESENT MY IDEA BETTER)
mapTest[i].storage = mapTest[i].function(outputstr);

甚至可能吗?有任何想法吗?双指针? C ++?魔法?黑魔法?

感谢。

请记住,我想将它用作多个模块的通用模板(甚至可能是某些自动化模块),因此特定功能会限制这一点。

1 个答案:

答案 0 :(得分:1)

非常有趣的项目。必须鼓励他们开展工作。

你的想法似乎很好,不需要C ++,但黑魔法可能会有所帮助: - )。

要认真:是的,可以将指针与结构成员相关联。对于char,short,int和long,我认为你做的方式是可以的。

对于字符串和结构,解析器必须分配内存。对于字符串,用te_strdup替换te_strcpy应该这样做。

对于结构体,它有点复杂:您必须告诉解析器结构的大小以进行内存分配,并描述结构的内容以便正确填充它。 为此,一个解决方案可能是在tMapping结构中添加这些信息:

typedef struct sMapping
{
    const char *string;
    int (*function)(char*, void*);
    void *functionParam; // for a te_parse function this param could be a struct containing a tMapping array and a target struct to fill
    void *storage;
} tMapping;

mapTest数组变为:

tMapping mapTest[]={
    { .string = "name", .function = te_strdup, .storage= &(person.name)}, 
    { .string = "age", .function = te_atoi, .storage= &(person.age)},
    { .string = "location", .function = te_parse, .functionParam=sMapGeo, .storage= &(person.location)},
    { .string = "height", .function = te_atoi, .storage= &(person.height)},
};

要拥有通用的te_parse函数,sMapGeo结构可以是:

(THIS CODE WON'T WORK AS IS, BUT IT EXPLAINS THE IDEA)
 struct {
    void *structToFill = &saveGeo;
    int structSize = sizeof(saveGeo);
    tMapping mapStruct[] = 
    { .string="city", .function=te_strdup, .storage=&(saveGeo.city)}
    etc.
 } sMapGeo;

然后te_parse函数应该如下所示:

void *te_parse(char *input, tParseMap *sMap)
{
    applyMapping(sMap->mapStruct); //apply the mapping like the main mapping
    char *mem = malloc(sMap->structSize);
    memcpy(mem, sMap->structToFill, sMap->structSize));
    return mem;
}

最后一件小事。由于存储是一个指针,不要忘记*为指向的内容赋值:

*mapTest[i].storage = mapTest[i].function(outputstr, mapTest[i].functionParam);

毕竟,处理浮点数,双精度数组,数组甚至使代码与32位和64位架构兼容是另一回事!