I'm reading records from a CSV file using fgets() to read the file one line at a time, and strtok() to parse the fields in each line. I'm encountering a problem where fgets() overwrites a string that was previously written, in favor of the new string.
Here's an example of what I mean by that:
record.csv (This is the file I'm reading in)
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;
}
When we compile and execute this, it prints out:
Johann
18
Johann
29
"John" in newData[0].name
gets overwritten with "Johann" during the second iteration of the while
loop. Notice however that only the strings get mixed up, but not the integers. I suspect this has to do with fgets
because when I modified the above source to only run fgets
once, the output for "John" was as it should be.
Maybe I'm misusing fgets
(or perhaps my assumption is wrong), but could someone give me some pointers on why the strings are being overwritten with each calls to fgets
?
Second Update: Thank-you very much again to all the commenters and the answerers. Good to know those things which I was not aware of. The source works perfect now.
Do:
or define
name
member aschar name[64];
and then againstrcpy( newData[i].name, token );
withoutmalloc
. The 64 bytes for name can be more or less.You are not copy the string but the pointer to the string.
A very simple way to copy the string, but note that this limit the size of the string at 99 characters.