2009-04-08 12 views
0

Ich versuche, eine Funktion zu schreiben, die alle Elemente in einem Array von Strings um eins erhöht.Alle Strings in Array verschieben (Problem mit realloc)

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int i; 
    for(i = cur; i < frag_len-1; i++) 
    { 
     if(strlen(frags[i+1]) > strlen(frags[i])) 
      frags[i] = realloc(frags[i], strlen(frags[i+1])*sizeof(char)); 
     strcpy(frags[i], frags[i+1]); 
    } 

    free(frags[frag_len-1]); 
} 

Dies wird mir den Fehler geben: „realloc(): ungültig nächste Größe: ...“ Jedes Array dynamisch zugewiesen die Größe einer Zeichenfolge aus einer Datei gelesen werden. Sollte ich nicht in der Lage sein, neue Array-Größen dynamisch zuzuordnen, da mein frags-Parameter ein Array von Zeigern ist?

Dank

+0

Computing sizeof (char) fügt dem Code nur Verschleierung hinzu. Es ist immer gleich 1. – unwind

Antwort

3

Da, wie Sie das Array sagen ist nur ein Array von Zeigern, Sie brauchen keine Umschichtungen vorzunehmen. Sie müssen nur die Zeiger selbst kopieren. Ein einfacher Aufruf von memmove oder etwas Ähnlichem im Teil des Arrays ist alles was benötigt wird.

Etwas, das sich annähert.

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    free(frags[frag_len]); 
    memmove(frags+cur+1, frags+cur, (frag_len-cur) * sizeof(char*)); 
} 
+0

Vergessen Sie nicht, frag_len mit sizeof (char *) zu multiplizieren – Alnitak

+0

Machst du Witze? Char ist immer Größe 1 Byte –

+0

Oder noch besser, durch sizeof * frags, um unnötige Wiederholung des Typs zu vermeiden. – unwind

2

Es gibt keine Notwendigkeit zu free()/realloc() alle an.

Ihr char **frags ist ein Zeiger auf eine Liste von Zeigern, so dass Sie die Zeigerwerte einfach umher mischen können, ohne neue Zeichenfolgen zu erstellen.

Sie sicher, dass Sie am Ende der Liste beginnen und rückwärts zählen, oder verwenden Sie memmove():

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int i; 

    free(frags[frag_len]); /* because otherwise this is left dangling */ 

    for(i = frag_len; i > cur; i--) 
    { 
     frags[i] = frags[i - 1]; 
    } 
} 

oder:

void shift_frags(char **frags, int frag_len, int cur) 
{ 
    int n = frag_len - cur; 
    frags += cur; 
    free(frags[n]); 
    memmove(frags + 1, frags, n * sizeof(*frags)); /* nb: memmove(dst, src, n) */ 
} 

NB: Es gibt eine mögliche off-by- Ein Fehler hier, hängt von der Semantik Ihres frag_len-Werts ab, und ob Sie wissen, dass der frag-Speicherblock bereits groß genug ist, um einen anderen Zeiger zu halten.

1

Ihre realloc versagt wahrscheinlich, weil Sie nicht ein Byte für das hintere NUL ('\ 0') Zeichen in Strings zu reservieren - das Hinzufügen einer 1 zu Ihrer realloc Größe:

if(strlen(frags[i+1]) > strlen(frags[i])) 
     frags[i] = realloc(frags[i], (strlen(frags[i+1]) + 1)*sizeof(char)); 
    strcpy(frags[i], frags[i+1]); 

wird fix dieser Fehler. Der spezifische Fehler, den Sie erhalten, liegt wahrscheinlich daran, dass einer Ihrer Strings die Länge 0 hat, und realloc (foo, 0) gibt Ihnen einfach diesen Fehler auf Ihrem System oder weil Sie das nachgestellte '\ 0' in nicht zugeordnetem Speicher schreiben und etwas anderes wichtiges überschreiben, Korruption verursachen.

Das einfache Umordnen von Zeigern (frags [i] = frags [i + 1], oder die Verwendung von memmove()) ist einfacher, schneller und verhindert, dass Sie Speicher verschwenden.