私はCSVファイルからfgets()を使って一度に1行ずつファイルを読み込み、strtok()を使って各行のフィールドを解析しています。私はfgets()が以前に書かれた文字列を新しい文字列のために上書きするという問題に直面しています。
は、ここで私はそれによって何を意味するかの例です:
以前に格納された文字列は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
while
ループの2回目の繰り返しで、 "Johann"で "012"のnewData[0].name
が上書きされます。ただし、文字列だけが混ざり合っていますが、整数は混同されません。私はこれがfgets
と関係していると考えています。上記のソースをfgets
に一度だけ変更すると、 "John"の出力が1つになるはずです。
多分私はfgets
(またはおそらく私の仮定は間違っています)を誤用していますが、誰かが私にfgets
の各呼び出しで文字列が上書きされている理由のいくつかのポインタを教えてくれますか?
2回目の更新:すべてのコメント作成者と回答者に感謝します。私が気づいていなかったことを知って良かった。ソースは今完璧に動作します。
それぞれの行を同じ変数 'line'でコピーします。 'strtok'が見つけたデータのコピーを作成しません。それが上書きが起こる方法です。スペースを割り当て、 'strdup()'を使ってデータをコピーしてください。 Cは文字列用のメモリを管理しません。あなたはそれを自分で行う必要があります。 –
@xing、ohh、 'newData [i] .name'のメモリは、ヒープ内で手動で割り当てる必要がありますか?私はそれを知らなかった。ありがとう、私はそれを試してみましょう。 @JonathanLefflerだから 'newData [i] .name = token'はデータをコピーしないのですか? – ctatton
あなたは 'newData [i] .name = token;'これを 'newData [i] .name = strdup(token);'に変更することで、名前のメモリを割り当てることができます。 – bruceg