Array of structure



  • Ich dachte die Länge wäre hier bereits durch

    #define MAXMATRNUM 6
    #define MAXEXAMIDNUM 6

    bzw.

    char Matr[MAXMATRNUM+1];
    char ExamID[MAXEXAMIDNUM+1];

    beschränkt.

    Und wie kann ich das umschreiben?



  • Tergo schrieb:

    Ich dachte die Länge wäre hier bereits durch

    #define MAXMATRNUM 6
    #define MAXEXAMIDNUM 6

    bzw.

    char Matr[MAXMATRNUM+1];
    char ExamID[MAXEXAMIDNUM+1];

    beschränkt.

    Das ist scanf aber ziemlich egal. 🙂
    Probier es aus.



  • Meinst du so?

    #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=0; i<n; i++)
        {
            printf("Please enter the Matriculation Number %d\n",i+1);
            scanf("%7s",&*database[i].Matr);
            printf("Please enter the Exam-ID %d\n",i+1);
            scanf("%7s",&*database[i].ExamID);
            printf("Please enter the Mark %d\n",i+1);
            scanf("%f",&database[i].mark);
        }
    
        for(i=0; i<n; i++)
        {
        if(database[i].mark<=4.0 && database[i].mark>=0.7)
        {
          num++;
        }
        }
        printf("The number of passed exams is: %d\n", num);
    
        free (database);
        return EXIT_SUCCESS;
    }
    


  • Tergo schrieb:

    Meinst du so?

    Das ist schon mal ein Anfang. Jetzt musst du nur noch nachforschen, ob scanf nicht auch noch eine 0 anfügt (String-Ende), oder sogar noch ein CR (unter Windows womöglich CR und LF) mit in deinen String kopiert.

    Schreibt scanf mit "%7s" wirklich nur 7, oder sogar 8, 9 oder 10 Zeichen?
    Das musst du jetzt noch rausfinden.



  • #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=0; i<n; i++)
        {
            printf("Please enter the Matriculation Number %d\n",i+1);
            scanf("%7s",&*database[i].Matr);
            printf("%s",database[i].Matr);
            printf("Please enter the Exam-ID %d\n",i+1);
            scanf("%7s",&*database[i].ExamID);
            printf("Please enter the Mark %d\n",i+1);
            scanf("%f",&database[i].mark);
        }
    
        for(i=0; i<n; i++)
        {
        if(database[i].mark<=4.0 && database[i].mark>=0.7)
        {
          num++;
        }
        }
        printf("The number of passed exams is: %d\n", num);
    
        free (database);
        return EXIT_SUCCESS;
    }
    

    Habe versucht, den Wert direkt danach auszuprinten. Wenn ich 6 Ziffern eingebe, kommen 6 Ziffern wieder heraus.

    Edit: habe außerdem entdeckt, dass die Berechnung der bestandenen Examen falsch ist, wenn ich z.B. 2x 0.7 und einmal 4.0 eingebe. Laut Programm hätte nur ein Examen bestanden 😕 Edit: 0.7 ist das Problem.

    Edit2: wenn ich mehr als 7 Stellen eingebe, nimmt scanf die Stellen nicht mehr auf. Es werden nur 7 Stellen vergeben. Also sind wir mit %7s doch gut dabei, oder?



  • Tergo schrieb:

    Edit2: wenn ich mehr als 7 Stellen eingebe, nimmt scanf die Stellen nicht mehr auf. Es werden nur 7 Stellen vergeben. Also sind wir mit %7s doch gut dabei, oder?

    7 sichtbare Zeichen. Wie kriegst du aber raus, ob das letzte Zeichen nicht doch eine 0 ist und somit 8 zeichen geschrieben werden?



  • Darauf folgte DIREKT die nächste Frage (also nach der ExamID), da war kein Platz zwischen. Ich schätze das zählt nicht, oder? 😃
    Wie kann ich das denn noch untersuchen?

    So vielleicht?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.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=0; i<n; i++)
        {
            printf("Please enter the Matriculation Number %d\n",i+1);
            scanf("%7s",&*database[i].Matr);
            printf("%u", strlen(database[i].Matr));
            printf("Please enter the Exam-ID %d\n",i+1);
            scanf("%7s",&*database[i].ExamID);
            printf("Please enter the Mark %d\n",i+1);
            scanf("%f",&database[i].mark);
        }
    
        for(i=0; i<n; i++)
        {
        if(database[i].mark>=0.7 && database[i].mark<=4.0)
        {
          num++;
        }
        }
        printf("The number of passed exams is: %d\n", num);
    
        free (database);
        return EXIT_SUCCESS;
    }
    

    strlen spuckt weiterhin 7 Zeichen aus, egal wieviele ich eintippe. Ein gutes Zeichen, richtig? 😃

    Edit: zur letzten Test-for-Schleife: wenn ich >=0.6 eingebe, wird das Examen auch gezählt, wenn ich 0.6 eingebe. Wenn ich allerdings >=0.7 eingebe, wird 0.7 nicht mehr gezählt. Was läuft denn da schief? 😕
    Seltsamerweise wird das Examen auch gezählt, wenn ich einfach >0.6 eingebe. Für 0.7 gilt das allerdings auch wieder nicht. Wo ist denn da der Unterschied?



  • Du kannst bei scanf auch angeben, dass da 1000 Zeichen platz haben. Wenn der Zielbereich kleiner ist, wird gnadenlos über die Grenze hinaus geschrieben.

    Die Längenbegrenzung bei %s von scanf gilt für die Anzahl der eingebenen Zeichen. Für die Endekennung '\0' muss aber noch Platz bleiben. Die wird immer angehängt.

    strlen sucht nur nach dieser '\0', darum kannst du davon nicht auf den Platz schließen.

    Für diese '\0' ist übrigens die +1 im der Definition der char-Arrays (Zeile 11 & 12)



  • Aber wo kann ich denn den Zielbereich einstellen? Das müsste doch im malloc funktionieren, hier sitzt doch der Speicher. Da hier aber n*size aufgestellt wird, ist doch genügend Platz, oder nicht?



  • Der Platz für die IDs wird über die Größenangaben in der struct festgelegt (Zeile 11 u 12).

    Wieviel structs du dann speichern kannst, wird mit malloc festgelegt.



  • Aber dann müsste doch DEFINITIV genug Speicher frei sein, oder nicht?

    Ich gehe das Ganze jetzt mal Schritt für Schritt durch.

    Ich definiere den Platz für die Strings mit 6 Stellen.

    Anschließend sage ich, dass ich noch eine Stelle mehr brauche ('0').

    Das Programm fragt, wieviele Datensets/Strukturen ich haben will.

    Ich sage 'n'.

    Also habe ich n-mal den Platz, den ich vorher festgelegt habe.

    Das heißt, ich müsste für die Eingaben einer 6-stelligen Ziffer, noch einer 6-stellen Ziffer und einer Float-Variable doch in jedem Falle genug Platz haben, oder nicht?

    Edit: Verstehe auch einfach nicht, wieso >= 0.7 nicht funktioniert. 😞



  • Nein.

    Tergo schrieb:

    Ich definiere den Platz für die Strings mit 6 Stellen.

    Das ist der Platz für ein Examen

    Tergo schrieb:

    Anschließend sage ich, dass ich noch eine Stelle mehr brauche ('0').

    Der Stringterminator ist das Zeichen mit dem Wert 0 (Null) '0' ist das Zeichen dass die Ziffer Null darstellt und hat im ASCII den Wert 48.
    Das Zeichen mit dem Wert 0 kann man als '\0' (mit \, siehe Escapesequencen) schreiben oder auch einfach als 0 (ohne ')

    Tergo schrieb:

    Das Programm fragt, wieviele Datensets/Strukturen ich haben will.

    Ich sage 'n'.

    Also habe ich n-mal den Platz, den ich vorher festgelegt habe.

    Ich hoffe, du gibst da einen Zahlenwert ein und keinen Buchstabe. Denn 'n' (mit ') steht für den kleinen Buchstaben N.

    Und du hast dann Platz für n Examen und nicht für lange Strings.

    Die Struct ist eine Folge von Speicherstellen.

    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |M|M|M|M|M|M|M|E|E|E|E|E|E|E|m|m|m|m|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    

    M ist der Platz für Matr, E für ExamID, m für mark

    Mit dem malloc bekommst du dann den Speicherbereich, an dem Platz für n structs ist

    +----------- database[0] -----------+----------- database[1] -----------+----------- database[2] -----------+
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |0|1|2|3|4|5|_|9|9|9|_| | | |f|f|f|f|0|1|2|3|4|5|_|9|9|8|_| | | |f|f|f|f|0|1|2|3|4|5|_|9|9|7|_| | | |f|f|f|f|
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    +--- Matr ----+-- ExamID ---+ mark -+--- Matr ----+-- ExamID ---+ mark -+--- Matr ----+-- ExamID ---+ mark -+
    

    012345 ist die Matr, _ steht für das Stringende,997 bis 999 für die ExamID und ffff für die interne Darstellung von mark.

    Wenn du jetzt zuviel Zeichen eingibst, werden die Bereiche überschrieben.
    Darum musst du die Eingabe begrenzen.



  • Wieso gibt es denn für ExamID eigentlich nur 3, bzw. mit Stringende vier Zeichen? Hier setze ich doch wie bei Matr auch 6+1 Zeichen fest.

    Und wie kann ich die Eingabe begrenzen?



  • Tergo schrieb:

    Edit: Verstehe auch einfach nicht, wieso >= 0.7 nicht funktioniert. 😞

    Nicht alle Fließkommazahlen können exakt abgespeichert werden.
    Oft ist es ein Nähreungswert.

    Dein mark ist vom Typ float , der ist nicht so genau wie eine Zahl vom Typ double .
    Die 0.7 werden aber als double aufgefasst. Beim Vergleich wird das ungenaue mark in ein double gewandelt und dann mit dem genauen 0.7 verglichen.

    Ist wie bei 1/3 bei Dezimalzahlen: 0,333 < 0,3333333
    (Intern arbeitet der Rechner mit Binärdarstellung)

    Du kannst dem Compiler aber sagen, dass er die 0,7 als float auffassen soll. Setze ein f dahinter: 0.7f



  • Tergo schrieb:

    Wieso gibt es denn für ExamID eigentlich nur 3, bzw. mit Stringende vier Zeichen? Hier setze ich doch wie bei Matr auch 6+1 Zeichen fest.

    Du musst ja nicht 6 Zeichen eingeben, 3 reichen doch auch.

    Tergo schrieb:

    Und wie kann ich die Eingabe begrenzen?

    Das machst du doch schon.
    Aber mit dem falschen Wert.



  • f habe ich nun dahinter gesetzt. Es funktioniert 🙂 🙂

    Laut Aufgabe soll die ExamID aber 6 Stellen haben 😕
    Das heißt, ich wäre doch dann mit 6+1 bei ExamID und Matr gut bedient oder?



  • Tergo hat jetzt in Dirk einen C-Privatlehrer gefunden. 😃

    Btw, bitte nicht falsch verstehen, Dirk. Ich finde es gut, wie du das machst.
    Schon mal daran gedacht, daraus einen Beruf zu machen?



  • Das ist die letzte Information, die ich benötige, dann wäre das Programm fertig 😞

    Bin Dirk, und natürlich auch dir, Andromeda, auch wahnsinnig dankbar für die Hilfe 🙂



  • Irgenwann hast du angefangen im Formatsring von scanf eine Ziffer (7) einzubauen.
    Wieso, weshalb, warum?

    http://www.cplusplus.com/reference/cstdio/scanf/



  • Ich dachte das wäre dafür, um die Eingabe zu begrenzen 😕

    Oder muss hier eine 6 stehen?


Anmelden zum Antworten