richtiger Funktionsaufruf
-
Beim ersten Aufruf waren beide NULL bzw nil. Eigentlich muss ich currentPointer ja auch gar nicht übergeben, da ihm sowieso list_begin zugeordnet wird, deshalb habe ich mir gedacht, dass es sinnvoller ist, tmpPointer, also den Zeiger auf das Element, das eingefügt werden soll, zu übergeben.
Ich habe jetzt noch ein paar Kleinigkeiten geändert und u.a. auch die Variablen wieder global in der main() deklariert.
Mein jetziges Problem ist, dass er für list_begin immer wieder den NULL-Zeiger hat, obwohl in der sort()-Funktion ein Zeiger übergeben wird, der nicht NULL ist, was ich auch mit printf("%p",list_begin); immer ab prüfe.
Meine Vermutung ist, dass der Rückgabetyp nicht char oder struct element* sein sollte, mir fällt aber partout nicht ein, was er sonst ist.#include <stdio.h> #include <stdlib.h> #define MaxCharPerLine 51 struct element { char *list0; struct element *next; }; char sort(struct element*, struct element*); int main () { /* Zeiger auf Anfang der Liste */ struct element *list_begin = 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[MaxCharPerLine]; int found = 0; int number = 0; int repeat = 1; /* Einlesen in list0 */ while(fgets(t, sizeof(t), stdin)!=NULL) { tlen = strlen(t); if(tlen == 1) { free(s); continue; } char *s = calloc(tlen + 1,sizeof(char)); 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; printf("%p %p\n",list_begin,tmpPointer); sort(list_begin,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 */ while(repeat) { printf("Gesuchte Zeichenkette: "); scanf("%s",&search); currentPointer = list_begin; beforePointer = NULL; while(currentPointer != NULL) { number++; if(strstr((currentPointer->list0),search)) { /* Übereinstimmung */ found = 1; } /* vorheriges Element merken */ beforePointer = currentPointer; if(found == 1) { if(beforePointer == NULL) { /* Erstes Element gefunden */ printf("%i: %s\n",number,list_begin->list0); /* Gefundenes Element löschen */ list_begin = currentPointer->next; } else { printf("%i: %s\n",number,currentPointer->list0); /* Löschen des gefundenen Elements */ beforePointer->next = currentPointer->next; } } found = 0; currentPointer = currentPointer->next; } number = 0; } free(tmpPointer); return 0; } char sort(struct element *list_begin,struct element *tmpPointer) { struct element *currentPointer = list_begin; /* Sortieren */ 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; } } printf("%p\n",list_begin); return list_begin; }
-
Achte auf die Compilerwarnungen
char sort(struct element *list_begin,struct element *tmpPointer) {... printf("%p\n",list_begin); return list_begin; // list_begin ist kein char }
und in der main:
sort(list_begin,tmpPointer); // Rückgabewert?
Der Rückgabetyp bei der Definition und beim return passen nicht zusammen.
Zudem wertest du den ja auch gar nicht aus.
-
So etwa?
struct element* sort(struct element*, struct element*); ... struct element* sort(struct element *list_begin,struct element *tmpPointer) { ... return list_begin; }
Mein compiler (gcc in CodeBlocks) gibt mir außer ein paar Warnungen zu impliziten Deklarationen zu Funktionen wie strlen, strcpy etc sonst nichts zurück.
Sorry, dass ich da grade so schwer von Begriff bin..
-
rei0d schrieb:
Mein compiler (gcc in CodeBlocks) gibt mir außer ein paar Warnungen zu impliziten Deklarationen zu Funktionen wie strlen, strcpy etc sonst nichts zurück.
Dann geh mal ins Menue Project -> Build Options ... und da auf den Reiter Compiler Settings.
Da machst du je einen Haken bei "Enable all compiler warnings [-Wall]" und "Enable extra compiler warnings [-Wextra]"Und ein #include <string.h> solltest du noch spendieren.
Dein Programm muss ohne Warnungen compilieren.
-
Danke für den Tipp mit den Compilerwarnungen, jetzt zeigt er wirklich mehr an, was enorm hilfreich ist.
Ich habe jetzt den ganzen Code entsprechend der Aufgabenstellung überarbeitet und alles zum Laufen bekommen, d.h. das Einsortieren, Ausgeben und Suchen in einzelne Funktionen gepackt. Fehler oder Warnungen bekomme ich auch keine mehr angezeigt.
Danke für die Hilfe, ich war zeitweise wirklich schwer von Begriff.PS:
Ich habe nicht bedacht, dass der Pointer list_begin, den ich in einer Funktion ändere, ja sich global nicht ändert, das war eigentlich mein größter Denkfehler.PPS: Hier mein Quellcode:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define MaxCharPerLine 51 struct element { char *list0; struct element *next; }; struct element* sort(struct element*, struct element*); void printAll(struct element*); int searchForString(struct element*, char*); int main () { /* Zeiger auf Anfang der Liste */ struct element *list_begin = NULL; /* Temporaerer Zeiger auf Listenknoten */ struct element *tmpPointer; char t[MaxCharPerLine]; int tlen = 0; int cnt = 0; int repeat = 1; char search[MaxCharPerLine]; /* Einlesen in list0 */ while(fgets(t, sizeof(t), stdin)!=NULL) { tlen = strlen(t); if(tlen == 1) { continue; } char *s = calloc(tlen + 1,sizeof(char)); 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; printf("%p %p\n",list_begin,tmpPointer); list_begin = sort(list_begin,tmpPointer); } printAll(list_begin); /* Freigeben von stdin, sodass Eingabe über Tastatur erfolgen kann */ freopen("/dev/tty","r",stdin); while(repeat) { printf("Gesuchte Zeichenkette: "); fgets(search,MaxCharPerLine,stdin); /* fgets() liest '\n\0' als letzte Zeichen ein, '\n' muss aber weg für strstr() */ search[strlen(search) - 1] = '\0'; cnt = searchForString(list_begin,search); puts("\t|------------------------------------|"); printf("\t|\t%i Objekt(e) gefunden.\t |\n",cnt); puts("\t|------------------------------------|"); } free(tmpPointer); return 0; } struct element* sort(struct element *list_begin,struct element *tmpPointer) { struct element *currentPointer = list_begin; /* Sortieren */ 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; } } return list_begin; } void printAll(struct element *list_begin) { struct element *tmpPointer; tmpPointer = list_begin; while (tmpPointer != NULL) { printf("%s\n", tmpPointer->list0); /* Zeiger auf nächsten Eintrag */ tmpPointer = tmpPointer->next; } } int searchForString(struct element *list_begin,char *search) { int cnt = 0; struct element *currentPointer; struct element *beforePointer; int found = 0; int number = 0; currentPointer = list_begin; beforePointer = NULL; while(currentPointer != NULL) { number++; if(strstr((currentPointer->list0),search)) { /* Übereinstimmung */ found = 1; } /* vorheriges Element merken */ beforePointer = currentPointer; if(found == 1) { cnt++; if(beforePointer == NULL) { /* Erstes Element gefunden */ printf("%i: %s\n",number,list_begin->list0); /* Gefundenes Element löschen */ //list_begin = currentPointer->next; } else { printf("%i: %s\n",number,currentPointer->list0); /* Löschen des gefundenen Elements */ //beforePointer->next = currentPointer->next; } } found = 0; currentPointer = currentPointer->next; } number = 0; return cnt; }
-
Wäre es nicht auch schön, wenn man das Programm beenden könnte, ohne es abzuschießen? Dann könntest du auch üben, wie man Speicher richtig freigibt. Mit deinem einem free, welches zudem nie erreicht wird, ist es nämlich nicht getan.
-
Ok, jetzt beendet es, wenn EOF erfüllt ist.
... while(printf("Suchen nach: ") && fgets(search,sizeof(search),stdin) != NULL) { /* fgets() liest '\n\0' als letzte Zeichen ein, '\n' muss aber weg für strstr() */ search[strlen(search) - 1] = '\0'; cnt = searchForString(list_begin,search); puts("\t|------------------------------------|"); printf("\t|\t%i Objekt(e) gefunden.\t |\n",cnt); puts("\t|------------------------------------|"); } ...
Um die Liste zu löschen müsste doch folgendes klappen oder?
... /* Zeiger auf Anfang der Liste */ struct element *list_begin = NULL; /* Temporaerer Zeiger auf Listenknoten */ struct element *tmpPointer; struct element *freePointer = NULL; ... tmpPointer = list_begin; while(tmpPointer!=NULL) { freePointer = tmpPointer; tmpPointer = tmpPointer->next; free(freePointer->list0); free(freePointer); } free(tmpPointer); ...
-
s musst du ganz am Schluss wieder freigeben; genauso übrigens alle Listenelemente!
dein free(tmpPointer) in Zeile 77 macht übrigens nicht das was du vermutlich willst; es wird nämlich lediglich das letzte Element aus der Liste an free übergeben, alle anderen Elemente bleiben im Speicher!
-
rei0d schrieb:
Eigentlich müsste ich ja noch s freigeben, mit einem free(s) meckert aber der Compiler. Gibt es sonst noch eine Möglichkeit?
Achte auf den Scope von s. Die Pointervariable s ist nur innerhalb der while-Schleife gültig.
Allerdings übernimmt doch
tmpPointer->list0
den Bereich von s.
-
Ich habe meinen letzten Beitrag schon dahingehend editiert, jetzt müsste er ja die gesamte Liste löschen oder?
-
Sollte funktionieren. Aber das free in Zeile 18 ist überflüssig. Das Element wird in der Schleife schon freigegeben.