Pointer auf struct, dessen Elemente Pointer auf andere structs sind



  • Hi Leute,

    habe ein Problem und komme damit leider nicht klar 😕

    Habe einen pointer auf eine struct, darin habe ich pointer auf andere structs. Und kann auf diese Elemente nicht zugreifen. Könnt Ihr mir vielleicht helfen?

    Ein Beispielauszug:

    typedef struct
    {
    
        struct TTime *time;
        struct TDate *date;
        char *desc;
        char *Location;
        struct TTime *duration;
    
    } TAppointment;
    
    typedef struct
    {
    
        int day;
        int month;
        int year;
        enum WD {Su,Mo,Tu,Wd,Th,Fr,Sa} Day_of_Week;
    
    } TDate;
    
    int test(TAppointment *ter)
    {
    
    ter = (TAppointment*)malloc(sizeof(TAppointment));
    
    ter->date->month = 11; //test
    
    return 1;
    }
    

  • Mod

    struct TDate
    hat nichts mit einer unbenannten Struktur zu tun, für die du einen (zufällig gleichen) typedef-Namen deklariert hast.



  • Es ist guter Stil

    typedef struct StrukturName { ... } StrukturName;
    

    zu schreiben, dann geht beides, struct StrukturName und StrukturName . Ausserdem gehen Forwärtsdeklarationen.



  • Die Zeiger in deinem neu alloziierten Struct sind ja auch nicht initialisiert.

    ter       = malloc(sizeof(TAppointment));
    ter->date = malloc(sizeof(TDate));
    
    ...
    

    wird funktionieren. Das (und die resultierende Fehlerbehandlung) wäre dann sinnvoll in eine Funktion auszulagern, ebenso wie eine andere anzulegen, die den Wust wieder freigibt. Allerdings dürfte es in der Regel sinnvoller sein, den Verweis sein zu lassen und

    typedef struct
    {
    
        struct TTime time;
        struct TDate date;
        char *desc;
        char *Location;
        struct TTime duration;
    
    } TAppointment;
    

    zu schreiben. Um die Strings variabler Länge wirst du dich aber wohl händisch kümmern müssen.



  • Hi Leute, vielen Dank für eure Hilfe. Jetzt funktioniert das in etwa ^^

    Könnt ihr eventuell nochmal drüber gucken, denn bei der Ausgabe werden mir nicht die richtigen Werte angezeigt. Der Fehler liegt in func.c.
    Die Ausgabe soll ungefähr diese Form haben: "Tag", der xx.xx.xx ... weiter unten die Termine. In der Methode, wo ich das Datum auslese, habe ich getestet und die Werte werden richtig übernommen. Hab schon einige Kommilitonen gefragt, aber sie wissen auch nicht weiter. Irgendwas mache ich bei der Übergabe falsch, aber ich weiß nicht was 😕

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /*******************************************************
     * void clearbuffer
     *
     * Funktion:  löscht den tastaturpuffer
     * ****************************************************/
    void clearBuffer()
    {
        while (getchar() != '\n')
            ;
    }
    
    /*******************************************************
     * void clearScreen
     *
     * Funktion:  löscht das Bildschrim
     * ****************************************************/
    void clearScreen()
    {
        system("cls");
    }
    
    /*******************************************************
     * void waitForEnter
     *
     * Funktion:  bittet und wartet auf eingabe eines Enter
     * ****************************************************/
    void waitForEnter()
    {
        printf("\nBitte Eingabetaste druecken ...");
        clearBuffer();
    }
    
    /*******************************************************
     * void printline
     *
     * Funktion:  schreibt ein zeichen in eine zeile
     * Parameter: -Zeichen das geschrieben werden soll
     *                        -Wieoft das Zeichen geschriebenwird
     * ****************************************************/
    void printLine(char c, int n)
    {
        for(; n>0; n--)
        {
            printf("%c", c);
        }
        printf("\n");
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "tools.h"
    
    int menu(char *title,char *menu_p[],int number)
    {
    
        int input = 0;
        char eingabe;
    
        while(!(input >= 1 && input <= number))
        {
    
            clearScreen();
            printf("%s\n",title);
            printLine('-',strlen(title));
            printf("\n");
    
            int i;
            for(i=1; i<=number; i++)
            {
    
                printf("%i. %s\n",i,menu_p[i-1]);
    
            }
            printf("\nIhre Wahl: ");
    
            scanf("%c",&eingabe);
    
            if(eingabe >= 48 && eingabe <= 57){
                input = atoi(&eingabe);
            }
        }
        return input;
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "calendar.h"
    #include "datastructure.h"
    #include "menu.h"
    
    int main()
    {
        char *menupunkt[7];
        menupunkt[0] = "Neuen Termin anlegen";
        menupunkt[1] = "Termin bearbeiten";
        menupunkt[2] = "Termin loeschen";
        menupunkt[3] = "Termin suchen";
        menupunkt[4] = "Termine sortieren";
        menupunkt[5] = "Termine auflisten";
        menupunkt[6] = "Programm beenden";
    
        int c = 0;
    
        while(c == 0)
        {
    
            switch(menu("Terminverwaltung V 1.0",menupunkt,7))
            {
    
            case 1:
                createAppointment();
                break;
    
            case 2:
                editAppointment();
                break;
    
            case 3:
                deleteAppointment();
                break;
    
            case 4:
                searchAppointment();
                break;
    
            case 5:
                sortCalendar();
                break;
    
            case 6:
                listCalendar();
                break;
    
            case 7:
                c = 1;
                break;
    
            }
        }
    
        return 0;
    }
    
    #include <stdio.h>
    #include "datastructure.h"
    #include <string.h>
    #include "calendar.h"
    #include <stdlib.h>
    #include "tools.h"
    /*Rückgabe: 1 für Schaltjahr
                0 für nicht Schaltjahr */
    int isLeapYear(int jahr)
    {
        return !(jahr % 400) || (!(jahr % 4) && (jahr % 100));
    
    }
    
    /*Rückgabe: 1 für gültiges Datum
                0 für nicht gültiges Datum */
    int isDateValid(int jahr,int monat,int tag)
    {
        if (jahr==0 || monat == 0 || tag ==0)
            return 0;
    
        if ((monat==1) || (monat==3) || (monat==5) || (monat==7) || (monat==8) || (monat==10) || (monat==12))
            return (tag<32);            // in diesen Monaten gibt es maximal nur 31 Tage
        else if ((monat==4) || (monat==6) || (monat==9) || (monat==11))
            return (tag<31);            // in diesen Monaten gibt es maximal nur 30 Tage
        else if (monat==2)              // Prüfung für Februar
        {
            if (isLeapYear(jahr)!=0)
                return (tag<30);        // im Schaltjahr hat der Februar 29 Tage
            else
                return (tag<29);        // außer Schaltjahr hat der Februar 28 Tage
        }
        else
            return 0;
    }
    
    int isTimeValid(int h, int m){
    
    if(h > 24)
        return 0;
    
    if(m > 60)
        return 0;
    
       return 1;
     }
    
    /*Rückgabe: 1 für gültiges Datum
                0 für nicht gültiges Datum */
    int getDateFromString(TAppointment *ter, char* Input )
    {
    
    int tag, monat, jahr;
        char* date = Input, *s;
        int temp = 0;
    
        for ( s = date; *s != '.'; s++ )
            temp *= 10, temp += *s - '0';
        tag = temp;
        temp = 0;
    
        for ( s++; *s != '.'; s++ )
            temp *= 10, temp += *s - '0';
        monat = temp;
        temp = 0;
    
        for ( s++; *s; s++ )
            temp *= 10, temp += *s - '0';
        jahr = temp;
    
        if (isDateValid(jahr,monat,tag)){
    
        //  ter = (TAppointment*)malloc(sizeof(TAppointment));
         ter = malloc(sizeof(TAppointment));
         ter->date = malloc(sizeof(TDate));
    
           ter->date->day = tag;
           ter->date->month = monat;
           ter->date->year = jahr;
    
           //Wochentagsberechnung
    
        /** Zeller's congruence for the Gregorian calendar. **/
       /** With 0=Monday, ... 5=Saturday, 6=Sunday         **/
       if (monat < 3) {
          monat += 12;
          jahr--;
       }
        ter->date->day_of_week = ((13*monat+3)/5 + tag + jahr + jahr/4 - jahr/100 + jahr/400) % 7;
    
    return 1;
     //WOchentagsberchnunng zu ende
    
        }else{
            return 0;
        }
    
    }
    
    /*Rückgabe: 1 für gültiges Datum
                0 für nicht gültiges Datum */
    int getDate(TAppointment *termin)
    {
        char Input[20];
        scanf("%19[0123456789.]",Input);            // Eingabe sollte so sein: DD.MM.YYYY
        return getDateFromString(termin,Input);
    }
    
    /*Rückgabe: 1 für gültiges Datum
                0 für nicht gültiges Datum */
    
    int getTimeFromString(TAppointment *termin, char* Input )
    {
    
    int h, m;
        char* date = Input, *s;
        int temp = 0;
    
        for ( s = date; *s != '.'; s++ )
            temp *= 10, temp += *s - '0';
        h = temp;
        temp = 0;
    
        for ( s++; *s; s++ )
            temp *= 10, temp += *s - '0';
        m = temp;
    
        if (isTimeValid(h,m)){
    
    //termin = malloc(sizeof(TAppointment));
         termin->time = malloc(sizeof(TTime));
    
           termin->time->hours = h;
           termin->time->mins = m;
    
    return 1;
    
        }else{
            return 0;
        }
    
    }
    
    /*Rückgabe: 1 für gültiges Datum
                0 für nicht gültiges Datum */
    int getTime(TAppointment *termin)
    {
        char Input[20];
        scanf("%19[0123456789.]",Input);            // Eingabe sollte so sein: DD.MM.YYYY
        return getTimeFromString(termin,Input);
    }
    
    int getText(char *Request,  char **P, int MaxLen)
    {
        char *Eingabe = calloc(MaxLen + 1, sizeof(char));
        char Format[20];
        int scanErg;
        int Len;
        *P = NULL;
    
        if(Eingabe)
        {
            printf("%s", Request);
            sprintf(Format, "%%%i[^\n]", MaxLen);
            do
            {
    
                scanErg = scanf(Format, Eingabe);
                clearBuffer();
                if(scanErg == 1)
                {
                    Len = strlen(Eingabe);
                    if(Len > 0)
                    {
                        *P = malloc((Len + 1)*sizeof(char));
                        if(*P)
                            strcpy(*P, Eingabe);
                        else
                        {
                            free(Eingabe);
                            return 0;
                        }
                    } else
                    {
                        scanErg = 0;
                    }
                }
            } while(scanErg == 0);
            free(Eingabe);
            return 1;
        } else
            return 0;
    }
    
    /*************************************************************************************************/
    /* Datum formatiert ausgeben */
    void printDate(TDate **T)
    {
        printf("\n");
    
        switch((*T)->day_of_week){
         case 0: printf("Sonntag");
                 break;
        case 1: printf("Montag");
                break;
        case 2: printf("Dienstag");
                break;
        case 3: printf("Mittwoch");
                break;
        case 4: printf("Donnerstag");
                break;
    
        case 5: printf("Freitag");
               break;
    
        case 6: printf("Samstag");
                 break;
    
        }
    
        printf(", der ");
        printf("%0d.", (*T)->day);
        printf("%0d.",(*T)->month );
        printf("%0d", (*T)->year );
        printf("\n");
        printLine('-', 30);
    
    }
    
    /*************************************************************************************************/
    /* Zeit formatiert ausgeben */
    void printTime(TTime **PT)
    {
    
        printf("%02i:", (*PT)->hours);
        printf("%02i", (*PT)->mins);
    
    }
    
    void printAppointment(TAppointment *PCal)
    {
        int i;
    
        printf("   ");
        printTime(&(*PCal).time);
        printf(" -> ");
        printf("%-15s",(*PCal).Location);
        printf(" | ");
        for (i = 0; i < 50 && ((*PCal).desc[i]); i++)
        {
            printf("%.1s",&(*PCal).desc[i]);
        }
        if (i == 50)
            printf("...");
        printf("\n");
    }
    
    #include <stdio.h>
    #include <stdlib.h>
    #include "datastructure.h"
    #include "tools.h"
    #include "func.h"
    
    int AppointmentCount = 0;
    TAppointment calendar[MAXAPPOINTMENTS];
    
    void createAppointment()
    {
        clearScreen();
        clearBuffer();
        TAppointment termin;
        printf("Datum:        ");
        while (!getDate(&termin))        // Schleife, bis ein gültiges Datum eingegeben wurde.
        {
            clearBuffer();                 // clear buffer, sorn gibt es Problem mit dem "scanf".
            printf("Das eingegebene Datum ist ungueltig!\nGeben Sie bitte noch mal ein gueltiges Datum ein: ");
        }
    
        //-------
        clearBuffer();
    
        printf("Uhrzeit:      ");
        while (!getTime(&termin))        // Schleife, bis ein gültiges Datum eingegeben wurde.
        {
            clearBuffer();                 // clear buffer, sorn gibt es Problem mit dem "scanf".
            printf("Das eingegebene Uhrzeit ist ungueltig!\nGeben Sie bitte noch mal eine gueltige Uhrzeit ein: ");
        }
    
        //________
    
        char Beschreibung[] = "Beschreibung   :";
        while (!getText(Beschreibung,&termin.desc,100)){
    
            printf("Zu lang! \n Bitte nochmal eingeben: ");
        }
    
        //----------
        char Ort[] = "Ort         :";
        while (!getText(Ort,&termin.Location,50)){
            clearBuffer();
        }
    
    calendar[AppointmentCount] = termin;
    
    AppointmentCount++;
        waitForEnter();
    }
    void editAppointment()
    {
        printf("editAppointment \n");
        clearBuffer();
        waitForEnter();
    }
    void deleteAppointment()
    {
        printf("deleteAppointment \n");
        clearBuffer();
        waitForEnter();
    }
    void searchAppointment()
    {
        printf("searchAppointment \n");
        clearBuffer();
        waitForEnter();
    }
    void sortCalendar()
    {
        printf("sortCalendar \n");
        clearBuffer();
        waitForEnter();
    }
    
    /* Termine anzeigen */
    
    /* Termine anzeigen */
    void listCalendar()
    {
    
        waitForEnter();
        char Title[] = "Liste der Termine";
        int i, j, k;
        TAppointment **PCalSort= malloc(AppointmentCount * sizeof(int)); // Sortierzeiger
        TAppointment *tmp;  // Zwischenspeicher zur Umsortierung
    
        clearScreen();
        printf("%s\n", Title);
        printLine('=', sizeof(Title));
        if (AppointmentCount)          // wenn mind. ein Termin eingetragen
        {
            // jedem Terminzeiger einen Zeiger zuweisen
            for (i = (AppointmentCount -1); i >= 0; i--)
            {
                PCalSort[i] = &calendar[i];
            }
            // Bubble- Sort der Terminzeiger; Vgl.kriterien haben aufsteigende Prioritaeten
            for ( i = (AppointmentCount -1); i >=0; i--)
            {
                for (j = 0; j < i; j++)     // Termine durchlaufen, wenn noetig-> vertauschen
                {
                    if (PCalSort[j]->time->mins > PCalSort[j+1]->time->mins)
                    {
                        tmp = PCalSort[j];
                        PCalSort[j] = PCalSort[j+1];
                        (PCalSort[j+1]) = tmp;
                    }
                }
            }
            for ( i = (AppointmentCount -1); i >=0; i--)
            {
                for (j = 0; j < i; j++)
                {
                    if (PCalSort[j]->time->hours > PCalSort[j+1]->time->hours)
                    {
                        tmp = PCalSort[j];
                        PCalSort[j] = PCalSort[j+1];
                        (PCalSort[j+1]) = tmp;
                    }
                }
            }
            for ( i = (AppointmentCount -1); i >=0; i--)
            {
                for (j = 0; j < i; j++)
                {
                    if (PCalSort[j]->date->day > PCalSort[j+1]->date->day)
                    {
                        tmp = PCalSort[j];
                        PCalSort[j] = PCalSort[j+1];
                        (PCalSort[j+1]) = tmp;
                    }
                }
            }
            for ( i = (AppointmentCount - 1); i >=0; i--)
            {
                for (j = 0; j < i; j++)
                {
                    if (PCalSort[j]->date->month > PCalSort[j+1]->date->month)
                    {
                        tmp = PCalSort[j];
                        PCalSort[j] = PCalSort[j+1];
                        (PCalSort[j+1]) = tmp;
                    }
                }
            }
            for ( i = (AppointmentCount - 1); i >= 0; i--)
            {
                for (j = 0; j < i; j++)
                {
                    if (PCalSort[j]->date->year > PCalSort[j+1]->date->year)
                    {
                        tmp = PCalSort[j];
                        PCalSort[j] = PCalSort[j+1];
                        (PCalSort[j+1]) = tmp;
                    }
                }
            }
            // ersten Eintrag als Referenzobjekt zuerst ausgeben
            printDate(&PCalSort[0]->date);
            printAppointment(PCalSort[0]);
            i = 1;
            k = 1;      // erster Eintrag muss beruecksichtigt werden!
            // sortierte Liste ausgeben, gleiche Daten tabellarisch
            do
            {
                for (j = k; (j < 15) && (i < AppointmentCount); j++, i++)
                {
                    if ((PCalSort[i]->date->year == PCalSort[i - 1]->date->year) &&
                    (PCalSort[i]->date->month == PCalSort[i - 1]->date->month) &&
                    (PCalSort[i]->date->day == PCalSort[i - 1]->date->day))
                    {
                        printAppointment(PCalSort[i]);
                    }else
                    {
                    printDate(&PCalSort[i]->date);
                    printAppointment(PCalSort[i]);
                    }
                }
                k = 0;
                if ((AppointmentCount > 15) && (j == 15))      // alle 15 Termine Eingabetaste
                    waitForEnter();
            } while (i < AppointmentCount);
        } else
            printf("Keine Termine eingetragen!\n");
    
            waitForEnter();
    }
    
    #ifndef CALENDAR_H_INCLUDED
    #define CALENDAR_H_INCLUDED
    
    void createAppointment();
    void editAppointment();
    void deleteAppointment();
    void searchAppointment();
    void sortCalendar();
    void listCalendar();
    
    #endif // CALENDAR_H_INCLUDED
    
    #ifndef DATASTRUCTURE_H_INCLUDED
    #define DATASTRUCTURE_H_INCLUDED
    
    #define MAXAPPOINTMENTS 100
    
    typedef struct TTime
    {
    
        int hours;
        int mins;
    
    } TTime;
    
    typedef struct TDate
    {
    int nutte;
        int day;
        int month;
        int year;
        int day_of_week;  //So:0 Mo:1 ....
        //enum WD {Su,Mo,Tu,Wd,Th,Fr,Sa} Day_of_Week;
    
    } TDate;
    
    typedef struct TAppointment
    {
     int nutte;
        struct TTime *time;
        struct TDate *date;
        char *desc;
        char *Location;
        struct TTime *duration;
    
    } TAppointment;
    
    extern int AppointmentCount;
    extern TAppointment calendar[MAXAPPOINTMENTS];
    
    #endif // DATASTRUCTURE_H_INCLUDED
    
    #ifndef function_H_INCLUDED
    #define function_H_INCLUDED
    
    int isLeapYear(int jahr);
    int isDateValid(int jahr,int monate,int tag);
    int isTimeValid(int h, int m);
    int getDate(TAppointment *termin);
    int getTime(TAppointment *termin);
    int getDateFromString(TAppointment *termin, char* Input );
    int getTimeFromString(TAppointment *termin, char* Input );
    int getText(char *Request,  char **P, int MaxLen);
    void printDate(TDate **T);
    //void printDate(TAppointment *T);
    void printTime(TTime **PT);
    void printAppointment(TAppointment *PCal);
    #endif // FUNCTION_H_INCLUDED
    
    #ifndef MENU_H_INCLUDED
    #define MENU_H_INCLUDED
    
    int menu(char *title,char *menu_p[],int number);
    
    #endif // MENU_H_INCLUDED
    
    #ifndef FUNKTION_H_INCLUDED
    #define FUNKTION_H_INCLUDED
    
    // Funktionsdeklaration
    void clearBuffer();
    void clearScreen();
    void waitForEnter();
    void printLine(char c, int n);
    
    #endif
    


  • Die printTime() Methode funktioniert und liefert auch nach dem aufrufen in listCalendar() richtige Werte zurück. Nur printDate liefer falsche Werte.


  • Mod

    Glaubst du im Ernst, das guckt sich jemand an? Lies dir den ersten und dritten Link in meiner Signatur durch.



  • An getDatumFromString übergibst du einen Zeiger ter, den veränderst du in der Funktion, und erwartest, dass sich das beim Aufrufer wiederspiegelt. Da C aber grundsätzlich alle Argumente by-value übergibt, bleibt die Veränderung nur lokal innerhalb der Funktion sichtbar. Du müsstest noch eine Zeigerindirektion einführen:

    int getDateFromString(TAppointment **ter, char* Input )
    {
     /* ... */
         *ter = malloc(sizeof(TAppointment));
         (*ter)->date = ...
    }
    

    Das gleiche Problem gibt es anscheinend noch öfter. Ansonsten solltest du auch nochmal checken, ob du die Datentypen nicht durcheinanderbringst. Einen Zeiger auf TAppointment mit malloc(sizeof(TTime)) zu initialisieren wird in der Regel nicht das gewünschte Ergebnis bringen.


Anmelden zum Antworten