2016-09-07 14 views
1

ファイルからバイナリツリーに単語を挿入しようとしています。挿入機能は、fscanfの後にすべての読み取り文字列を印刷しようとしたときにもファイルを読み取らないときに機能しますそれも動作しますが、ツリーに挿入しようとすると、ファイルの最後の文字列だけが読み込まれます。なぜこれが起こりますか?ファイルから最後の単語だけを読み取るFscanf

while(1){ 

    if(fscanf(f,"%s %d",string,&x)==EOF) 
      break; 

     tree=insert(tree,string,x); 
    } 
+1

挿入する前に 'string'のコピーを作成していません。 'insert'関数はポインタを保存するだけで、すべてのツリーエントリは同じ文字列を指しています。 – Barmar

+0

バグを示す完全なサンプルプログラムを提供して、残りのコードがどのように見えるのか推測しないようにしてください。 –

答えて

1

文字列のコピーを作成せず、ツリーに指定したポインタを格納するだけです。したがって、すべてのツリーエントリには同じ文字列へのポインタが含まれており、fscanfを呼び出すたびに上書きされます。

同じ問題がx引数で発生し、毎回同じポインタを渡しています。値ごとに新しいintを割り当てる必要があります。

while (1) { 
    if (fscanf(f, "%s %d", string, x) == EOF) { 
     break; 
    } 
    char *new_str = malloc(strlen(string)+1); 
    strcpy(new_str, string); 
    int *new_int = malloc(sizeof(*x)); 
    *new_int = *x; 
    tree = insert(tree, new_str, new_int); 
} 
+0

これは常に同じ 'int *'を挿入します。 –

+0

@RolandIlligいいえ、そうではありません。整数は値によって関数に渡されます。 – Barmar

+0

しかし、 'x'は' int'ではなく、 'int *'です。さもなければ、 'fscanf'の呼び出しは未定義の動作を呼び出します。 –

0

あなたのコードは次のようになります。

while (fscanf(f, "%s %d", string, &val) == 2) { 
    char *copy = malloc(strlen(string) + 1); 
    if (copy == NULL) 
     break; 
    strcpy(copy, string); 
    insert(copy, val); 
} 

を両方のフィールドを読み取ることができるかどうかを確認するfscanfのエラー処理を、注意してください。また、valの前に&があることに注意してください。おそらくコンパイラの警告が表示されません。ところで、使用可能なすべてのコンパイラの警告を有効にする必要がありますので、バグを自分で検索する必要はありません。

+0

'insert()'の2番目の引数は 'int *'でなければなりません。 'int'を渡しています。 – Barmar

+0

この場合、 'int'を挿入する方がより合理的ですが、これは質問からは分かりません。 –

+0

木は、どんなタイプのデータも格納できるように設計されているかもしれないので、値は 'void *'になります。 – Barmar

関連する問題