【问题标题】:C: is it possible to associate a pointer to a structure member?C:是否可以将指针关联到结构成员?
【发布时间】:2015-02-13 07:08:34
【问题描述】:

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

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

然后创建了这样一个数组,将某些东西映射到前 2 个值:

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++?魔法?黑魔法?

谢谢。

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

【问题讨论】:

  • .storage = &amp;person[i] 这不符合您的目的。将结构的地址传递给 void 指针?并有tsave person[num];数组
  • 这意味着我需要有针对年龄和身高的特定功能,不是吗?我在想也许有一种方法可以避免这种情况,并对所有整数使用相同的函数,只知道将结果放在哪里?!
  • 函数有什么用?如果您尝试更新单个 API 中的值,那么此分配应该足够好,因为您拥有结构的地址..
  • 我必须道歉,我已经对我首先写的内容​​进行了一些更正。我的意思是年龄和身高使用相同的函数te_atoi。

标签: c struct mapping


【解决方案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;
}

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

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

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

【讨论】:

  • 它确实很有魅力,谢谢。可悲的是,由于时间限制和缺乏知识,我不得不用双指针来实现它,但现在我回来放弃了这些。非常感谢您所做的一切!
猜你喜欢
  • 2021-06-15
  • 2016-01-26
  • 2020-11-22
  • 2017-07-27
  • 1970-01-01
  • 2020-02-16
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多