0

我有一个读取 csv 文件然后struct用它的参数更新 a 的函数。我希望能够循环遍历结构元素,所以我转向宏。解析 csv 文件的输出是文件行和列的二维字符串数组。要将字符串转换为它们各自的数据类型(当前结构只有intand char*),我在用于循环遍历结构的宏中使用了一个转换宏。

CVT_INT atoi(str)
CVT_STR str

但是,在释放通过解析 csv 文件分配的内存时,如果文件中的字符串在开始或结束时没有组合在一起,就会变得很棘手。

csv[row][col]
string|string|int|string|int
string|string|int|string|int
...

for(int row = 0; row < number_of_rows; row++)
    for(int col = 2; col < number_of_cols; col++)
        free(csv[row][col]) // frees string when row[i][3]

我可以确保所有字符串都位于结构的开头,但我希望它是动态的,并且我不想考虑确保数据类型被分组。

我可以释放由 CVT_INT 转换的分配字符串,但释放 CVT_STR 使用的字符串会导致结构的字符串被释放。我可以想到一种解决方法: 1. 分配新空间 2. 复制旧字符串 3. 释放旧字符串。

CVT_STR strcpy((char*)malloc(sizeof(char)*(1+strlen(str))), str)

但是,在执行上述操作时,无论何时调用它都会导致崩溃,我不明白为什么。谁能给我一个解释和解决它的方法/做同样工作的不同路线?我知道这不是很有效,因此也欢迎提出改进这方面的建议。

另一种可能,我只能释放int. 但是,我无法弄清楚如何在宏中执行此操作,因为它必须返回一个 int。

下面是我调用包含转换宏的循环结构宏的示例。

#define STRUCT(type, name, converter) \
        obj->struct.name = converter(csv[row][col++]);
STRUCT_FIELDS
#undef PLAYER

谢谢你的帮助

更新:

更换

CVT_STR strcpy((char*)malloc(sizeof(char)*(1+strlen(str))), str)

CVT_STR strdup(str)

工作,但我不明白为什么。也许有人可以启发我?

4

2 回答 2

2

您需要添加一个strlen不包含尾随 NUL 字节的内容。

CVT_STR strcpy((char*)malloc((sizeof(char) * strlen(str)) + 1), str)

或者干脆

CVT_STR strcpy((char*)malloc(strlen(str) + 1), str)
于 2013-05-03T19:52:34.837 回答
1

因此,我们有一个可以转换事物的宏:

#define STRUCT(type, name, converter) \
    obj->type.name = converter(csv[row][col++]);    // Guessing `struct` meant `type`?

它被这样调用:

STRUCT(foo, bar, CVT_STR)

现在,如果 CVT_STR 是一个宏,则该宏将直接展开为 STRUCT 宏展开,如下所示:

obj->foo.bar = strdup(csv[row][col++]); 

现在,如果你想逐步完成这个,你会很难,因为它只是将宏作为一个步骤。

相反,我们编写一个函数:

inline char *cvt_str(const char *str)
{
    char *tmp = strdup(str); 
    return tmp;
}

并像这样使用这个函数:

STRUCT(foo, bar, cvt_str)

现在我们可以使用调试器在 cvt_str 中设置断点,并单步执行它以查看哪里出错了。

于 2013-05-03T20:48:49.183 回答