Je lis les enregistrements d'un fichier CSV en utilisant fgets() pour lire le fichier une ligne à la fois, et strtok() pour analyser les champs de chaque ligne. Je rencontre un problème où fgets() écrase une chaîne qui a été précédemment écrite, en faveur de la nouvelle chaîne.
Voici un exemple de ce que je veux dire par là:
Les chaînes stockées précédemment sont remplacées par des fgets
record.csv (Ceci est le fichier que je lis dans)
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;
}
Lorsque nous compilons et exécutons ceci, il imprime:
Johann
18
Johann
29
"John" dans newData[0].name
est remplacé par "Johann" lors de la deuxième itération de la boucle while
. Notez cependant que seules les chaînes sont mélangées, mais pas les entiers. Je suppose que cela a à voir avec fgets
parce que quand j'ai modifié la source ci-dessus pour exécuter seulement fgets
une fois, la sortie pour "John" était comme il se doit. Peut-être que j'utilise abusivement fgets
(ou peut-être mon hypothèse est erronée), mais quelqu'un pourrait-il me donner des indications sur la raison pour laquelle les chaînes sont remplacées avec chaque appel à fgets
?
Deuxième mise à jour: Merci encore beaucoup à tous les commentateurs et les répondeurs. Bon à savoir ces choses dont je n'étais pas au courant. La source fonctionne parfaitement maintenant.
Vous copiez chaque ligne sur la même variable 'line'; vous ne faites pas de copie des données trouvées par 'strtok'. Voilà comment l'écrasement se produit. Allouer de l'espace et copier les données, en utilisant peut-être 'strdup()'. C ne gère pas la mémoire pour les chaînes pour vous; vous devez le faire pour vous-même. –
@xing, ohh, la mémoire de 'newData [i] .name' doit-elle être allouée manuellement dans le tas? Je n'étais pas au courant de ça. Merci, je vais essayer. @JonathanLeffler so 'newData [i] .name = token' ne copie pas les données? – ctatton
vous pouvez allouer de la mémoire pour le nom en changeant ceci: 'newData [i] .name = token;' à ceci: 'newData [i] .name = strdup (token);'. – bruceg