2016-04-17 12 views
-2

Ich bin eine Textdatei unbekannter Größe gegeben und ich muss es bis zum Ende lesen, berechnen Sie die Anzahl der Wörter, Buchstaben und einige andere Sachen. Um dies zu tun, versuche ich, die gesamte Datei zu lesen und alle Wörter in einem Array zu speichern. Mir wurde gesagt, dass ich dynamische Speicherzuweisung verwenden soll, da ich die Größe der Textdatei vorher nicht kenne.Programm stürzt bei der Verwendung von Realloc

Bevor ich in den Algorithmus zur Berechnung der Wörter und Buchstaben komme, versuche ich, die dynamische Speicherzuweisung zu machen. Dies ist mein Code:

int main(int argc, char *argv[]) { 

    FILE *fp; // file pointer 

    //defining a dynamic string array 

    char **array = malloc(10 * sizeof(char *)); //10 rows for now, will be dynamically changed later 

    int i,size = 10, current = 0; // current points to the position of the next slot to be filled 

    for(i=0; i<10; i++){ 
     array[i] = malloc(20); //the max word size will be 20 characters (char size = 1 byte) 
    } 


    fillArray(fp, array, current, size); 

    return 0; 
} 

ich ein Array von Strings, eine Variable zeigt seine Größe zu definieren, und eine Variable zeigt auf den Schlitz, wo das nächste Element hinzugefügt wird. Die Funktionen sind wie folgt:

int fillArray(FILE *fp, char **p, int ptr, int size){ 

    puts("What's the name of the file (and format) to be accessed?\n (It has to be in the same directory as the program)"); 
    char str[20]; 
    gets(str); //getting the answer 
    fp = fopen((const char *)str, "r"); //opening file 


    int x=0, i=0, j; 

    while(x!=EOF){ // looping till we reach the end of the file 
     printf("current size: %d , next slot: %d\n", size, ptr); 
     if(ptr>=size){ 
      printf("increasing size\n"); 
      addSpace(p, &size); 
     } 
     x = fscanf(fp, "%19s", p[i]); 
     puts(p[i]); 
     i++; 
     ptr++; 
    } 

} 

void addSpace(char **p, int *size){ //remember to pass &size 
    //each time this is called, 10 more rows are added to the array 
    p = realloc(p,*size + 10); 
    int i; 
    for(i=*size; i<(*size)+10; i++){ 
     p[i] = malloc(20); 
    } 
    *size += 10; 
} 

void freeSpace(char **p, int ptr){ 
    //each time this is called, the rows are reduced so that they exactly fit the content 
    p = realloc(p, ptr); //remember that ptr points to the position of the last occupied slot + 1 

} 

Zu Beginn werden die Zeilen des Arrays sind 10. Jedes Mal, wenn die Worte des Textes nicht das Array passen, wird die Funktion addSpace 10 weitere Zeilen hinzugefügt genannt wird. Das Programm läuft 3 Mal erfolgreich (30 Zeilen erreichen) und stürzt dann ab.

Nach der Verwendung von printf, um herauszufinden, wo das Programm abstürzt (weil ich noch nicht an den Debugger gewöhnt bin), scheint es, dass es stürzt beim Versuch, 10 weitere Zeilen (bis 40) hinzuzufügen. Ich kann das Problem nicht lösen oder beheben. Jede Hilfe wird geschätzt.

+1

Wenn Sie 'malloc (20)' ist die maximale Stringlänge ** 19 ** Zeichen; das 20. Zeichen ist das '\ 0'. Außerdem solltest du '* size + 10 * sizeof * p' realloc! –

+0

'addSpace (p, &size);' kann 'p' nicht ändern, was, wenn es ein neu zugewiesener Zeiger ist, ein großes Problem ist :( –

Antwort

2

Klassisch!

Sie übergeben auch einen Doppelzeiger, der realloc d ist, die Adresse hat sich zwischen dem Anrufer und dem Angerufenen geändert.

Auch gibt es ein realloc Problem.

p = realloc(p,*size + 10); 

Wenn realloc ausfällt, der ursprüngliche Zeiger des Speichers Block clobbered.

Der richtige Weg, dies zu tun:

char **tmp_ptr = realloc(p, *size + 10); 
if (tmp_ptr == NULL){ 
    perror("Out of memory"); 
}else{ 
    p = tmp_ptr; 
} 
return p; 

Sie es eine andere Art und Weise tun, entweder geben die Adresse des neuen Blocks zurück oder Triple-Zeiger verwenden.

void addSpace(char ***p, int *size){ //remember to pass &size 
    //each time this is called, 10 more rows are added to the array 
    char **tmp_ptr = realloc(*p, *size + 10); 
    if (tmp_ptr == NULL){ 
     perror("Out of memory"); 
    }else{ 
     *p = tmp_ptr; 
    } 
    int i; 
    for(i=*size; i<(*size)+10; i++){ 
     *p[i] = malloc(20); 
    } 
    *size += 10; 
} 

Und von dem Anrufer

addSpace(&p, &size); 
+3

Oh, es ist viel schlimmer als das :( –

+0

@MartinJames entdeckte es etwas spät ... soz! – t0mm13b

+0

Aber das würde bedeuten, ich kann nicht mehr Wörter richtig lesen? Allerdings enthält die Datei 70 Wörter und möglich mehr.Es gibt keine Möglichkeit, sie alle hinzufügen zu können? – VlassisFo

2

C ist nach Wert übergeben. Der Zeiger wird an addSpace(p, &size); übergeben, und eine Kopie dieses Zeigers wird in der Funktion erstellt. Sobald die Kopie geändert wird: p = realloc(p,*size + 10); bleibt das Original gleich.

Nach dem Realloc-Aufruf ist der ursprüngliche Zeiger nicht mehr gültig. Die Verwendung führt zu undefiniertem Verhalten, einem Absturz in Ihrem Fall.

den neuen Wert zurück und es auf den ursprünglichen Zeiger zuweisen:

p = addSpace(p , &size); 
+0

Aber es funktionierte schon 2 mal, wenn das der Fall ist, sollte es überhaupt nicht funktionieren? – VlassisFo

+1

@Alan Nein, das korrekte Arbeiten ist eines der Ergebnisse von undefiniertem Verhalten. – 2501

+1

@Alan liefern/hand in/was auch immer, und es wird dann brechen. UB ist bösartig wie folgt :( –