Zeichenkette in verketteter Liste suchen & Löschen [C89]
-
Guten Morgen,
ich bin gerade dabei, ein Programm zu schreiben, das aus einer Textdatei mehrere Strings in die verkettete Liste list0 einliest und sortiert. Das funktioniert einwandfrei. Jetzt soll aber ein Teilstring in der sortierten Liste gesucht und evtl. gelöscht werden. Ich bekomme aber immer einen Speicherzugriffsfehler beim Ausführen des Programms.
Außerdem würde meine Herangehensweise doch nur prüfen, ob der genau eingegebene String, der in search abgespeichert wird, vorhanden ist. Es sollen aber auch Teilketten gefunden werden. Wie würde das gehen?Die Textdatei ist etwa so aufgebaut:
Eintrag Nr. 2 Eintrag Nr. 3 Eintrag Nr. 1 ...
Sortiert soll es dann so aussehen:
Eintrag Nr. 1 Eintrag Nr. 2 Eintrag Nr. 3
Danach soll jetzt eine Abfrage nach dem gesuchten Teilstring kommen, indem man z.B. "1" eingibt. Jetzt soll die "1" im String "Eintrag Nr. 1" gefunden, dieser ausgegeben und gelöscht werden. Wird nach "Eintrag" gesucht, sollen in dem Beispiel alle Strings gesucht und ausgegeben werden.
Hier mein Code:
#include <stdio.h> #include <stdlib.h> #define MaxCharPerLine 51 struct element { char *list0; struct element *next; }; int main () { /* Zeiger auf Anfang und Ende der Liste */ struct element *list_begin = NULL; struct element *list_end = NULL; /* Temporaerer Zeiger auf Listenknoten */ struct element *tmpPointer; /* Zeiger auf aktuelles Element */ struct element *currentPointer; /* Zeifer auf vorheriges Element */ struct element *beforePointer; char t[MaxCharPerLine]; int tlen = 0; int cnt = 0; char s[MaxCharPerLine]; char search; int i = 0; int j = 0; int found = 0; /* Einlesen in list0 */ while(fgets(t, sizeof(t), stdin)!=NULL) { tlen = strlen(t); char *s = (char*)calloc(tlen + 10,sizeof(char)); if(tlen == 1) { free(s); continue; } if(t[tlen - 1]=='\n') { t[tlen - 1]='\0'; } strcpy(s,t); cnt++; /* Speicher anfordern */ tmpPointer = (struct element *)malloc(sizeof (struct element)); /* Daten in list0 eintragen */ tmpPointer -> list0 = s; tmpPointer -> next = NULL; /* Sortieren */ currentPointer = list_begin; if(list_begin == NULL) { list_begin = tmpPointer; } else { if(strcmp(list_begin->list0, tmpPointer->list0) > 0) { tmpPointer->next = list_begin; list_begin = tmpPointer; } else { while((currentPointer->next) != NULL) { if(strcmp((currentPointer->next)->list0, tmpPointer->list0) > 0) { break; } currentPointer = currentPointer->next; } tmpPointer->next = currentPointer->next; currentPointer->next = tmpPointer; } } } /* Ausgabe von list0 */ tmpPointer = list_begin; while (tmpPointer != NULL) { printf ("%s\n", tmpPointer -> list0); /* Zeiger auf nächsten Eintrag */ tmpPointer = tmpPointer -> next; } /* Freigeben von stdin, sodass Eingabe über Tastatur erfolgen kann */ freopen("/dev/tty","r",stdin); /* Suche nach Teilkette */ printf("Gesuchte Zeichenkette: "); scanf("%s",&search); currentPointer = list_begin; beforePointer = NULL; while(currentPointer != NULL) { if(strcmp((currentPointer->list0),search) == 0) { /* Übereinstimmung */ found = 1; break; } /* vorheriges Element merken */ beforePointer = currentPointer; currentPointer = currentPointer->next; if(found) { if(beforePointer == NULL) { /* Erstes Element gefunden */ printf("%s",list_begin->list0); /* Gefundenes Element löschen */ //list_begin = currentPointer->next; } else { printf("%s",currentPointer->list0); /* Löschen des gefundenen Elements */ // beforePointer->next = currentPointer->next; } } } free(tmpPointer); return 0; }
-
Mal ganz abgesehen davon, dass du mit Einsparung deiner verk. Liste auch gleich 90% deines Codes einsparen könntest (und somit auch entsprechend viele Fehler)
dürftechar search; ... scanf("%s",&search);
ein Fehler sein.
-
Erst mal überflogen:
char search; ... scanf("%s",&search);
Das passt nicht zusammen.
scanf
erwartet bei %s einen Zeiger mit ausreichend Platz für eine nullterminierten String
Ein einzelnes Zeichen reicht ja gerade für die '\0'.Teilstrings kannst du mit der Standardfunktion
strstr
suchen.Das ist auch kein C89 (wegen Zeile 40):
Warum +10?
Warum der cast?
sizeof(char) ist per Definition 1.Schreib das
calloc
hinter dasif(tlen == 1)
-
Danke für die schnellen Antworten.
Dass eine verkettete Liste in dem Fall nicht sehr effektiv ist, weiß ich selber, wir sollen aber eine verwenden, um den Umgang damit zu lernen.Ich habe jetzt folgendes angepasst:
Zeile 31:char search[MaxCharPerLine];
Zeile 40ff:
if(tlen == 1) { free(s); continue; } char *s = calloc(tlen,sizeof(char));
Zeile 121:
if(strstr((currentPointer->list0),search) != NULL){...
Zeile 129:
currentPointer = currentPointer->next;
habe ich ans Ende der while Schleife gepackt.
Jetzt kommt zumindest kein Fehler mehr, er gibt aber immernoch keinen String aus, den er eigentlich gefunden haben müsste.
-
Ok ich hab meinen Fehler selber gefunden:
In Zeile 125 bin ich mit break automatisch aus der while Schleife rausgegangen, was ja totaler Quatsch ist. Abgesehen davon habe ich jetzt die Variable found nach jedem Durchlauf der while Schleife wieder 0 gesetzt.
-
Beim calloc ist ein +1 richtig. (für die '\0')