Array of structure



  • Ich glaube ich verstehe jetzt, wieso 'exams' falsch gewählt war. Database war ja schließlich bereits deklariert, richtig?

    #include <stdio.h> 
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    char passedTest(struct list database);
    
    struct list
    {                                   
        char Matr[MAXMATRNUM+1]; 
        char ExamID[MAXEXAMIDNUM+1]; 
        float mark[]; 
    }; 
    
    int main() 
    { 
        int n,result,i;
        struct list *database;
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(n=0; n<i; n++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&database[n].mark);
        }
    
        result=passedTest(database);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    } 
    
    char passedTest(struct list database)
    {
        int num;
        if(exams[n].mark<=4.0)
    
        return 0;
    }
    

    Den einzigen Error, den ich jetzt noch AUßERHALB der unteren Funktion erhalte, ist, dass der Typ von passedTest Konflikte bereitet. Dieser ist aber, wie oben, char.

    Edit: habe schon mal angefangen, das Endergebnis letztendlich abzudrucken. Das einzige, was nun noch fehlt, ist der Test in der Funktion 😞



  • Du hast jetzt zweimal database definiert.
    Einmal als Pointer und einmal als Array.
    Das mag der Compiler nicht.

    Du übergibst auch dieses database an die Funktion passedTest. Die erwartet aber ein struct und keine Adresse (Zeiger) darauf. Großer Unterschied!



  • Tergo schrieb:

    Ich glaube ich verstehe jetzt, wieso 'exams' falsch gewählt war. Database war ja schließlich bereits deklariert, richtig?

    Und deshalb benennst du das exams-Array einfach um, noch dazu in "database", was bereits weiter oben als Pointer existiert. In C gibt es zwar keine One-Definition-Rule, aber 2 verschiedene Objekte gleichen Namens, in einer Übersetzungseinheit, sind auch in C nicht erlaubt.



  • Das heißt, es wäre eigentlich so:?

    #include <stdio.h> 
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    char passedTest(struct list database);
    
    struct list
    {                                   
        char Matr[MAXMATRNUM+1]; 
        char ExamID[MAXEXAMIDNUM+1]; 
        float mark[]; 
    }; 
    
    int main() 
    { 
        int n,result,i;
        struct list database;
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(n=0; n<i; n++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&database[n].mark);
        }
    
        result=passedTest(list);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    } 
    
    char passedTest(struct list database)
    {
        int num;
        if(database[n].mark<=4.0)
    
        return 0;
    }
    

    Hier wird jetzt die ganze 'list' an die Funktion weitergegeben. Desweiteren ist database kein Pointer mehr.



  • Tergo schrieb:

    Das heißt, es wäre eigentlich so:?

    Nein, auch nicht. 😞
    Wieso hast du das Sternchen vor database weggelöscht?
    Weißt du denn, wieso es überhaupt da war?



  • Das Sternchen hat 'Database' als Pointer deklariert, das Löschen war ein Irrtum. Hier die korrigierte Version:

    Edit: ich verstehe schon, wieso Database als Pointer deklariert wurde, allerdings mache ich offenbar kurz darauf etwas falsch: ich scanne die Eingaben in database rein und sage dort, dass es sich dabei um ein Array handelt. Tut es aber nicht. Ich dachte jedoch, dass database ein Array sein muss, schließlich, davon bin ich ausgegangen, brauchen wir für die Aufgabe ein Array of structures?

    #include <stdio.h> 
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    char passedTest(struct list database);
    
    struct list
    {                                   
        char Matr[MAXMATRNUM+1]; 
        char ExamID[MAXEXAMIDNUM+1]; 
        float mark[]; 
    }; 
    
    int main() 
    { 
        int n,result,i;
        struct list *database;
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(n=0; n<i; n++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&database[n].mark);
        }
    
        result=passedTest(list);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    } 
    
    char passedTest(struct list database)
    {
        int num;
        if(database[n].mark<=4.0)
    
        return 0;
    }
    


  • Hör auf hier rumzunerven, melde dich erst wieder, wenn du Code hast, der compilierbar und ohne Warnungen ist.



  • Tergo schrieb:

    Edit: ich verstehe schon, wieso Database als Pointer deklariert wurde, allerdings mache ich offenbar kurz darauf etwas falsch: ich scanne die Eingaben in database rein und sage dort, dass es sich dabei um ein Array handelt. Tut es aber nicht.

    Das ist egal. Einen Pointer kann man wie ein Array ansprechen.

    int *pointer = ...;
    *(pointer+a) = b; // ist das selbe ...
    pointer[a] = b;    // ... wie das
    

    🙂



  • Das heißt, bis dorthin sollte es eigentlich fehlerfrei laufen?
    Der Compiler spuckt nämlich tatsächlich keine Fehler mehr aus, die sich auf die main-Funktion beziehen. In der passedTest-Funktion hingegen wird's schwieriger, aber da ist es ja klar, der Code ist dort auch noch nicht fertig.
    Habe ja die Struktur jetzt in die passed-Test-Funktion gegeben und möchte jetzt gerne die float-Werte abrufen und diese gegentesten. Die passed-Test-Funktion würde dann nun so aussehen:

    #include <stdio.h> 
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    char passedTest(struct list database);
    
    struct list
    {                                   
        char Matr[MAXMATRNUM+1]; 
        char ExamID[MAXEXAMIDNUM+1]; 
        float mark[]; 
    }; 
    
    int main() 
    { 
        int n,result,i;
        struct list *database;
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(n=0; n<i; n++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&database[n].mark);
        }
    
        result=passedTest(struct database);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    } 
    
    char passedTest(struct list database)
    {
        int num=0,n,i;
    
        for(n=0;n<i;n++)
        {
        if(database[n].mark<=4.0)
        num++;
        else
        continue;
        }
    
        return num;
    }
    


  • Der Auruf und die Deklaration von passedTest sind Müll.

    database in main ist ein Zeiger und so sollte der auch an die Funktion weiter gegeben werden.
    Dann muss die Funktion aber auch einen Zeiger erwarten.
    Und du musst der Funktion auch noch die Anzahl der Elemente im Array mitgeben. Als extra Parameter.

    Deine scanf in der Schleife sind immer noch falsch.

    Und dein else continue ist sehr sinnfrei.



  • DirkB schrieb:

    Der Auruf und die Deklaration von passedTest sind Müll.

    database in main ist ein Zeiger und so sollte der auch an die Funktion weiter gegeben werden.
    Dann muss die Funktion aber auch einen Zeiger erwarten.
    Und du musst der Funktion auch noch die Anzahl der Elemente im Array mitgeben. Als extra Parameter.

    Deine scanf in der Schleife sind immer noch falsch.

    Und dein else continue ist sehr sinnfrei.

    In der main: "for(n=0; n<i; n++)", - n und i hat er wohl vertauscht, denn n enthält die Anzahl der Datensätze und i ist bis dahin uninitialisiert.

    Und "mark" in der Struct hat Array-Klammern. Das ist sicher auch nicht gewollt. 😃



  • Habe jetzt nochmal einige Anmerkungen von euch berücksichtigt und diese hier hinterlegt 🙂

    #include <stdio.h> 
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    char passedTest(struct list *database);
    
    struct list
    {                                   
        char Matr[MAXMATRNUM+1]; 
        char ExamID[MAXEXAMIDNUM+1]; 
        float mark; 
    }; 
    
    int main() 
    { 
        int n,result,i;
        struct list *database[int];
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(i=0; i<n; i++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&*database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&*database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&*database[n].mark);
        }
    
        result=passedTest(*database);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    } 
    
    char passedTest(struct list database)
    {
        int num=0,n,i;
    
        for(i=0;i<n;i++)
        {
        if(*database[n].mark<=4.0)
        num++;
        }
        return num;
    }
    

    Erhalte jetzt so gut wie keine Fehlermeldungen mehr, die letzten beiden beziehen sich auf Zeile 18 und 50. Dass Zeile 50 falsch ist sehe ich ein, bei Zeile 18 grübel ich weiterhin...



  • Was bedeutet denn Zeile 18?
    Warum hast du Zeile 18 denn geändert?
    Und wie lautet die Fehlermeldung genau?

    Nochmal: Der Parameter der Funktion passedTest ist vom falschen Typ.
    Du kannst da database als Array der struct definieren, oder als Pointer auf die struct.
    Aber nicht als struct selber.

    Welchen Wert hat n in Zeile 48.

    Du musst bei Fehlern immer mit dem Ersten in der Liste anfangen. Die Nachfolgenden können Folgefehler sein.

    Beim Programmieren musst du wissen, was jedes einzelne Zeichen bedeutet.
    Hier und da mal ein paar *, & und [] einbauen, führt nicht zum Ziel.



  • Das bedeutet, dass die Funktionen nur den Pointer Database benötigen, um die Struktur zu handlen? Nur, wenn ich den Prototyp der Funktion mit *database deklariere, ist database ja hier noch gar nicht vorgemerkt worden?

    Habe n nun als globale Variable deklariert, damit müsste der doch von der main auch in die passed-Test Funktion übernommen werden, oder?

    Edit: Erhalte auch für scanf-Funktion in der Schleife bei mark den Fehler, dass ich doch dort float benutzen solle. Allerdings ist %f doch float 😕



  • Tergo schrieb:

    Das bedeutet, dass die Funktionen nur den Pointer Database benötigen, um die Struktur zu handlen?

    Ja.
    Obwohl, die Größe wäre auch wichtig.

    Tergo schrieb:

    Nur, wenn ich den Prototyp der Funktion mit *database deklariere, ist database ja hier noch gar nicht vorgemerkt worden?

    Dann deklariere die Funktion doch nach der struct. 🙄

    Tergo schrieb:

    Habe n nun als globale Variable deklariert, damit müsste der doch von der main auch in die passed-Test Funktion übernommen werden, oder?

    Mach das rückgaängig!
    Warum spedierst du der Funktion nicht einfach einen zweiten Parameter?
    In den ersten Versuch vor drei Seiten, hattest du sogar drei. Du weißt also, das dass geht.



  • Tergo schrieb:

    Edit: Erhalte auch für scanf-Funktion in der Schleife bei mark den Fehler, dass ich doch dort float benutzen solle. Allerdings ist %f doch float 😕

    Auch da hast du solange mit extra Zeichen rumgespielt, bis es kaputt war.

    &*database[n].mark ist ein float, wenn auch sehr umständlich. Aber das will scanf ja auch nicht haben. scanf möchte eine Adresse (hier auf float) haben.



  • Wird die Größe nicht über Malloc bestimmt?

    Die Funktion ist jetzt nach der Struct deklariert.

    Die Funktion hat jetzt einen zweiten Parameter.

    Dass Scanf eine Adresse will, funktioniert doch mit '&', dachte ich? & gibt immer die Adresse aus, so war meine Annahme.. (oder &database[n].mark ?)

    Hier der aktuelle Stand:

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    struct list
    {                                  
        char Matr[MAXMATRNUM+1];
        char ExamID[MAXEXAMIDNUM+1];
        float mark;
    };
    
    struct list *database;
    
    char passedTest(*database);
    
    int main()
    {
        int n,result,i;
        printf("Please enter the number of exams: ");
        scanf("%d", &n);
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(i=0; i<n; i++)
        {
            printf("Please enter the Matriculation Number %d",i);
            scanf("%c",&*database[n].Matr);
            printf("Please enter the Exam-ID %d",i);
            scanf("%c",&*database[n].ExamID);
            printf("Please enter the Mark %d",i);
            scanf("%f",&*database[n].mark);
        }
    
        result=passedTest(*database);
    
        printf("The number of passed exams is: %d", result);
    
        free (database);
        return EXIT_SUCCESS;
    }
    
    char passedTest(*database)
    {
        int num=0,i,n;
    
        for(i=0;i<n;i++)
        {
        if(*database[n].mark<=4.0)
        num++;
        }
        return num;
    }
    


  • Tergo schrieb:

    Wird die Größe nicht über Malloc bestimmt?

    Du kannst die Größe aber anhand des Zeigers nicht mehr ermitteln. Darum musst du sie dir extra merken und immer mitführen.

    Tergo schrieb:

    Die Funktion ist jetzt nach der Struct deklariert.

    OK.
    Aber warum ist dataset jetzt global?

    Tergo schrieb:

    Die Funktion hat jetzt einen zweiten Parameter.

    Lüge.

    Tergo schrieb:

    Dass Scanf eine Adresse will, funktioniert doch mit '&', dachte ich? & gibt immer die Adresse aus, so war meine Annahme.. (oder &database[n].mark ?)

    Was macht der * an der Stelle und wie ist es mit Arrays und Zeigern?

    Jetzt nicht verwechseln. Beim scanf hast du einen einfachen Tap, von dem du die Adresse willst: database[n].mark ist ein float. Da kannst du mit dem Adressoperator arbeiten.
    Bei passedTest möchtest du das ganze Array angeben.

    Ob du den Zeiger mit dem * derefernzierst oder mit den Arrayklammern, ist egal.
    Aber beides auf einmal zusammen macht man Doppelzeigern. Den hast du nicht.

    Tergo schrieb:

    Hier der aktuelle Stand:

    Die Änderungen darin sind andere als oben beschrieben und teilweise ein weiterer Rückschritt. 😞



  • Folgender Vorschlag:

    ich verzichte auf die Funktion, diese wird ja auch nicht in der Aufgabe verlangt und beziehe den Test der bestandenen Examen einfach in die main-Funktion mit ein. Das sähe dann so aus (ohne Fehlermeldungen):

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    struct list
    {                                  
        char Matr[MAXMATRNUM+1];
        char ExamID[MAXEXAMIDNUM+1];
        float mark;
    };
    
    int main()
    {
        int n,i,num=0;
        printf("Please enter the number of exams:\n");
        scanf("%d", &n);
        struct list *database;
        database = malloc (n * sizeof(struct list));
        if (database == 0)
            return EXIT_FAILURE;
    
        for(i=1; i<=n; i++)
        {
            printf("Please enter the Matriculation Number %d\n",i);
            scanf("%c",&*database[n].Matr);
            printf("Please enter the Exam-ID %d\n",i);
            scanf("%c",&*database[n].ExamID);
            printf("Please enter the Mark %d\n",i);
            scanf("%f",&database[n].mark);
        }
        for(i=1; i<=n; i++)
        {
        if(database[n].mark<=4.0 && database[n].mark>=0.7)
        {
          num++;
        }
        }
        printf("The number of passed exams is: %d\n", num);
    
        free (database);
        return EXIT_SUCCESS;
    }
    

    Das Programm führt korrekt aus, fragt nach sämtlichen Werten, jedoch: kurz vor der Auswertung, wieviele Examen bestanden haben erhalte ich eine riesige Meldung:

    ***Error in 'main': free(): invalid next size (fast): 0x000... ***

    gefolgt von jeder Menge Informationen bezüglich des Speichers.

    Es muss also etwas mit der free Funktion nicht stimmen..

    Edit: jetzt das Ganze etwas aufgeräumter.



  • Tergo schrieb:

    Es muss also etwas mit der free Funktion nicht stimmen..

    Wenn die nicht ok ist, dann wärst du nicht der Erste, der der das merkt.

    Das Problem liegt bei dir!

    Lass dir mal den Wert von database nach dem malloc und vor dem free ausgeben und vergleiche die Angaben:

    printf("database zeigt auf %p\n": database);
    

    Oder nutze den Debugger.

    Durch dein krudes vermischen von & und * und Nichtbeachtung der Arraygrenzen zerschießt du dir den Zeiger.


Anmelden zum Antworten