我有一个函数读取csv文件,然后使用它的参数更新struct
。
我希望能够遍历一个结构元素,所以我转向了宏。解析csv文件的输出是文件行和列的二维字符串数组。要将字符串转换为各自的数据类型(目前结构只有int
和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使用的字符串将导致释放struct的字符串。我能想到一个解决方法: 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)
工作,但我不明白为什么。也许有人可以启发我?
答案 0 :(得分:2)
您需要向strlen
添加一个不包含尾随NUL字节的内容。
CVT_STR strcpy((char*)malloc((sizeof(char) * strlen(str)) + 1), str)
或只是
CVT_STR strcpy((char*)malloc(strlen(str) + 1), str)
答案 1 :(得分: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中设置一个断点,并逐步查看它以查看它出错的地方。