2016-12-13 3 views
5

Ich habe dieses Array von Strukturen und diese Funktion nimmt einen Zeiger auf den Zeiger des Arrays. Die ursprüngliche Größe ist 2, wenn die Größe erreicht ist, muss ich die Größe neu zuweisen und verdoppeln. Wenn dieser Code ausgeführt wird, erhalte ich einen ungültigen alten Fehler von der Realloc. Was mache ich falsch?Wie verwenden Sie Realloc, wenn Sie einen Zeiger auf einen Zeiger einer Struktur haben?

int PopulateArray(struct Inventory **inv, int *size, FILE *inputFile) { 
    int count = 0; 
    printf("address: %u\n", inv); 
    printf("address: %u\n", **inv); 
    int itemNumber; 
    int quantity; 
    float price; 
    int month; 
    int year; 
    while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber, 
    &quantity, &price, &month, &year) != EOF) { 
     (*inv)->itemNumber = itemNumber; 
     (*inv)->quantity = quantity; 
     (*inv)->price = price; 
     (*inv)->expDate.month = month; 
     (*inv)->expDate.year = year; 
     printf("count: %i size: %i\n", count, *size); 

     if (count == *size - 1) { 
     inv = realloc(inv, (*size * 2 * sizeof(struct Inventory))); 
     *size *= 2; 
     } 
     inv++; 
     count++; 
    } 
    return count; 
    } 
+1

'while (fscanf (...)! = EOF)' ist nicht sicher. Überlegen Sie, was passiert, wenn * einige *, aber nicht * alle * Conversions erfolgreich sind. – EOF

Antwort

4

in Ihrer Funktion ist inv (vermutlich) die Adresse eines Zeigervariable. Es ist der Wert der Variablen, die an realloc übergeben werden soll.

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 

Aus dem gleichen Grund, Inkrementieren inv selbst nicht tun, was Sie erwarten.

Da Sie realloc verwenden müssen, sollten Sie count verwenden, um das Array zu referenzieren.

while (fscanf(inputFile, "%i %i %f %i/%i", &itemNumber, 
    &quantity, &price, &month, &year) != EOF) { 
    (*inv)[count].itemNumber = itemNumber; 
    (*inv)[count].quantity = quantity; 
    (*inv)[count].price = price; 
    (*inv)[count].expDate.month = month; 
    (*inv)[count].expDate.year = year; 
    printf("count: %i size: %i\n", count, *size); 

    if (count == *size - 1) { 
    *inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 
    if (*inv == NULL) { 
     perror("realloc failed"); 
     exit(1); 
    } 
    *size *= 2; 
    } 
    count++; 
} 
3

Das Problem tritt auf, weil Sie inv (inv++;) sind zu ändern.

Sie können nur realloc Daten, wenn der übergebene Zeiger ein gültiger zugewiesener Zeiger ist, kein Zeiger innerhalb die zugeordnete Zone.

Sie müssen also Ihre inv Daten speichern, so dass Sie realloc verwenden können. Der Zeiger auf das aktuelle Element muss eine andere Variable sein.

Und überprüfen Sie, dass realloc nicht NULL zurückgibt, bevor Sie zurück zu inv zuweisen oder Sie verlieren Ihren ursprünglichen Zeiger.

Das ließ mich fast den größten Fehler verpassen (1 Fehler, der den anderen versteckt, klassisch): Sie übergeben einen struct Inventory ** Typ, so dass Sie den Zeiger ändern können, aber Sie ändern stattdessen den Doppelzeiger.

Sie sollten Ihre realloc auf dem spitzen Wert, nicht auf der Adresse des Zeigers ausführen:

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 
0

Wenn Sie inv von realloc(), Ihre inv zeigen nun auf den Start der neu Größe verändert Array aktualisieren . Also, Ihr Code

if (count == *size - 1) { 
    inv = realloc(inv, (*size * 2 * sizeof(struct Inventory*))); 
    *size *= 2; 
    } 
    inv++; 

die letzten inv++ macht inv Punkt effektiv zu inv[1], nicht die inv[count], die Sie wahrscheinlich darauf hinweisen würden, wollten.

ich unten bin hinzugefügt, da falsche Antworten werden upvoted werden

Der Vorschlag von

*inv = realloc(*inv, (*size * 2 * sizeof(struct Inventory))); 

ist nicht korrekt.

Sie versuchen, das Array der Zeiger dynamisch zu verdoppeln. Also ist der korrekte Zeigertyp, der an realloc übergeben werden soll, struct Inventory **.

(Sie wahrscheinlich von pptr = malloc(sizeof(struct Inventory*) * INIT_SIZE) Anfangstabelle erstellt, so inv für realloc hier richtiger Typ ist)

Having said that, nachdem Sie die realloc in Ihrer Funktion ausführen, die ursprünglichen inv Zeiger durch den Code verwendet, die genannt Diese Funktion ist nicht mehr gültig. Wenn Sie diese Funktion also zurückgeben, verlieren Sie den Zeiger auf das geänderte Array. Um damit umzugehen, müssen Sie den neuen Zeigerwert inv an die aufrufende Funktion zurückgeben.

zusätzliche edit:

Und vergessen Sie nicht, Speicher für die tatsächlichen struct Inventory Artikel zuzuordnen:

inv[count] = malloc(sizeof(struct Inventory)); 

zu Beginn der Schleife.

Verwandte Themen