2017-06-27 8 views
-1

私は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回目の更新:すべてのコメント作成者と回答者に感謝します。私が気づいていなかったことを知って良かった。ソースは今完璧に動作します。

+3

それぞれの行を同じ変数 'line'でコピーします。 'strtok'が見つけたデータのコピーを作成しません。それが上書きが起こる方法です。スペースを割り当て、 'strdup()'を使ってデータをコピーしてください。 Cは文字列用のメモリを管理しません。あなたはそれを自分で行う必要があります。 –

+0

@xing、ohh、 'newData [i] .name'のメモリは、ヒープ内で手動で割り当てる必要がありますか?私はそれを知らなかった。ありがとう、私はそれを試してみましょう。 @JonathanLefflerだから 'newData [i] .name = token'はデータをコピーしないのですか? – ctatton

+1

あなたは 'newData [i] .name = token;'これを 'newData [i] .name = strdup(token);'に変更することで、名前のメモリを割り当てることができます。 – bruceg

答えて

1

文字列を指すのではなく、文字列のポインタをコピーします。

文字列をコピーする非常に簡単な方法ですが、文字列のサイズは99文字に制限されています。

typedef struct customer { 
    char name[100]; 
    int age; 
} Customer; 

strcpy(newData[i].name, token); 
1

の操作を行います。

newData[i].name = malloc(strlen(token) + 1); 
strcpy(newData[i].name, token); 

またはmallocずに再びchar name[64];strcpy(newData[i].name, token);としてnameメンバーを定義します。名前の64バイトは多かれ少なかれです。

関連する問題