Switch case : case ist anscheinend in einer Schleife?



  • Hi @ all,

    ich bin neu hier im Forum und würde gleich mit einer Frage starten 😃 .
    Leider habe ich bisher keine Lösung zu meinem Problem gefunden.

    Ich habe ein kleines Programm zur Adressverwaltung geschrieben, um mich mehr mit struct usw auseinander zu setzen :

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 100
    
    struct anschrift  {
    
            char vname[MAX];
            char nname[MAX];
            char street[MAX];
            int numb;
            char loc[MAX];
            int plz;
    };
    
    struct anschrift *eingabe();
    void ausgabe(struct anschrift *ptr);
    void welcome();
    void open(struct anschrift *ptr);
    void read(struct anschrift *ptr);
    
    int main(int argc, char **argv)   {
    
            int eing;
            struct anschrift *adress1;
    
            welcome();
    
            printf("\nBitte geben Sie eine Zahl ein 0-5: ");
                    scanf("%d", &eing);
            do  {
                    switch(eing)  {
                                    case 1: adress1 = eingabe();
                                            break;
                                    case 2: open(adress1);
                                            break;
                                    case 3: read(adress1);
                                            break;
                                    case 4: ausgabe(adress1);
                                            break;
                                    case 5: printf("sortierfunktion");
                                            break;
                                    case 0: break;
                                    default: printf("FALSCHE EINGABE");
                                             break;
                    }
    
            } while (eing != 0);
    
            printf("\nProogramm wurde beendet !\n");
    
    return 0;
    
    }
    
    struct anschrift *eingabe(void)  {
    
            static struct anschrift *adress;
            adress = malloc(sizeof(struct anschrift));
    
            printf("Vorname    : ");
                    fgetc(stdin);
                    fgets(adress->vname, MAX, stdin);
            printf("Nachname   : ");
                    fgets(adress->nname, MAX, stdin);
            printf("Strasse    : ");
                    fgets(adress->street, MAX,stdin);
            printf("Hausnummer : ");
                    scanf("%d", &adress->numb);
                    fgetc(stdin);
            printf("Ort        : ");
                    fgets(adress->loc, MAX, stdin);
            printf("PLZ        : ");
                    scanf("%d", &adress->plz);
            return adress;
    
    }
    
    void ausgabe (struct anschrift *ptr)  {
    
            printf("Vorname    : %s\n", ptr->vname);
            printf("Nachname   : %s\n", ptr->nname);
            printf("Strasse    : %s\n", ptr->street);
            printf("Hausnummer : %d\n", ptr->numb);
            printf("Ort        : %s\n", ptr->loc);
            printf("PLZ        : %d\n", ptr->plz);
    
    }
    
    void welcome()  {
            printf("###              ADRESSVERWALTUNG            ###\n");
            printf("### Sie haben folgende Auswahlmoeglichkeiten ###\n");
            printf("### 1   = Adressen einlesen                  ###\n");
            printf("### 2   = Adressen speichern                 ###\n");
            printf("### 3   = Adressen laden                     ###\n");
            printf("### 4   = Adressen ausgeben                  ###\n");
            printf("### 5   = Adressen sortieren                 ###\n");
            printf("### 0   = Programm beenden                   ###\n");
    }
    
    void open(struct anschrift *ptr)  {
            FILE *datei;
    
            datei = fopen("adressen2.txt", "w+");
            fwrite(&ptr, sizeof(struct anschrift),1, datei);
            fclose(datei);
    }
    
    void read(struct anschrift *ptr)  {
            FILE *file;
    
            file = fopen("adressen2.txt", "r");
            fread(&ptr, sizeof(struct anschrift),1, file);
            fclose(file);
    }
    

    Jetzt habe ich aber folgendes Problem das ich nicht verstehe:

    1. Ich compiliere das Programm via gcc
    2. Ich starte das Programm im Terminal
    3. Ich wähle z.B. den 1. Punkt im swichtcase aus

    Folgendes passiert:

    Der ausgewählte Fall wird unendlich oft wiederholt. Woran liegt das?

    Ich hoffe ihr könnt mir helfen 🙂

    Cheers

    progyx



  • Innerhalb deiner do while Schleife änderst du eing nicht, d.h. ist die Abbruchbedingung nie erfüllt, deswegen läuft die Schleife ewig.



  • Du musst den Wert für die Variable eing nach dem switch nochmal vom Nutzer eingeben lassen. Ansonsten bleibt die immer != 0 und der als erstes ausgewählte Fall wird immer wiederholt.



  • Weil sich nichts an eing ändert.
    Das scanf ist ausserhalb der Schleife.



  • Oh mein gott ja klar, ich wusste es muss irgend etwas triviales sein.
    Entschuldigt dass ich eure Zeit für etwas so dummes verschwendet habe *peinlich*

    Trotzdem vielen Dank!



  • Ein int ist kein guter Typ für eine Postleitzahl. Einige fangen mit 0 an.
    Ein int ist kein guter Typ für eine Hausnummer. Es gibt Zusätze mit Buchstaben.
    Und für die Zukunft:
    Ein int ist kein guter Typ für eine Telefonnummer.



  • Ok danke, werde ich mir merken 🙂

    Jetzt funktioniert der switch-Teil wieder, jedoch bekomme ich immer einen Speicherzugriffsfehler(Speicherabzug geschrieben) zurück, wenn ich den 4. Fall auswähle, also das Laden der Datei. Das schreiben funktioniert problemlos.

    Cheers
    progyx



  • In der Funktion read wird kein Speicher für die einzulesenden Daten bereitgestellt. Außerdem möchte fread glaube ich einen Zeiger auf den Bereich, wo es Daten ablegen möchte, Du übergibst aber die Adresse eines Zeigers.



  • Entferne den Adreßoperator bei fwrite und fread:

    fread(ptr, sizeof(struct anschrift),1, file);
    

    (da ptr selbst schon ein Zeiger ist)

    Außerdem solltest du die Zeiger-Behandlung noch verbessern (bisher müßte dein Programm krachen, wenn du als erstes 'read' aufrufst!?!):
    - den lokalen Zeiger mit NULL initialisieren
    - in den einzelnen Funktionen dann auf NULL abprüfen

    Jedoch merke ich gerade (beim Schreiben), daß es viel einfacher und besser wäre, wenn du einfach ein lokales Objekt anlegen würdest:

    struct anschrift adress1;
    

    und dieses dann an die einzelnen Funktionen übergibt (hier dann als &adress1).
    Dann kannst du auf das dynamische Allozieren mittels malloc() verzichten (das free() dazu fehlt ja auch noch - außerdem hättest du bei deinem jetzigen Programm immer erst eingabe() aufrufen müssen, damit der Speicher reserviert wird, d.h. ein sofortiges read() ginge nicht)!

    Eine generelle weitere Verbesserung ist die Verwendung des 'const'-Schlüsselwortes bei den Ausgabe und Schreibfunktionen:

    void ausgabe (const struct anschrift *ptr);
    

    PS. Warum heißt die Schreiben-Funktion 'open'?



  • Hi Th69,
    danke für die schnelle Hilfe.
    habe deine Änderungsvorschläge mal eingefügt:

    #include <stdio.h>
    #include <stdlib.h>
    #define MAX 100
    
    struct anschrift  {
    
            char vname[MAX];
            char nname[MAX];
            char street[MAX];
            int numb;
            char loc[MAX];
            int plz;
    };
    
    /*struct anschrift *eingabe();*/
    void ausgabe(struct anschrift *ptr);
    void welcome();
    void write(struct anschrift *ptr);
    void read(struct anschrift *ptr);
    void eingabe(struct anschrift *ptr);
    
    int main(int argc, char **argv)   {
    
            int eing;
            struct anschrift adress1;
    
            welcome();
    
            do  {
                    printf("\nBitte geben Sie eine Zahl 0-5 ein: ");
                            scanf("%d", &eing);
                    switch(eing)  {
                                    case 1: eingabe(&adress1);
                                            break;
                                    case 2: write(&adress1);
                                            break;
                                    case 3: read(&adress1);
                                            break;
                                    case 4: ausgabe(&adress1);
                                            break;
                                    case 5: printf("sortierfunktion");
                                            break;
                                    case 0: break;
                                    default: printf("FALSCHE EINGABE");
                                             break;
                    }
    
            } while (eing != 0);
    
            printf("\nProogramm wurde beendet !\n");
    
    return 0;
    
    }
    
    void eingabe(struct anschrift *ptr)  {
    
            printf("Vorname   : ");
                    fgetc(stdin);
                    fgets(ptr->vname, MAX, stdin);
            printf("Nachname  : ");
                    fgets(ptr->nname, MAX, stdin);
            printf("Strasse   : ");
                    fgets(ptr->street, MAX, stdin);
            printf("Hausnummer: ");
                    scanf("%d", &ptr->numb);
                    fgetc(stdin);
            printf("PLZ       : ");
                    scanf("%d", &ptr->plz);
                    fgetc(stdin);
            printf("Wohnort   : ");
                    fgets(ptr->loc, MAX, stdin);
                    fflush(stdin);
    
    }
    
    void ausgabe (struct anschrift *ptr)  {
    
            printf("Vorname    : %s\n", ptr->vname);
            printf("Nachname   : %s\n", ptr->nname);
            printf("Strasse    : %s\n", ptr->street);
            printf("Hausnummer : %d\n", ptr->numb);
            printf("Ort        : %s\n", ptr->loc);
            printf("PLZ        : %d\n", ptr->plz);
    
    }
    
    void welcome()  {
            printf("###              ADRESSVERWALTUNG            ###\n");
            printf("### Sie haben folgende Auswahlmoeglichkeiten ###\n");
            printf("### 1   = Adressen einlesen                  ###\n");
            printf("### 2   = Adressen speichern                 ###\n");
            printf("### 3   = Adressen laden                     ###\n");
            printf("### 4   = Adressen ausgeben                  ###\n");
            printf("### 5   = Adressen sortieren                 ###\n");
            printf("### 0   = Programm beenden                   ###\n");
    }
    
    void write(struct anschrift *ptr)  {
            FILE *datei;
            datei = fopen("adressen2.txt", "w+r");
    
            if (datei == NULL)  {
                    printf("Datei konnte nciht gefunden werden!");
            }
            else  {
            fwrite(&ptr, sizeof(struct anschrift),1, datei);
            fclose(datei);
            }
    }
    
    void read(struct anschrift *ptr)  {
            FILE *file;
            file = fopen("adressen2.txt", "r+");
    
            if (file == NULL)  {
                    printf("Datei konnte nicht gefunden werden!");
            }
            else  {
            fread(&ptr, sizeof(struct anschrift),1, file);
            fclose(file);
            }
    }
    

    Ich versteh nur noch nicht ganz warum es jetzt so einfach funktioniert bzw. es funktioniert soweit ausser wenn ich gleich beim Programmstart die Datei laden möchte, habe ich immer noch den Fehler.

    Gibt es jetzt eigentlich auch eine Möglichkeit dass ich mehrere Adressen damit einlesen kann?

    Cheers
    progyx



  • Th69 schrieb:

    Entferne den Adreßoperator bei fwrite und fread:

    fread( ptr, sizeof(struct anschrift),1, file);
    //    ^ Das & da (bei dir) ist der Adressoperator.
    

    (da ptr selbst schon ein Zeiger ist)

    Bei fwrite aber auch.

    progyx schrieb:

    Gibt es jetzt eigentlich auch eine Möglichkeit dass ich mehrere Adressen damit einlesen kann?

    Mach ein Array mit struct anschrift

    struct anschrift adress[10]; // statt adress1;
    

    für 10 Adressen


Log in to reply