Typdef Typ in Typdef Zugriff aber wie?
-
Mittels des Punktoperators kann man auf die Felder eines Structs zugreifen. Dafür braucht man natürlich ein Objekt des Struct-Typs. Du hast dich in deinen ganzen Zeigern selber verheddert: ScheduleList enthält einen Zeiger auf einen Zeiger auf ein Schedule. Und dann hast du einen Zeiger auf eine ScheduleList. Sind das nicht ein bisschen viele Indirektionen? Was willst du damit erreichen? Du weißt schon, dass in C nicht alles ein Zeiger sein muss (und sollte)? Eine Ebene von Indirektion könnte ich hier nachvollziehen, aber nicht drei.
-
Vielen Dank funktioniert einwandfrei
-
Sorry den zweiten Kommentar hab ich nicht gesehen. Ich versuche ZugId anStunde anMinute zu sortieren. Die eigentliche Aufgabe:
programm bahnhof.dat zug.dat fahrplan.dat zugnummer
Finde alle Züge, die den Zug zugnummer überholen und gib deren Zugnummer aus.
Implementierungstipp:
A ist Zug mit zugnummer
Für alle Züge B
Finde Bahnhof C, an dem A abfährt und an dem B später abfährt als A
(und zwar den darunter, an dem A am frühesten abfährt)
Wenn es einen solchen gibt:
Für alle Bahnhöfe D, an denen A nach C hält und an denen auch B hält
Wenn B an D früher hält als A, dann ist B ein Überholer von AEingelesen sind die Dateien alle. Bin mit den Pointern und der Syntax noch nicht ganz vertraut und den Algorithmus weiß ich auch noch nicht um die Aufgabe umzusetzen.
LG danke für eure Hilfe!
-
SmokeTM schrieb:
Eingelesen sind die Dateien alle.
Ich hoffe nicht per Einzel-realloc.
SmokeTM schrieb:
Bin mit den Pointern und der Syntax noch nicht ganz vertraut
Das ist normal für Anfänger, leider gilt das auch für viele sich selbst als Profi bezeichnende.
SmokeTM schrieb:
und den Algorithmus weiß ich auch noch nicht um die Aufgabe umzusetzen.
Das sieht man. Du hast an qsort gar keine compare-Callback-Funktion übergeben.
Informiere dich darüber, wie qsort funktioniert.Prinzipiell ist dein Datendesign schon OK, ein Objekt vom Typ Liste, was auf die Elemente verweist und die Anzahl kennt:
typedef struct { int ZugId; // Darauf möchte ich zugreifen int bahnhofId; int anStunde; // Darauf möchte ich zugreifen int anMinute; // Darauf möchte ich zugreifen int abStunde; int abMinute; int anzahlAussteiger; int anzahlEinsteiger; } Schedule; typedef struct { Schedule *schedules; // Über das hier int count; int allocated; } List; int cmp(const void*a, const void*b) { /* aufsteigend sortieren nach 2 rangungleichen Kriterien */ const Schedule *x = a, *y = b; if (x->anStunde != y->anStunde) return x->anStunde <= y->anStunde ? -1 : 1; return x->anMinute <= y->anMinute ? -1 : 1; } int main() { List list = { (Schedule[]) { {3,3,3,3,3,3,3,3},{1,1,1,1,1,1,1,1},{2,2,2,2,2,2,2,2},{0},{9,9,9,9,9,9,9,9} },5 }; qsort(list.schedules, list.count, sizeof*list.schedules, cmp); for (int i = 0; i < list.count; ++i) printf("%d\n", list.schedules[i].ZugId); return 0; }
-
Hallo Wutz danke für deinen Code ich hab den Code in mein Programm übernommen. Irgendwie glaub ich aber das die Sortierung nicht stimmt es ist jetzt alles vermischt.
Ich dachte die anStunde und anMinute sollte nach ZugId sortiert sein, also in etwa so.
ZugId | anStunde | anMinute
250 | 1 | 0
250 | 2 | 10
250 | 3 | 25
250 | 5 | 50
300 | 1 | 0
300 | 4 | 10
300 | 5 | 35Momentan wird ZugId jedoch vermischt. Daher denke ich passt es dann mit der anStunde und anMinute nicht mehr überein?
Umgeschriebener Code schedule.c:
void sortScheduleList (ScheduleList *sl){ qsort(sl->schedules, sl->count, sizeof*sl->schedules, cmp); for (int i = 0; i < sl->count; ++i) printf("ID: %d anStunde: %d anMinute %d \n", sl->schedules[i]->ZugId, sl->schedules[i]->anStunde, sl->schedules[i]->anMinute); } int cmp(const void*a, const void*b) { /* aufsteigend sortieren nach 2 rangungleichen Kriterien */ const Schedule *x = a, *y = b; if (x->anStunde != y->anStunde) return x->anStunde <= y->anStunde ? -1 : 1; return x->anMinute <= y->anMinute ? -1 : 1; }
schedule.h
typedef struct{ int ZugId; int bahnhofId; int anStunde; int anMinute; int abStunde; int abMinute; int anzahlAussteiger; int anzahlEinsteiger; } Schedule; typedef struct{ Schedule **schedules; int count; int allocated; } ScheduleList; ScheduleList *newScheduleList (); Schedule *newSchedule (ScheduleList *sl); void readScheduleList (ScheduleList *sl, char *fileName); void sortScheduleList (ScheduleList *sl); int cmp(const void*a, const void*b);
LG Danke für deine Hilfe Wutz
-
Mein vorheriger Beitrag gilt nach wie vor.
SeppJ schrieb:
ScheduleList enthält einen Zeiger auf einen Zeiger auf ein Schedule. Und dann hast du einen Zeiger auf eine ScheduleList. Sind das nicht ein bisschen viele Indirektionen?
Beachte, wie Wutz es besser gemacht hat.
-
Ok wenn ich den einen Zeiger von schedules wegnehme funktioniert das einlesen nicht daher poste ich jetzt den ganzen code.
schedule.h
typedef struct{ int ZugId; int bahnhofId; int anStunde; int anMinute; int abStunde; int abMinute; int anzahlAussteiger; int anzahlEinsteiger; } Schedule; typedef struct{ Schedule **schedules; int count; int allocated; } ScheduleList; ScheduleList *newScheduleList (); Schedule *newSchedule (ScheduleList *sl); void readScheduleList (ScheduleList *sl, char *fileName); void sortScheduleList (ScheduleList *sl); int cmp(const void*a, const void*b);
schedule.c
#include <stdio.h> #include <stdlib.h> #include "schedule.h" ScheduleList *newScheduleList () { ScheduleList *sl = (ScheduleList *) malloc (sizeof (ScheduleList)); sl->count = 0; sl->allocated = 10; sl->schedules = (Schedule **) calloc (sl->allocated, sizeof (Schedule *)); return sl; } Schedule *newSchedule (ScheduleList *sl) { if (sl->count >= sl->allocated){ sl->allocated *= 2; sl->schedules = (Schedule **) realloc (sl->schedules, sl->allocated * sizeof (Schedule *)); } Schedule *aa = (Schedule *) malloc (sizeof (Schedule)); sl->schedules[sl->count++] = aa; return aa; } void readScheduleList (ScheduleList *sl, char *fileName) { FILE *file = fopen (fileName, "r"); if (file == NULL) { perror (fileName); exit (1); } int r, id; do{ r = fscanf (file, "%d", &id); //printf("r: %d", r); if (r != EOF){ //printf("r: %d", r); Schedule *aa = newSchedule (sl); aa->ZugId = id; r = fscanf (file, "%d %d %d %d %d %d %d", &aa->bahnhofId, &aa->anStunde, &aa->anMinute, &aa->abStunde, &aa->abMinute, &aa->anzahlAussteiger, &aa->anzahlEinsteiger); printf("ID: %d bahnhofId: %d anStunde: %d anMinute: %d abStunde: %d abMinute: %d anzahlAussteiger: %d anzahlEinsteiger: %d \n", id, aa->bahnhofId, aa->anStunde, aa->anMinute, aa->abStunde, aa->abMinute, aa->anzahlAussteiger, aa->anzahlEinsteiger); } } while (r != EOF); fclose (file); } void sortScheduleList (ScheduleList *sl){ qsort(sl->schedules, sl->count, sizeof*sl->schedules, cmp); for (int i = 0; i < sl->count; ++i) printf("ID: %d anStunde: %d anMinute %d \n", sl->schedules[i]->ZugId, sl->schedules[i]->anStunde, sl->schedules[i]->anMinute); } int cmp(const void*a, const void*b) { /* aufsteigend sortieren nach 2 rangungleichen Kriterien */ const Schedule *x = a, *y = b; if (x->anStunde != y->anStunde) return x->anStunde <= y->anStunde ? -1 : 1; return x->anMinute <= y->anMinute ? -1 : 1; }
programm.c
#include <stdio.h> #include <stdlib.h> #include "train.h" #include "trainstation.h" #include "schedule.h" int main(int argc, char *argv[]){ TrainList *tl = newTrainList (); TrainStationList *tsl = newTrainStationList (); ScheduleList *sl = newScheduleList (); readScheduleList (sl, argv[3]); readTrainList (tl, argv[2]); readTrainStationList (tsl, argv[1]); sortScheduleList(sl); return 0; }
-
Obwohl Zeiger in C die Grundlage bilden, heißt das nicht, dass man überall wo man nicht mehr weiter weiß auch welche verwenden soll.
Natürlich musst du deinen bisherigen Code anpassen, wenn du das Datendesign veränderst.Die Beispielsortierung habe ich dir nur gezeigt, weil ich es für sinnvoll hielt, für deinen Anwendungsfall die Ankunftszeiten zu sortieren. Und da macht eine gleichzeitige Sortierung nach ZugId keinen Sinn.
Den fachlichen Algorithmus musst du dir schon selbst überlegen, wir können dir bei technischen Fragen, Daten- und Programmdesignfragen helfen.
Wie ich dir gezeigt habe, ich es völlig ausreichend, mit der Liste selbst und nicht einem Zeiger darauf zu operieren.
Ebenso hatnewSchedule
eine Zeigerebene zuviel, du operierst mit einer Folge von Zeigern auf struct wo eine Folge von struct ausreicht.
Dein Einlesen ist auch falsch. (um dem häufigen Anfängerargument: "läuft doch" vorzubeugen: nein, ein Code ist nicht korrekt, wenn er mit Spieldaten richtige Ergebnisse liefert).Ich empfehle dir dringend:
Priorisiere die Implementierung des fachlichen Problems (Finde alle Züge, die den Zug zugnummer überholen und gib deren Zugnummer aus.).
Dazu kannst du den von mir gezeigten Beispielcode verwenden, indem du die dortigen beispielhaften 5 Züge mit sinnvollen Testwerten vorbelegst: wenn das dann läuft, kannst du dein Datenlesen immer noch verbessern.
-
Danke für deine Antwort ich hab jetzt noch ein mal von vorne begonnen. Momentan sieht es so aus.
programm.c
#include <stdio.h> #include <stdlib.h> #include "schedule.h" int main() { ScheduleList list = newScheduleList(); ScheduleList list = { (Schedule[]) { {963,8980,21,39,21,41,28,7},{963,6996,21,50,21,51,7,35},{963,8335,23,4,0,0,35,0},{79090,7281,0,0,20,54,0,36},{79090,4286,1,1,20,56,0,9} },5 }; qsort(list.schedules, list.count, sizeof*list.schedules, cmp); for (int i = 0; i < list.count; ++i) printf("%d %d %d\n", list.schedules[i].ZugId, list.schedules[i].anStunde, list.schedules[i].anMinute); return 0; }
schedule.h
typedef struct { int ZugId; int bahnhofId; int anStunde; int anMinute; int abStunde; int abMinute; int anzahlAussteiger; int anzahlEinsteiger; } Schedule; typedef struct { Schedule *schedules; int count; int allocated; } ScheduleList; int cmp(const void*a, const void*b);
schedule.c
#include <stdio.h> #include <stdlib.h> #include "schedule.h" int cmp(const void*a, const void*b) { const Schedule *x = a, *y = b; if (x->anStunde != y->anStunde) return x->anStunde <= y->anStunde ? -1 : 1; return x->anMinute <= y->anMinute ? -1 : 1; }
Funktioniert auch einwandfrei, jetzt ist nur die Frage was an meinem einlesen falsch war oder eben verbesserungswürdig?
LG
-
Dein Algorithmus ist noch lange nicht fertig, aber das solltest du selbst wissen.
Beim Einlesen machst du den klassischen Anfängerfehler:
du benutzt fscanf und EOF/feof:
fscanf/scanf/sscanf liefern die Anzahl der erfolgreich gelesenen Werte zurück; dies ignorierst du aber indem du lediglich auf !=EOF (d.h. !=-1) testest.Benutze Positivlogik bei fscanf
alsowhile( fscanf(...)==8 ) { }
das funktioniert immer und hat die EOF-Prüfung inklusive.
-
wieso kann ich das nicht so schreiben?
ScheduleList newScheduleList () { ScheduleList sl = (ScheduleList ) malloc (sizeof (ScheduleList)); sl.count = 0; sl.allocated = 10; sl.schedules = (Schedule *) calloc (sl.allocated, sizeof (Schedule *)); return sl; }
error: conversion to non-scalar type requested
Ich komm einfach nicht weiter bin am verzweifeln. Das mit der PositivLogik hab ich erst recht nicht verstanden? Das heißt einen counter mitlaufen lassen und dagegen prüfen?
LG
-
ScheduleList newScheduleList () { ScheduleList sl = (ScheduleList ) malloc (sizeof (ScheduleList)); }
Lern C, anstatt hier immer nur doof zu fragen, warum X nicht funktioniert.
-
malloc
gibt einen Zeiger zurück. Den mag man gerade noch so in einen int-Typ Wandel, aber in einestruct
geht halt nicht.Es ist immer gut, auch die Zeile, auf die sich der Fehler bezieht, genau zu kennzeichnen.
Der Compiler macht das mit Zeilen- (und Spalten-)nummer.Durch die Definition von
ScheduleList sl
hast du schon den Speicher, den du brauchst (die komplette struct)
Oder du machstScheduleList *sl = malloc ..
, aber dann sind die Zugriffe auf die Member mit . falsch.SmokeTM schrieb:
Das mit der PositivLogik hab ich erst recht nicht verstanden? Das heißt einen counter mitlaufen lassen und dagegen prüfen?
Nein.
scanf
zählt für dich.
Schau dir mal genau an, was der Rückgabewert vonscanf
bedeutet:[url] http://www.cplusplus.com/reference/cstdio/scanf/[/url]Wenn du keine 8 Werte bekommst, ist was mit der Eingabe falsch.
Egal ob EOF oder fehlende Werte. Es bringt nichts mehr weiterzulesen.
-
Hab nun das file einlesen geändert.
ScheduleList newScheduleList () { ScheduleList sl; sl.count = 0; sl.allocated = 10; sl.schedules = (Schedule *) calloc (sl.allocated, sizeof (Schedule *)); return sl; } Schedule newSchedule (ScheduleList sl) { if (sl.count >= sl.allocated){ sl.allocated *= 2; sl.schedules = (Schedule *) realloc (sl.schedules, sl.allocated * sizeof (Schedule *)); } Schedule aa; sl.schedules[sl.count++] = aa; return aa; } void readScheduleList (ScheduleList sl, char *fileName) { FILE *file = fopen (fileName, "r"); if (file == NULL) { perror (fileName); exit (1); } int id; Schedule aa = newSchedule (sl); while(fscanf(file, "%d %d %d %d %d %d %d %d", &aa.ZugId, &aa.bahnhofId, &aa.anStunde, &aa.anMinute, &aa.abStunde, &aa.abMinute, &aa.anzahlAussteiger, &aa.anzahlEinsteiger) == 8) { printf("ID: %d bahnhofId: %d anStunde: %d anMinute: %d abStunde: %d abMinute: %d anzahlAussteiger: %d anzahlEinsteiger: %d \n", aa.ZugId, aa.bahnhofId, aa.anStunde, aa.anMinute, aa.abStunde, aa.abMinute, aa.anzahlAussteiger, aa.anzahlEinsteiger); } fclose (file); }
Jetzt stellt sich mir aber die Frage warum das so funktioniert den ich erstell hier nur eine Instanz von Schedule. Die Ausgabe im Terminal scheint aber richtig zu sein.
War das einlesen von euch so gemeint, wie ich es jetzt umgesetzt habe?
LG
-
SmokeTM schrieb:
Jetzt stellt sich mir aber die Frage warum das so funktioniert
Tut es nicht.
SmokeTM schrieb:
Die Ausgabe im Terminal scheint aber richtig zu sein.
Überleg mal, wann du welche Daten ausgibst.
(Woher weißt du, wieviel Zeilen gelesen wurden?)Du bringst Zeiger und Objekte gehörig durcheinander.