2017-11-02 28 views
0

ファイルから配列への一連のシングルワード線をロードする必要があります。そのために関数を作成しました。この関数はパラメータとしてchar*** arrをとります。これは文字列の配列へのポインタです。私はメモリを割り当て、次に配列に単語をロードするためにこのループを持っています。C:char *配列の最後の要素すべての配列エントリを書き換えます

i=0; 
FILE *fp = fopen(filename, "r"); 
while(fgets(tok, WORD_BUFFER, fp) != NULL){ 
    (*arr)[i] = tok; 
    printf("Word %d:%s", i, (*dict)[i]); 
    i++; 
} 
//arr is a char***, tok is a char[WORD_BUFFER], and WORD_BUFFER is 50 

私の問題は、これは私が[i]の項目に入力しようとしているものは何でも持つ配列のすべてのエントリを上書きしているように見えるということです。

A 
B 
C 
D 

私は(あるいは単に、後でその関数内)、main関数で配列を印刷するときただし、正しく印刷するようだ:次のようになり、ファイルのための上記のループの出力はので、私はこれを言います私はそれが私のfgetsの使用または(*arr)[i] = tokの割り当てとは何かを持って推測しているが、私はよく分からない

D 
D 
D 
D 

:、それは次のようにプリントアウトされます。 ありがとう!

+2

この文の後に(* arr)[i] = tok;配列のすべての要素は変数tokと同じ値を持ちます –

+0

なぜですか?なぜそれだけでarr [i]がtokの価値を持っているのではないでしょうか? – Jeb

+1

'='演算子を使ってポインタを代入するだけです。 'tok'は、ループ中のすべての繰り返しでファイルに上書きされます。したがって、すべてが 'tok'を指しています。これはファイルから最後に読み込まれた行です。保存する場合は、ループのたびに 'tok'から別の場所にデータを転送する必要があります([strcpy'](https://linux.die.net/man/3/strcpy)。 – yano

答えて

0

あなたのコメントに照らして、単純なchar*配列を使用して何をやっているのか説明しようとします。のは、以下のあなたが持っているとしましょう:

#include <stdio.h> 
#include <string.h> 

int main(void) 
{ 
    int i; 
    char tok[50] = "applesauce"; // tok can contain up to 49 chars plus the NUL terminator 

    char* myCharPtr[20]; // this is an array 20 long where each element is of type char* 

    // All the loop does is store the _address_ of tok at each position in the 
    // myCharPtr array. The _data_ "applesauce" only exists _once_ in memory, 
    // and whatever that address is now fills the contents of myCharPtr. 
    // (technically, "applesauce" exists twice in memory, the string literal 
    // and the char array.. but neither of those places are in myCharPtr) 
    for (i=0; i<20; i++) 
    { 
    myCharPtr[i] = tok; 
    } 

    for (i=0; i<20; i++) 
    { 
    printf("myCharPtr[%d] = %s\n", i, myCharPtr[i]); 
    // prints out "applesauce" for each entry because each entry points to tok. 
    } 

    // Now let's do 

    strcpy(tok, "apples"); // "apples" is smaller than 49, so we aren't overwriting the bounds of the array 

    for (i=0; i<20; i++) 
    { 
    printf("myCharPtr[%d] = %s\n", i, myCharPtr[i]); 
    // prints out "apples" for each entry because the _pointer_ to tok 
    // hasn't changed, but the _data_ in tok has changed. 
    } 

    // To further re-enforce this, you can do 
    printf("address of tok = %p\n", (void*)tok); 
    for (i=0; i<20; i++) 
    { 
    printf("address of myCharPtr[%d] = %p\n", i, (void*)(&myCharPtr[i])); 
    } 
    // the address for tok will match all the addresses in myCharPtr 

    // if you want to actually save/copy the data in tok, then you need to do 
    // something like this 

    char wordList[20][50]; // this can store up to 20 words that are each up 
          // to 49 chars each (must leave 1 byte for NUL termination 
    for (i=0; i<20; i++) 
    { 
    // assume this function populates tok with new data each call, much like fgets 
    // this function would have to ensure it's not writing strings bigger than 49 to tok 
    GetNewContentForTok(tok); 
    strcpy(wordList[i], tok); 
    // now, we are saving the contents of tok each time, not simply copying 
    // its pointer. 
    } 

    for (i=0; i<20; i++) 
    { 
    printf("wordList[%d] = %s\n", i, wordList[i]); 
    // this will print all the strings that were once stored in tok from the previous loop 
    } 

    return 0; 
} 

は、私は一般的にそのくらいの間接が私には混乱得ることができるよう、char***種類を扱う避けるようにしてください。上記の例では配列を使用しましたが、動的に割り当てられたメモリを指すポインタにも同じ原則が適用されます。

関連する問題