2017-11-02 12 views
0

Ich muss eine Reihe von einzelnen Wortleitungen aus einer Datei in ein Array laden, also habe ich eine Funktion dafür gemacht. Die Funktion nimmt char*** arr als Parameter, der ein Zeiger auf das Array von Zeichenfolgen ist. Ich reserviere Speicher und habe dann diese Schleife, um Wörter in das Array zu laden.C: Letztes Element in char * Array überschreibt alle Array-Einträge

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 

Mein Problem ist, dass diese mit jedem Eintrag des Arrays zu sein scheinen zu überschreiben, was ich versuche zu Eintrag eingeben [i]. Ich sage das, weil der Ausgang der Schleife oben für eine Datei, die etwa wie folgt aussieht:

A 
B 
C 
D 

scheint richtig zu drucken, aber wenn ich das Array in der Hauptfunktion drucken (oder auch nur später in dieser Funktion) , druckt es aus wie:

D 
D 
D 
D 

ich vermute, es hat etwas mit meiner Verwendung von fgets oder der Zuordnung von (*arr)[i] = tok aber ich bin nicht sicher, zu tun. Danke!

+2

Nach dieser Aussage (* arr) [i] = tok; Alle Elemente des Arrays haben den gleichen Wert der Variablen tok, –

+0

Warum ist das? Warum sollte es nicht nur den Wert von Tok ausmachen? – Jeb

+1

Sie tun nur eine Zeigerzuweisung mit dem Operator '='. 'tok' wird mit jeder Datei überschrieben, die sich in der Schleife befindet. Also zeigt alles auf 'tok', was die letzte aus der Datei gelesene Zeile ist. Sie müssen ['strcpy'] (https://linux.die.net/man/3/strcpy) die Daten von' tok' zu einem anderen Ziel jedes Mal durch die Schleife, wenn Sie es speichern möchten. – yano

Antwort

0

In Anbetracht Ihres Kommentars werde ich versuchen zu erklären, was Sie tun, mit einem einfachen char* Array. Angenommen, Sie haben die folgende:

#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; 
} 

ich in der Regel mit char*** Arten zu vermeiden, versuchen zu tun, wie viel indirection verwirrend für mich zu bekommen. Ich habe in meinem obigen Beispiel Arrays verwendet, aber die gleichen Prinzipien würden auch für Zeiger gelten, die auf dynamisch zugewiesenen Speicher zeigen.