循环并将数据分配给结构成员的宏错误地将结构成员识别为指针

我的问题是atoi正在将字符串的hex内存地址转换为十进制,而不是字符串中包含的内容。 它是在宏中执行此操作。 当宏定义使它成为int时,为什么将struct-> member解释为指针? 下面的伪代码:

if (struct.member == int)? struct.member = atoi(data) : struct.member = data; 

该程序的这一部分的目的是从包含有关结构属性的信息的.csv文件中检索数据。 我可以接受一个“id”并将每个单元格字符串存储到一个字符串数组(csvRowSplit)中。

但是,我想将数组的内容传输到包含不同数据类型的结构(我想用来检索玩家保存的属性,攻击方法,商店物品等的方法)。 硬编码很容易:

 opponent->att = atoi(csvSplitRow[0]); opponent->= atoi(csvSplitRow[1]); opponent->hitpoints = atoi(csvSplitRow[2]); opponent->description = csvSplitRow[3]); 

然而,这种结构成分更多,并且不是非常灵活或可重复。

我已经定义了一个宏来循环遍历结构的元素,并将csvSplitRow []与变量配对,如果需要转换为atoi。

 #define X_FIELDS \ X(char*, description, "%s") \ X(int, xpreward, "%d") \ X(int, att, "%d") \ /* ... */ X(int, crit, "%d") typedef struct { #define X(type, name, format) type name; X_FIELDS #undef } void update_opp(char** csvSplitRow, opp* opponent) { int i = 0; #define X(type, name, format) \ if (strcmp(format, "%d") == 0) \ // if an int, convert it opponent->name = atoi(csvSplitRow[i]); \ else \ // otherwise put it straight in opponent->name = csvSplitRow[i]; \ i++; X_FIELDS #undef X } 

直接赋予字符串成员的工作(即没有转换),但是atoi导致hex内存地址转换为整数,而不是它指向的字符串。

 // before conversion csvRowSplit[1] == 0x501150 "20" // practice atoi(csvRowSplit[1]) == 20 // after conversion and storing in struct int member opponent->xpreward = atoi(csvSplitRow[1]); opponent->xpreward == 5247312 // the decimal equivalent of 0x501150 

我不知道我现在能做什么,除了硬编码,每次我想要将一个解析过的csv与一个结构相匹配。 请帮忙!

编辑:我用-Werror得到编译时错误:

 error: assignment makes integer from pointer without a cast [-Werror] 

错误在update_opp函数的宏内。 但是,我知道它不是指针,因为我之前将它定义为int? 那么为什么不承认呢? 我不能施展它,所以我该怎么办?

您的问题在于此代码:

 #define X(type, name, format) \ if (strcmp(format, "%d") == 0) \ // if an int, convert it opponent->name = atoi(csvSplitRow[i]); \ else \ // otherwise put it straight in opponent->name = csvSplitRow[i]; \ i++; 

对于任何给定的属性名称(如果说),您将得到:

  if (strcmp("%d", "%d") == 0) opponent->att = atoi(csvSplitRow[i]); else opponent->att = csvSplitRow[i]; i++; 

除了它全部在一条线上。 但是,关键是要么将int (从atoi() )分配给字符串,要么在每次调用时将字符串赋值给int ,其中一个是错误的。 在优化之前,代码必须是正确的。

怎么修? 这很棘手。 我想我可能会使用这样的东西:

 #include  #define CVT_INT(str) atoi(str) #define CVT_STR(str) str #define X_FIELDS \ X(char*, description, "%s", CVT_STR) \ X(int, xpreward, "%d", CVT_INT) \ X(int, att, "%d", CVT_INT) \ /* ... */ \ X(int, crit, "%d", CVT_INT) typedef struct opp { #define X(type, name, format, converter) type name; X_FIELDS #undef X } opp; extern void update_opp(char** csvSplitRow, opp* opponent); void update_opp(char** csvSplitRow, opp* opponent) { int i = 0; #define X(type, name, format, converter) \ opponent->name = converter(csvSplitRow[i++]); X_FIELDS #undef X } 

在非常严格的编译器标志下编译时没有警告:

 gcc -pedantic -g -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \ -Wold-style-definition -c xm.c 

当需要执行其他操作时,可以重新定义CVT_INTCVT_STR宏。


替代版本的代码更广泛地利用了CVT_INTCVT_STR (重命名为X_INTX_STR ):

 #include  #define X_FIELDS \ X(X_STR, description) \ X(X_INT, xpreward) \ X(X_INT, att) \ /* ... */ \ X(X_INT, crit) typedef struct opp { #define X_INT char * #define X_STR int #define X(code, name) code name; X_FIELDS #undef X #undef X_INT #undef X_STR } opp; extern void update_opp(char** csvSplitRow, opp* opponent); void update_opp(char** csvSplitRow, opp* opponent) { int i = 0; #define X_INT(str) atoi(str) #define X_STR(str) str #define X(converter, name) \ opponent->name = converter(csvSplitRow[i++]); X_FIELDS #undef X #undef X_INT #undef X_STR } 

由于多个#define#undef操作,我并不是100%确信它更好,但在某些方面它更接近最小(例如它不需要"%d" vs "%s"字段,例如 – 至少,不在显示的代码中)。