以前存储的字符串被 fgets 覆盖
Previously stored strings are overwritten by fgets
我正在从 CSV 文件中读取记录,使用 fgets() 一次读取文件一行,并使用 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
都会覆盖字符串吗?
第二次更新:再次非常感谢所有评论者和回答者。很高兴知道那些我不知道的事情。来源现在完美。
做:
newData[i].name = malloc( strlen( token ) + 1 );
strcpy( newData[i].name, token );
或将 name
成员定义为 char name[64];
,然后在没有 malloc
的情况下再次定义 strcpy( newData[i].name, token );
。 name的64字节可多可少
您复制的不是字符串,而是指向字符串的指针。
一种复制字符串的非常简单的方法,但请注意,这会将字符串的大小限制在 99 个字符。
typedef struct customer {
char name[100];
int age;
} Customer;
strcpy(newData[i].name, token);
我正在从 CSV 文件中读取记录,使用 fgets() 一次读取文件一行,并使用 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
都会覆盖字符串吗?
第二次更新:再次非常感谢所有评论者和回答者。很高兴知道那些我不知道的事情。来源现在完美。
做:
newData[i].name = malloc( strlen( token ) + 1 );
strcpy( newData[i].name, token );
或将 name
成员定义为 char name[64];
,然后在没有 malloc
的情况下再次定义 strcpy( newData[i].name, token );
。 name的64字节可多可少
您复制的不是字符串,而是指向字符串的指针。
一种复制字符串的非常简单的方法,但请注意,这会将字符串的大小限制在 99 个字符。
typedef struct customer {
char name[100];
int age;
} Customer;
strcpy(newData[i].name, token);