Korrekte Syntax von Pointern
-
Hallo liebes Forum,
ich möchte mich erstmal kurz vorstellen. Seit dem WS 2013/14 studiere ich an der RWTH Aachen Informatik und bin zur Zeit im 2. Semester.
Der Professor ist der Meinung, dass 2 Vorlesungen á 1,5 Stunden ausreichen, um C zu programmieren.
Naja lange Rede kurzer Sinn.
Wir haben eine Hausaufgabe erhalten, in der wir eine "single linked list" implementieren sollen.
Die Funktionen enqueue dequeue sollen wir korrekt implementieren, da die Kommentare nur Hinweise geben.Dazu haben wir ein Code-Grundgerüst erhalten.
Ich hab alles abgesucht, aber in meinen Augen sollte die Implementierung von enqueue stimmen, jedoch funktionert die "Test-Main" nicht.
Ich wäre sehr dankbar, wenn vielleicht jemand so freundliche wäre und im selben Zuge erklären könnte, wann () um einen Pointer muss oder wann ein * dabei stehen muss und wann ein . zum Abruf des Inhalts gebraucht wird und wann ein ->.
Ich hoffe auf eine gute Zeit, da sich C wahrscheinlich durch mein ganzes Studium zieht und dieses Forum sieht vielversprechend aus.
Liebe Grüße
Benedikt#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct stud_type_ { /* Struktur des Datensatzes: */ int matnum; /* Matrikelnummer, Vor- */ char vorname[20]; /* und Nachname sind Eintraege. */ char nachname[20]; /* Die Datenbank ist eine */ struct stud_type_ *next_student; /* einfach verkettete Liste */ } stud_type; /* Ist die Datenbank leer? */ int is_empty(stud_type** liste) { return *liste == NULL; } /* Einfuegen eines Elementes * * Bekommt einen Zeiger auf einen Zeiger der auf das 1. Element der Liste zeigt * Bekommt MatNr, Vorname und Nachname des Studenten der EingefŸgt werden soll * */ void enqueue(stud_type** studenten_liste, int matnum, char vorname[20], char nachname[20]) { /* Deklariere benštigte Variablen */ stud_type *studenten_liste_neu; /* Hol Speicher auf dem Heap an fŸr den neuen Listen Eintrag */ studenten_liste_neu = (stud_type*) malloc(sizeof(stud_type)); /* BefŸll den Speicher */ { studenten_liste_neu->matnum = matnum; strcpy(studenten_liste_neu->vorname, vorname); strcpy(studenten_liste_neu->nachname, nachname); }; /* FŸg den neuen Eintrag in die Liste ein */ if (is_empty(studenten_liste)) { studenten_liste = &studenten_liste_neu; } else { (*studenten_liste)->next_student = &(*studenten_liste_neu); (*studenten_liste_neu).next_student = NULL; } /* Ist die Liste leer ? */ /* Sortier den Studenten aufsteigend nach Matrikelnummer ein */ } /* Lšschen eines Elementes. * * Bekommt einen Zeiger auf einen Zeiger der auf das 1. Element der Liste zeigt * Bekommt die MatNr des Studenten der zu lšschen ist * * Gibt 0 fŸr einen Fehler zurŸck * Gibt 1 fŸr erfolg zurŸck */ int dequeue(stud_type** studenten_liste, int matnum) { /* Deklariere benštigte Variablen */ /* PrŸfe Randbedingungen */ /* Finde den Studenten */ /* Lšsche den Studenten und gibt den Speicher frei */ /* Was muss passieren wenn das 1. Element gelšscht wird? */ /* Was ist wenn es nicht in der Liste ist? */ /* ... */ } /* Auslesen eines Elementes * * Bekommt zeiger auf den Listenstart * Bekommt matnr des Studenten der ausgelesen werden soll * * Schreibt Vorname und Nachname in vorname und nachname */ int get_student(stud_type* studenten_liste, int matnum, char vorname[20], char nachname[20]) { stud_type *curr; /* Durchmustern der DB */ curr = studenten_liste; while ((curr != NULL) && (curr->matnum < matnum)) curr = curr->next_student; if ((curr == NULL) || (curr->matnum != matnum)) /* RŸckgabewert: Fehler */ return 0; else { strcpy(vorname, curr->vorname); strcpy(nachname, curr->nachname); /* RŸckgabewert: OK */ return 1; } } /* Test der Listenfunktionen */ int main() { /* Initialisierung der Datenbank */ stud_type *studenten_liste = NULL; /* platz fŸr vorname */ char vorname[20]; /* platz fŸr nachname */ char nachname[20]; /* zeiger fŸr iteration */ stud_type *curr; printf(">>> Fuege neuen Studenten in die Liste ein: Bill Clinton [6666] ...\n"); enqueue(&studenten_liste, 6666, "Bill", "Clinton"); printf(">>> Fuege neuen Studenten in die Liste ein: Hillary Clinton [4711] ...\n"); enqueue(&studenten_liste, 4711, "Hillary", "Clinton"); printf(">>> Fuege neuen Studenten in die Liste ein: Newt Gingrich [9999] ...\n"); enqueue(&studenten_liste, 9999, "Newt", "Gingrich"); printf(">>> Test, ob die Matrikelnummer 0815 bereits erfasst wurde ...\n"); if (get_student(studenten_liste, 815, vorname, nachname)) printf(" Matrikelnummer %4i: %s %s\n", 815, vorname, nachname); else printf(" Matrikelnummer %4i ist unbekannt\n", 815); printf(">>> Fuege neuen Studenten in die Liste ein: Monica Lewinsky [0815] ...\n"); enqueue(&studenten_liste, 815, "Monica", "Lewinsky"); printf(">>> Loesche die Matrikelnummer 4711 ...\n"); if (dequeue(&studenten_liste, 4711)) printf(" Matrikelnummer %4i geloescht\n", 4711); else printf(" Matrikelnummer %4i war nicht erfasst\n", 4711); printf(">>> Test ob die Studentenliste leer ist ...\n"); if (is_empty(&studenten_liste)) printf(" Die Studentenliste ist leer \n"); else printf(" Die Studentenliste ist nicht leer \n"); printf(">>> Test, ob die Matrikelnummer 6666 bereits erfasst wurde ...\n"); if (get_student(studenten_liste, 6666, vorname, nachname)) printf(" Matrikelnummer %4i: %s %s\n", 6666, vorname, nachname); else printf(" Matrikelnummer %4i ist unbekannt\n", 6666); printf(">>> Loesche die Matrikelnummer 9998 ...\n"); if (dequeue(&studenten_liste, 9998)) printf(" Matrikelnummer %4i geloescht\n", 9998); else printf(" Matrikelnummer %4i war nicht erfasst\n", 9998); printf(">>> Loesche die Matrikelnummer 9999 ...\n"); if (dequeue(&studenten_liste, 9999)) printf(" Matrikelnummer %4i geloescht\n", 9999); else printf(" Matrikelnummer %4i war nicht erfasst\n", 9999); printf(">>> Gebe alle erfassten Studenten aus ...\n"); curr = studenten_liste; while (curr != NULL) { printf(" Matrikelnummer %4i: %s %s\n", curr->matnum, curr->vorname, curr->nachname); curr = curr->next_student; } return 0; }
-
Hallo,
welche Entwicklungsumgebung (IDE) benutzt du? Am besten, du arbeitest dich mal in den Debugger ein. Und dann setze mal in die enqueue()-Funktion einen Haltepunkt (breakpoint) und lass dir mal den Inhalt der Variablen 'studenten_liste' (sowie '*studenten_liste') anzeigen.
Tipp: die Zeile "studenten_liste = &studenten_liste_neu;" ist falsch...
-
Hallo LouBen3010,
ich habe mir deine enqueue Funktion mal kurz angeschaut und ein paar Kommentare dazugeschrieben:
LouBen3010 schrieb:
[...] void enqueue(stud_type** studenten_liste, int matnum, char vorname[20], char nachname[20]) { /* Deklariere benštigte Variablen */ stud_type *studenten_liste_neu; /* Hol Speicher auf dem Heap an fŸr den neuen Listen Eintrag */ studenten_liste_neu = (stud_type*) malloc(sizeof(stud_type)); /* BefŸll den Speicher */ { studenten_liste_neu->matnum = matnum; strcpy(studenten_liste_neu->vorname, vorname); strcpy(studenten_liste_neu->nachname, nachname); studenten_liste_neu->next_student=0; //sowas nur weglassen, wenn du ganz sicher bist was du machst... aber bei dir gibt es deswegen keine probleme }; /* FŸg den neuen Eintrag in die Liste ein */ if (is_empty(studenten_liste)) { //studenten_liste = &studenten_liste_neu; //studenten_liste_neu ist eine Stackvariable. Also ist die Speicheradresse von studenten_liste_neu, nachdem die Funktion enqueue verlassen wurde, nicht mehr gültig. Du willst sie aber abspeichern um sie später zu benutzen. Das untige ist, was du wahrscheinlich willst. Den Ort wo studenten_liste_neu hinzeigt abspeichern: *studenten_liste = studenten_liste_neu; } else { //das Einsortieren fehlt komplett. Deine Liste kann nur zwei Einträge beinhalten! Hier muss eine Schleife sein. (*studenten_liste)->next_student = &(*studenten_liste_neu); (*studenten_liste_neu).next_student = NULL; } /* Sortier den Studenten aufsteigend nach Matrikelnummer ein */ } [...]
Es gibt übrigends recht viel was man an dem ganzen Code verbessern kann.
-
LouBen3010 schrieb:
Der Professor ist der Meinung, dass 2 Vorlesungen á 1,5 Stunden ausreichen, um C zu programmieren.
Übliches Lehrergeschwätz. Ohne Definition von "C programmieren" einfach nur dämlich, einfach ignorieren.
Praxisirrelavante verk. Listen sind ein beliebtes Schulungsthema von Lehrer mit laienhaften Vorstellungen von Programmierung.->
Zugriff auf struct-Element über ein Objekt vom Typ Zeiger auf struct
zeigeraufstruct->structelement
.
Zugriff auf struct-Element über ein Objekt vom Typ struct
*
bei Deklarationen: Typfestlegung für "Zeiger auf..."
bei Ausdrücken: Dereferenzierung eines Zeigers
()
normaler Operator, "zeigeraufstruct->element" entspricht "(*zeigeraufstruct).element", meistens wird "->" vorgezogenvoid enqueue(stud_type** studenten_liste, int matnum, char vorname[20], char nachname[20]) { /* einfaches Einfügen immer am Ende; sortiertes Einfügen ist deutlich aufwändiger */ /* Definition */ stud_type *studenten_liste_neu; /* dyn. Speicherreservierung */ studenten_liste_neu = malloc(sizeof(*studenten_liste_neu)); studenten_liste_neu->matnum = matnum; strcpy(studenten_liste_neu->vorname, vorname); strcpy(studenten_liste_neu->nachname, nachname); studenten_liste_neu->next_student = NULL; /* wichtig! */ if (is_empty(studenten_liste)) { *studenten_liste = studenten_liste_neu; } else { stud_type *ende = *studenten_liste; /* ans Ende laufen und am Ende einhängen */ while( ende->next_student!=NULL ) ende=ende->next_student; ende->next_student = studenten_liste_neu; } }
-
Hallo,
dafür schon einmal vielen vielen Dank!
Ich hoffe ich begreif das alles was schneller.Es ist echt verrückt.
Nach den 2 Vorlesungen C gehts mit dem Thema Betriebssysteme weiter und es wird kein Wort mehr über C im praktischen Sinne verschwendet.
Jedoch scheint bei denen im Lehrplan zu stehen, dass wir C programmiert haben müssen.Gibt es gute "Tutorials" die mir relativ schnell die Basics in C vermitteln können?
Die weiteren Teile der Hausaufgabe sind nämlich Sortierungen von Namen oder Matrikelnummern von A-Z oder Z-A.. Das ist WAHNSINN.Wir Studenten sind einfach vollkommen überfordert!
Aber wenigstens bekomm ich ein paar Teilpunkte, weil enqueue wenigstens jetzt funktioniert.
-
Am besten, du besorgst dir ein Buch, s.a. in Linkliste für Neulinge hier im Forum.
Du kannst ersteinmal auch in die WikiBooks schauen: C Programming bzw. auch auf deutsch: C-Programmierung.
-
LouBen3010 schrieb:
Die weiteren Teile der Hausaufgabe sind nämlich Sortierungen von Namen oder Matrikelnummern von A-Z oder Z-A.. Das ist WAHNSINN.
Sortieren ist normalerweise nicht das Problem, aber das Sortieren von verk. Listen schon.
Vielleicht hilft es dir, wenn ich dir sage, dass ein nachträgliches Sortieren einer 'fertigen' verk.Liste nochmal einfacher wäre, als das sortierte Einfügen in eine wachsende Liste.
Zum nachträglichen Sortieren einer verk.Liste kannst du keine Algorithmen mit wahlfreiem Zugriff nehmen (also die Mehrzahl), aber z.B. Bubblesort.
-
LouBen3010 schrieb:
ich möchte mich erstmal kurz vorstellen. Seit dem WS 2013/14 studiere ich an der RWTH Aachen Informatik und bin zur Zeit im 2. Semester.
Der Professor ist der Meinung, dass 2 Vorlesungen á 1,5 Stunden ausreichen, um C zu programmieren.Ich sitze grade spaßenshalber in einer Vorlesung, in der der Prof. der Meinung ist, dass Null Vorlesungen dazu ausreichen (die Studenten können alle Java und Haskell, aber kein C). Und das ist auch richtig so: Praktisches Programmieren kann man nur für sich lernen, nicht durch Vorlesungen.
Antworten hast du ansonsten ja schon bekommen. Noch kurz dazu:
Ich wäre sehr dankbar, wenn vielleicht jemand so freundliche wäre und im selben Zuge erklären könnte, wann () um einen Pointer muss oder wann ein * dabei stehen muss und wann ein . zum Abruf des Inhalts gebraucht wird und wann ein ->.
Klammern benutzt du, wenn die Rangfolge der Operatoren dazu führen würde, dass ein Ausdruck anders interpretiert wird, als du gemeint hast. Das ist nichts anderes als bei Ausdrücken wie (3+4)*5 auch. Du musst halt wissen, dass bei etwas wie *ptr.feld der Elementzugriff (.) eine höhere Priorität hat als die Dereferenzierung (*). Wolltest du eigentlich erst ptr Dereferenzieren und dann auf ein Element des Ergebnisses zugreifen, schreibst du (*ptr).feld.
-> ist eine Abkürzung: ptr->feld bedeutet haargenau das gleiche wie (*ptr).feld, ist aber leichter zu schreiben und sieht besser aus.
-
Wutz schrieb:
LouBen3010 schrieb:
Die weiteren Teile der Hausaufgabe sind nämlich Sortierungen von Namen oder Matrikelnummern von A-Z oder Z-A.. Das ist WAHNSINN.
Sortieren ist normalerweise nicht das Problem, aber das Sortieren von verk. Listen schon.
Ja, immer, wenn man versucht, den Code vom Array-Sortieren eins-zu-eins zu übernehmen. Das wird hier passieren.
Wutz schrieb:
Vielleicht hilft es dir, wenn ich dir sage, dass ein nachträgliches Sortieren einer 'fertigen' verk.Liste nochmal einfacher wäre, als das sortierte Einfügen in eine wachsende Liste.
Bezweifle ich.
Wutz schrieb:
Zum nachträglichen Sortieren einer verk.Liste kannst du keine Algorithmen mit wahlfreiem Zugriff nehmen (also die Mehrzahl), aber z.B. Bubblesort.
Da muss ich ja a[i] und a[i+1] anfassen, gar einen Zeiger nach a[i] haben, einen von a[i] nach a[i+1] und einen von a[i+1], das würde mir ein wenig Angst machen.
Für mich wären Quicksort oder Mergesort feiner, da rede ich nur von zwei Listen mit enque/deque/is_empty/get und vielleicht ein wenig Rekursion (oder toDo-Liste).