richtiger Funktionsaufruf
-
Danke für die schnelle Antwort und für den Tipp!
Hab das jetzt wie folgt abgeändert, bekomme aber immernoch einen Fehler, bei der Funktion insert()(Zeile 118), wegen in Konflikt stehenden Typen. Hast du dazu noch einen Tipp oder Hinweis?#include <stdio.h> #include <stdlib.h> #define MaxCharPerLine 51 /* 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 tmpSearch1[MaxCharPerLine]; char tmpSearch2[MaxCharPerLine]; char t[MaxCharPerLine]; int tlen = 0; int cnt = 0; char s[MaxCharPerLine]; char search[MaxCharPerLine]; int i = 0; int j = 0; int found = 0; int number = 0; int repeat = 1; struct element { char *list0; struct element *next; }; int insert(struct element, struct element); int main () { insert(*list_begin,*currentPointer); /* 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; } int insert(struct element *list_begin,struct element *currentPointer) { /* 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; /* 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; } } } return list_begin->list0; }
-
Schau mal selber.
Deine Deklaration (der Prototyp)int insert(struct element, struct element);
und deine Definition:
int insert(struct element *list_begin,struct element *currentPointer) { ....
Das passt nicht.
-
Ok, ich habe jetzt die Funktionsdefinition wie folgt geändert:
int insert(struct element*, struct element*);
Außerdem habe ich noch den Funktionsaufruf so geändert:
insert(list_begin,currentPointer);
Jetzt werden zwar keine Fehler mehr angezeigt, aber auch anscheinend kein Wert richtig eingetragen, d.h. ich kann zwar nach einem Teilstring suchen, es wird aber kein Treffer angezeigt und auch sonst die Liste nicht ausgegeben, deswegen habe ich den Funktionsaufruf angepasst, weil die Zeiger ja auf list0 zeigen sollen:
insert(list_begin->list0,currentPointer->list0);
Jetzt wird alles richtig compiliert, ich bekomme aber einen Speicherzugriffsfehler, woran könnte das liegen?
Achja, ich habe, der Einfachheit halber, alle Variablen global definiert, was an für sich ja nicht so gut ist. Könnten deshalb nicht auch Fehler auftreten?
-
Überleg mal, welche Werte die Paramter beim ersten Aufruf haben.
Sonst nimm den Debugger.Oder gib mal die Werte von deinen Zeigern in main und in insert aus.zur Kontrolle auf dem Bildschirm aus. Für Zeiger gibt es bei printf den Formatspecifier %p
rei0d schrieb:
Jetzt wird alles richtig compiliert, ..
Dann schalte mal den Warnlevel auf Maximum.
list_begin->list0
ist einchar*
insert ewartet doch aber einstruct element*
rei0d schrieb:
Achja, ich habe, der Einfachheit halber, alle Variablen global definiert, was an für sich ja nicht so gut ist.
Das macht es nicht einfacher, sondern nicht lesbar/nachvollziehbar.
-
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.