B
Um einen Listenknoten zu löschen, müssen 2 Dinge passieren:
aus der Liste ausklinken
Element löschen
Du hast eine einfach verkettete Liste, das heißt, du kannst, wenn du einen Zeiger auf einen Listenknoten hast, immer nur den nachfolgenden Knoten entfernen, da du zum ausklinken den next-Zeiger des vorhergehenden Knoten verändern mußt.
Das heißt, du brauchst eine Fallunterscheidung, ob der erste Knoten der Liste gelöscht werden soll. In dem Fall wird nicht der next-Zeiger des vorhergehenden Knotens verändert, sondern der Listenkopf.
Da du eine Funktion zu suchen scheinst, die erst einen String sucht, und dann den entsprechenden Knoten entfernt, bietet sich eine Aufteilung der Aufgaben in 4 Funktionen an:
delete(string)
delete_first() // löscht erstes Element
delete_next(struct listelement*) // löscht nachfolgendes Element
struct listelement * find(string) // gibt Listenknoten zurück, der den String enthält
Das ganze läßt sich simpler gestalten, wenn man als Listenkopf einen Pseudoknoten verwendet, dh einen Listenknoten wie alle anderen, den man bei Suchoperationen usw. übergeht. Man kann den sogar gleichzeitig als Listenkopf und -ende verwenden, so dass sich eine zyklische Liste ergibt. Die Algorithmen zum entfernen und einfügen vereinfachen sich dadurch insbesondere bei einer doppelt verketteten Liste.
Noch was zum Stil:
Globale Variablen sind schlecht, auch wenns der Listenkopf ist (was spricht gegen Argumentübergabe, zb void listenausgabe(struct listelement * wurzel) ...)
gets ist schlecht, da du keine Kontrolle über die Länge der Eingabe hast. Wenn jemand zuviel eingibt, werden die Grenzen deiner Arrays überschritten und es kommt zum buffer overflow (nimm fgets stattdessen)
die Funktion zum Löschen der ganzen Liste hat undefiniertes Verhalten: Du löschst erst einen Knoten p, und verwendest danach nochmal p, um an p->next zu kommen. Du hast keine Garantie, dass free (ich seh an der Stelle mal über delete hinweg, eigentlich ist das ein C++-Programm was du da hast ;)) den Bereich, den es freigibt, nicht überschreibt. Der Speicher gehört dir einfach nicht mehr, nachdem du ihn freigegeben hast. Also speichere zuerst p->next in einen anderen temporären Zeiger, und lösche dann p.