Typdef Typ in Typdef Zugriff aber wie?


  • Mod

    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 hat newSchedule 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
    also

    while( 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 eine struct 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 machst ScheduleList *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 von scanf 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.


Anmelden zum Antworten