我想创建类似于映射数组的东西,以便将来开发某些模块。我们的想法是拥有一个由外部函数执行的字符串,该函数总是返回一个字符串,结果需要解析为正确的格式,然后将其存储在结构的特定成员()中。使用特定的功能很容易做到这一点,但我想使用一些更通用的方法和功能,如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 ++?魔法?黑魔法?
感谢。
请记住,我想将它用作多个模块的通用模板(甚至可能是某些自动化模块),因此特定功能会限制这一点。
答案 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位架构兼容是另一回事!