Verkettete Listen ein Anfang
-
Hallo also ich arbeite mich grad in Verkette Listen ein. Und Wollte eine Liste mit 4 Werten erstellen. Vorname, Nachname, Alter und Matrikelnummer.
Ich habe aber das Konzept nicht ganz verstanden glaube ich. Deshalb habe ich 3 Fragen die Nummeriert sind gestellt.
#include <stdio.h> struct liste {//Eine struct variable mit dem Namen "datei" wird erstellt char vnam[30];//Vorname char nnam[30];//Nachname int alt;//Alter int matr;//Matrikelnummer struct datei *next;//Zeiger auf das nächste Element der Liste } struct liste *anker;//1. Verstehe nicht wass das macht. Es wird ein Zeiger auf einen Typ liste erstellt der aber auf NULL zeigt weil da noch kein Speicherplatz ist. //Dies macht man global damit man von überall drauf zugreifen kann ohne es jedes mal an die Funktion zu übergeben. Oder? void anhang (struct liste *anker) //Funktion zum anhängen es wird der anker übergeben { int alter=0,matrnr=0; char vorname[30],nachname[30]; struct liste *zgr, *hzgr; //zwei Zeiger vom Typ struct zgr=anker; //aufs erste Element while(zgr->next!= NULL)//2.zgr zeigt jetzt auf das erste Element. So dass zgr->next auf den Zeiger zeigt der auf das nächste Element zeigt. zgr=zgr->next;//Solange der Zeiger nicht NULL ist (also danach nichts mehr kommt, ende der Liste) wird zgr zum next Zeiger. hzgr=malloc(sizeof(struct element));//Speicherplatz für neues Element } int main() { anker=malloc(sizeof(struct liste));//3. Hier wird jetzt auch der Speicherplatz allociert und zugewiesen so das nach dem anker jetzt auch ein element ist. anhang(anker); printf("world\n"); getchar(); return 0; }
Wie man sehen kann bin ich grad dabei die Funktion Anhang zu schreiben damit ein neues Listenelement angehägt wird und man es dann mit Daten füllen kann.
Dazu habe ich jetzt das Problem wie ich denn am besten die Daten reinschreibe die von der Tastatur eingegeben werden sollen.
würde folgendes gehen?
scanf("%s",hzgr->vnam);
Außerdem habe ich gelesen das scanf ne scheiß Funktion ist da man über das Array hinausschreiben kann weil die Länge der Eingabe nicht geprüft ist. Was wäre denn eine bessere Funktion? Bitte nur Betriebsystemunabhängig wenns so etwas gibt. Und dann wäre natürlich cool wenn ihr die Funktion die ihr nennt erklärt oder nen Link zu ner guten Quelle gebt
Danke schonmal
-
Zu 1.:
Du musst dir merken, wo die Liste anfängt, sonst gehen dir Elemente verloren, da du ja nur den Nachfolger kennst.
Es muss nicht global sein. Es ist sogar besser, wenn du es jedesmal an deine Funktionen mit übergibst.Zu 2.:
Es ist blöd, die lokale Variable genau so zu nennen wie dein Listenanfang.
Du hast dann nämlich keinen Zugriff auf das globale anker.Es kann auch sein das zgr schon NULL ist. Dann hast du bei zgr->next Probleme.
Deine Funktionen sollten auch einen sinnvollen Rückgabewert haben.
z.B den Wert vom ersten Listenelement.Du besorgst z.Zt Speicher in main und benutzt ihn nicht. (Zeile 32)
Du solltest zumindest nach der Speicheranforderung das next-Element initialisieren (mit NULL)Verkettete Listen funktionieren so wie Schnitzeljagd.
Dir wird gesagt wo du anfängst (dein anker), und an dem Ort findest du einen Hinweis, wo es weitergeht (next), und an dem Ort .....Und den Speicher den du mit malloc angefordert hast, musst du auch wieder freigeben.
malloc kann auch mal schief laufen und gibt dann NULL zurück.
-
So dann hier das neue Kunstwerk. Aber wie du schon sagtes macht die While schleife Probleme.
Ich habe mal Dummyhaft für das erste Element schon in der Main Funktion die Eingabe machen lassen. So das der erste nicht frei bleibt.
Woran liegt den das Problem in der While schleife? Eigentlich sage ich doch nur er soll immer wieder das next vom nächsten Element bekommen wenn es noch ein nächstes Element gibt.
Auch die If schleife davor kann vor dem Problem nicht zu bewahren.
#include <stdio.h> #include <stdlib.h> struct liste {//Eine struct variable mit dem Namen "liste" wird erstellt char vnam[30];//Vorname char nnam[30];//Nachname int alt;//Alter int matr;//Matrikelnummer struct liste *next;//Zeiger auf das nächste Element der Liste }; void anhang (struct liste *anker) //Funktion zum anhängen es wird der anker übergeben { struct liste *zgr, *hzgr; //zwei Zeiger vom Typ struct zgr=anker; //aufs erste Element if (zgr->next!=NULL)//PROBLEM MIT DER IF ABFRAGE { while(zgr->next!= NULL)//PROBLEM MIT DER SCHLEIFE zgr=zgr->next; } hzgr=malloc(sizeof(struct liste));//Speicherplatz für neues Element if (hzgr==NULL) { printf("\nFehler bei der Speicher allocierung in der Funktion: Anhang"); getchar(); return ; } printf("\nBitte Vorname eingeben:");//Eingabe aller Daten. scanf("%s",hzgr->vnam); printf("\nBitte nachnamen eingeben:"); scanf("\n%s",hzgr->nnam); printf("\nBitte Alter eingeben:"); scanf("%d",&hzgr->alt); printf("\nBitte Matrikelnummer eingeben:"); scanf("%d",&hzgr->matr); hzgr->next=NULL;//Den zeiger vom neuen Element noch auf NULL setzen zgr->next=hzgr;//Und das neue Element an das Ende der alten Liste return ; } int main() { struct liste *anker; anker=malloc(sizeof(struct liste)); printf("\nBitte Vorname eingeben:");//Eingabe aller Daten. scanf("%s",anker->vnam); printf("\nBitte nachnamen eingeben:"); scanf("\n%s",anker->nnam); printf("\nBitte Alter eingeben:"); scanf("%d",&anker->alt); printf("\nBitte Matrikelnummer eingeben:"); scanf("%d",&anker->matr); anhang(anker); printf("world\n"); getchar(); getchar(); return 0; }
-
Jetzt habe ich das mit scanf glatt vergessen.
scanf ist nicht scheiße.
Du musst nur wissen was es macht.
Bei den Formatspecifiern kann man Längenangaben machen.
Ein %29s liest maximal 29 Zeichen ein. Ein Zeichen wird für die abschließende '\0' gebraucht.
Allerdings stopt es bei Leerzeichen. Ein "Kai Malte" als Vornamen macht also Probleme.gets ist scheiße, denn da kannst du keine Längenangabe machen.
Bei fgets kannst die Länge angeben (in diesem fall 30).
fgets speichert aber das '\n' von der Entertaste mit ab.Du kannst bei scanf den [ Specifier nehmen. Da gibt man eine Liste von erlaubten oder nicht erlaubten Zeichen ein.
Ein%29[^\n]
liest alles bis zur Entertaste aber maximal 29 Zeichen.
Die Zeichen ab 30 werden dann für die nächste Eingabe verwendet.
Dies ist das Unterforum für Standard-C. Hier gibt es nur betriebsystemunabhängige Hinweise.
Und wenn es nicht anders geht, nur mit großen Bauchschmerzen
-
Odatas schrieb:
Ich habe mal Dummyhaft für das erste Element schon in der Main Funktion die Eingabe machen lassen. So das der erste nicht frei bleibt.
Woran liegt den das Problem in der While schleife? Eigentlich sage ich doch nur er soll immer wieder das next vom nächsten Element bekommen wenn es noch ein nächstes Element gibt.
Und was ist mit anker->next?
Welchen wert hat das?Du musst aus deiner Funktion anhang auch das erste Listenelement zurückbekommen.
struct liste *anhang (struct liste *anker) { Wenn anker != NULL Nachfolger suchen. Speicher (zgr) besorgen und füllen. Wenn anker == NULL return zgr; sonst retrun anker; } //und in main anker = anhang(anker);
Da fehlt allerdings die Fehlerbehandlung.
Du kannst auch Speicher holen/füllen und an Liste anhängen in getrennte Funktionen machen.Odatas schrieb:
Auch die If schleife davor kann vor dem Problem nicht zu bewahren.
Es gibt keine if-Schleife
-
DirkB schrieb:
Und was ist mit anker->next?
Welchen wert hat das?Ok da war der Fehler der Next von Anker muss natürlich auch NULL bekommen.
Jetzt klappt es super.
DirkB schrieb:
Du musst aus deiner Funktion anhang auch das erste Listenelement zurückbekommen.
Du meinst den Anker? Wäre es da nicht dann doch schlauer gewesen den Global zu machen dann muss ich den weder zurückgeben noch hingeben. Oder ist Global einfach zu verpöhnt?
DirkB schrieb:
Da fehlt allerdings die Fehlerbehandlung.
Ja an der muss ich noch arbeiten ist aber erstmal Sekundär für mich
DirkB schrieb:
Es gibt keine if-Schleife
:p
-
Mit der einen globalen Variablen, kannst du nur eine Liste verwalten.
Wenn die Liste jedesmal an die Funktion übergeben wird, kannst du auch mehrere gleichartige Listen in deinem Programm verwalten.Nebenbei ist eine
struct liste
vom Namen her ziemlich blöd, wenn sie Studenten verwaltet.Eine struct list sieht ungefähr so aus:
struct liste { struct liste *next; };
So eine struct ist wenig sinnvoll, da sie kein Nutzdaten hat, aber du kannst die Komplette Listenverwaltung (einfügen, anhängen, löschen, Ende finden) damit machen.
Wenn du dann eine struct student { struct liste *student;//Zeiger auf das nächste Element der Liste char vnam[30];//Vorname char nnam[30];//Nachname int alt;//Alter int matr;//Matrikelnummer };
hast, ist das nicht anders.
Da die ->next Zeiger sogar an der selben Stelle stehen, kannst du sogar die selben Funktionen nehmen. (zum verketten der liste, nicht zum Speicher holen)