gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-05 01:31:18 25 4
gpt4 key购买 nike

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

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 导致十六进制内存地址转换为整数,而不是它指向的字符串。

// 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++;

对于任何给定的属性名称(例如att),您会得到:

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

除了它都在一条线上。但是,关键是您要么将 int(来自 atoi())分配给字符串,要么将字符串分配给 int在每次调用中,这两个调用中的一个是错误的。代码在优化之前必须是正确的。

如何解决?这很棘手。我想我可能会使用这样的东西:

#include <stdlib.h>

#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 <stdlib.h>

#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
}

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

关于c - 循环遍历并将数据分配给结构成员的宏错误地将结构成员识别为指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15983496/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com