【发布时间】:2017-06-27 22:14:41
【问题描述】:
我正在使用 fgets() 从 CSV 文件中读取记录,一次读取一行,使用 strtok() 解析每一行中的字段。我遇到了一个问题,其中 fgets() 覆盖了以前编写的字符串,有利于新字符串。
这是我的意思的一个例子:
record.csv(这是我正在阅读的文件)
John,18
Johann,29
main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct customer {
char *name;
int age;
} Customer;
int main(void)
{
FILE *csv_data;
char line[100], *token;
Customer newData[2];
csv_data = fopen("record.csv", "r");
// Index 0 for John's data, index 1 for Johann's data
int i = 0;
/* loops until end of file */
while(fgets(line, 100, csv_data)) {
/* name field */
token = strtok(line, ",");
if (token != NULL) {
newData[i].name = token;
}
/* age field */
token = strtok(NULL, ",");
if (token != NULL) {
// atoi() converts ascii char to integer
newData[i].age = atoi(token);
}
i++;
}
/* print John's records */
printf("%s\n", newData[0].name);
printf("%d\n", newData[0].age);
/* print Johann's records */
printf("%s\n", newData[1].name);
printf("%d\n", newData[1].age);
return 0;
}
当我们编译并执行它时,它会打印出来:
Johann
18
Johann
29
newData[0].name 中的“John”在while 循环的第二次迭代中被“Johann”覆盖。但是请注意,只有字符串会混淆,而整数不会。我怀疑这与fgets 有关,因为当我将上述源代码修改为仅运行fgets 一次时,“John”的输出应该是这样。
也许我在滥用fgets(或者我的假设是错误的),但是有人可以给我一些关于为什么每次调用fgets 都会覆盖字符串的指针吗?
第二次更新:再次感谢所有评论者和回答者。很高兴知道我不知道的那些事情。源代码现在完美运行。
【问题讨论】:
-
你将每一行复制到同一个变量
line;您不会复制strtok找到的数据。这就是覆盖发生的方式。分配空间并复制数据,可能使用strdup()。 C 不会为您管理字符串的内存;你必须自己做。 -
@xing,哦,
newData[i].name的内存必须在堆中手动分配?我没有意识到这一点。谢谢,我试试。 @JonathanLeffler 所以newData[i].name = token不会复制数据? -
您可以通过将这个:
newData[i].name = token;更改为这个:newData[i].name = strdup(token);来为名称分配内存。 -
谢谢@bruceg。是的,我实现了
strdup,它按预期复制了字符串。