Array of structure



  • 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?



  • Tergo schrieb:

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

    Oder muss hier eine 6 stehen?

    Du willst einen String mit 6 Zeichen.
    Ein String in C hat aber üblicherweise n+1 Zeichen, wegen der abschließenden 0.
    Was sagt uns das?



  • Dass ich 7 Zeichen brauche. Aber das habe ich doch, oder nicht? 😕

    Edit: ich poste hier nochmal den aktuellen Stand:

    #include <stdio.h>
    #include <stdlib.h>
    #define MAXMATRNUM   6  
    #define MAXEXAMIDNUM    6
    
    struct exam
    {                                  
        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 exam *database;
        database = malloc (n * sizeof(struct exam));
        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>=0.7f && database[i].mark<=4.0)
        {
          num++;
        }
        }
        printf("The number of passed exams is: %d\n", num);
    
        free (database);
        return EXIT_SUCCESS;
    }
    


  • Tergo schrieb:

    Dass ich 7 Zeichen brauche. Aber das habe ich doch, oder nicht? 😕

    Du sollest dir daher darüber klar werden, was "%7s" im scanf-Kontext bedeutet.
    Also RTFSM! 😃



  • Also scanf speichert die Werte, die eingegeben werden unter der Adresse von *database[i]. Wenn nun %7s angegeben wird, werden nur die ersten 7 Zeichen gespeichert, richtig? Das heißt, wenn ich 012345 eingebe, werden diese gespeichert inklusive des String-Endes '0'.



  • Tergo schrieb:

    Wenn nun %7s angegeben wird, werden nur die ersten 7 Zeichen gespeichert, richtig? Das heißt, wenn ich 012345 eingebe, werden diese gespeichert inklusive des String-Endes '0'.

    "012345" sind aber 6 Zeichen.

    Preisfrage: wie viele Zeichen, inklusive der infamen 0, werden bei %7s gespeicher?

    [] 6 Zeichen?
    [] 7 Zeichen?
    [] 8 Zeichen?

    Nur eine Antwort ist richtig.



  • Tergo schrieb:

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

    Ja, ja das ist es.

    Tergo schrieb:

    Oder muss hier eine 6 stehen?

    scanf schrieb:

    %[*][width][length]specifier

    width Specifies the maximum number of characters to be read in the current reading operation (optional).

    Tergo schrieb:

    Also scanf speichert die Werte, die eingegeben werden unter der Adresse von *database[i]. Wenn nun %7s angegeben wird, werden nur die ersten 7 Zeichen gespeichert, richtig? Das heißt, wenn ich 012345 eingebe, werden diese gespeichert inklusive des String-Endes '0'.

    012345 sind nur 6 Zeichen. Du erlaubst aber 7 Zeichen: 1234567. Und dann kommt noch automatisch die '\0'. Was dann 8 Zeichen wären. Dein Array hat aber nur Platz für 7 Zeichen.
    (Du kannst aber auch Buchstaben eingeben)



  • Das heißt es müsste einfach 6s sein? Ich dachte, man müsste die '0' am Stringende selber mit einberechnen.

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

    So dann?



  • Tergo schrieb:

    Ich dachte, man müsste die '0' am Stringende selber mit einberechnen.

    Das tust du ja. Siehe die "+1" in der Struct-Definition.



  • Okay, das leuchtet mir ein 🙂
    Das heißt, das Programm ist nun fertig?


Anmelden zum Antworten