Verkettete Liste, letzten Eintrag löschen
-
Hallo zusammen!
Da ich letztens so wunderbar geholfen bekommen habe, muss ich leider wieder eure Hilfe in Anspruch nehmen:
Geht bei meinem Problem um eine verkettete Liste in die man nach und nach Wörter eingeben kann. Weiterhin kann man zwischen den einzelnen Einträgen wiederum Einträge vornehmen oder auch löschen. Das Ende der Liste wird mit dem Wort ENDE gekennzeichnet.
Das funktioniert auch alles soweit, bis auf dass ich den letzten Eintrag zwar löschen kann, dieser aber immer wieder mit ausgegeben wird, also letztendlich nicht gelöscht wird. Aufgerufen wird die Funktion in main, wo zuvor das zu löschende Wort eingelesen und an die Funktion übergeben wird.
wort ist ein feld mit 20er Größe und liste ist der Zeiger auf den Anfang der Liste.
Wo ist dort der Haken bzw. was habe ich falsch gemacht?
Hier mal die Lösch-Funktion:
void loeschen(element* ptr, char delwort[20]) { element* kopf = ptr; element* tempptr; if (strcmp(liste->wort, delwort) == 0){ liste = kopf->next; free(kopf); return; } else { if (strcmp(ptr->next->wort, delwort) == 0) { if (ptr->next->next == NULL) { free(ptr->next->next); ptr->next = NULL; } else{ tempptr = ptr->next; ptr->next = ptr->next->next; free(tempptr); return; } if (ptr->next != NULL){ loeschen(ptr->next, delwort); } return; } } }
-
Ne verkette Liste schließt man mit NULL ab und nicht mit einem "ENDE-Wort". Dann sollte das auch einfacher sein.
void loeschen(element* ptr, char delwort[20]) { element* kopf = ptr; element* tempptr; if (strcmp(liste->wort, delwort) == 0){ // Während der rekursion immer sas erste Wort prüfen ? Warum ? liste = kopf->next; free(kopf); return; } else { if (strcmp(ptr->next->wort, delwort) == 0) { if (ptr->next->next == NULL) { //Wenn der pointer NULL ist gibst du frei ? free(ptr->next->next); ptr->next = NULL; // hier leak: ptr->next ist valid (siehe letzte Zeile) und du wirfst es weg } else{ tempptr = ptr->next; ptr->next = ptr->next->next; free(tempptr); return; } if (ptr->next != NULL){ loeschen(ptr->next, delwort); //ist sehr missverständlich - du löschst ja nicht das nächste element oder ? Ich würde einfach solange durch die Liste laufen bis das nächste emlement NULL ist, wenn das wort geufunden ist rausschneiden und return; } return; } } }
Und was genau ist nochmal liste und was kopf ?!
Code (ungetested) für Liste terminiert mit NULL
element* loeschen(element* ptr, char delwort[20]) // ptr ist start der liste, returnt den neuen start der liste { if(ptr == NULL) return NULL; if(strcmp(ptr->wort, delwort) == 0) // start löschen ? { element* temp = ptr->next; free(ptr); return temp; } while(ptr->next != NULL) { if(strcmp(ptr->next->wort, delwort) == 0) { element* temp = ptr->next->next; free(ptr->next); ptr->next = temp; return ptr; } ptr = ptr->next; } return ptr; }
Ist doch gleich viel schöner so.