Ursachenforschung Endlosschleife



  • Hallo,
    das ist das erste Mal, dass ich in diesem Forum schreibe und hoffe man verzeihe mir den relativ langen Code den ich hier schon mitbringe. Ich habe das Programm soweit gekürzt wie möglich, um die auftretende Endlosschleife reproduzieren zu können. In diesem gekürzten Programm sollen aus einer gegeben Datei Informationen ausgelesen werden wie, Name, Adresse, Matrikelnummer etc. und in einen eigens dafür erstellten Datentyp mit Namen "STUDENTENDATEN" geschrieben werden. Dieser Programmteil war gegeben. Das Einlesen funktioniert. Was ich hier nicht zeige ist, dass ich später die eingelesenen Daten prüfen und sortieren werde, jener Teil ist, weil irrelevant für mein folgendes Problem, rausgenommen.
    Zu der Endlosschleife. Teste ich das Einlesen der Daten in einem gesonderten Programm , lasse mir das Eingelesene danach zum Testen nochmals ausgeben, ist alles gut. Teste ich den switch gesondert ist auch alles gut. Die Endlosschleife entsteht beim Zusammensetzen von Beidem. Nachdem ich die Daten eingelesen habe, möchte ich über den switch weitere Anweisung beim Anwender anfragen. Doch sobald ich eigentlich gefragt werden müsste, nach einer Eingabe, bestaune ich eine unendliche Abfrage nach einer Abfrage, die offenbar auch ohne mein zutun sofort befriedigt wird. Ein "fflush(stdin)" hat nicht geholfen. Auch verzweiflungstaten wie mehrere getchar() vor dem switch halfen nicht. Aus einem mir nicht bekannten Grund liegt irgendwas im Puffer? oder ich habe einen logischen Fehler irgendwo der es mir unmöglich macht scanf selbst eine Eingabe zukommen zu lassen.
    Ich kenne sowas sonst nur von Fällen wo ich scanf einen falschen Typ als Eingabe liefer. Vielleicht entsteht das Problem auch durch das Einlesen? Ich hoffe ich nicht zuwenig oder zuviel geschrieben^^.
    Hier nun das Programm:

    #include <stdio.h>
    #include <stdlib.h>
    
    #define ANZAHL 10
    
    /**  Strukturdeklaration  *******************************************/
    
    typedef struct
    {
       char vorname[30];
       char nachname[30];
       int matrikelnr;
       int plz;
       char wohnort[30];
       char strasse[30];
       int hausnr;
    } STUDENTENDATEN;
    
    /**  Prototypen  ****************************************************/
    
    int satz_lesen (STUDENTENDATEN *const s);
    
    /*==================================================================*\
     *  Hauptprogramm
    \*==================================================================*/
    
    int main (void)
    {
    
        int i = 0;
        int j = 0;
        int z = 0;
        int abbruch = 0;
    
        STUDENTENDATEN satz[ANZAHL];
    
        while (satz_lesen (&satz[i]) != EOF && i < ANZAHL)
    	{
                i++;
    	}
        i = j;
    
        while(abbruch == 0)
        {
            abbruch = 1;
            printf("Wollen Sie den Datensatz sortieren und wenn ja, wonach?\n");
            printf("Ja, nach Matrikelnummer(1) , Ja, nach dem Nachnamen(2), Nein, nicht sortieren(0)\n");
            scanf("%i", &z);
    
            switch (z)
            {
                case '0':
                        printf("Eingegeben wurde %i", z);
                break;
                case '1':
                        printf("Eingegeben wurde %i", z);
                break;
                case '2':
                        printf("Eingegeben wurde %i", z);
                break;
                default:
                        abbruch = 0;
                        printf("Falsche Eingabe.\n");
            }
        }
    
        return 0;
    }
    
    /*==================================================================*\
     *  Eingabefunktion
    \*==================================================================*/
    
    int satz_lesen (STUDENTENDATEN *const s)
    {
        if (EOF == scanf ("%s", s->vorname))
    	return EOF;
        if (EOF == scanf ("%s", s->nachname))
    	return EOF;
        if (EOF == scanf ("%d", &s->matrikelnr))
    	return EOF;
        if (EOF == scanf ("%d", &s->plz))
    	return EOF;
        if (EOF == scanf ("%s", s->wohnort))
    	return EOF;
        if (EOF == scanf ("%s", s->strasse))
    	return EOF;
        if (EOF == scanf ("%d", &s->hausnr))
    	return EOF;
    
        return 0;
    }
    

    Hmm ich muss blind sein, ich kann keinen Anhang machen. Deshalb die Einzulesende Datei hier: http://www.megaupload.com/?d=5MTWCUZD

    Das Programm wird mit programm.exe < daten.txt bzw. ./programm < daten.txt ausgeführt.

    Entschuldigt nochmals den langen Code.



  • Du hast die Eingabe umgeleitet auf die Datei daten.txt. Damit dürfte es nicht mehr möglich sein, irgendeine Eingabe von der Konsole zu verarbeiten.
    Übergib Deinen Dateinamen stattdessen als Parameter an das Programm.



  • Außerdem liest Du einen int von der Konsole und vergleichst in der switch - Anweisung mit Charactern ('0' '1' '2') - das gibt immer falsch.

    So funktioniert es: (Aufruf: programm.exe daten.txt)

    #include <stdio.h>
    #include <stdlib.h>
    
    #define ANZAHL 10
    
    /**  Strukturdeklaration  *******************************************/
    
    typedef struct
    {
       char vorname[30];
       char nachname[30];
       int matrikelnr;
       int plz;
       char wohnort[30];
       char strasse[30];
       int hausnr;
    } STUDENTENDATEN;
    
    /**  Prototypen  ****************************************************/
    
    int satz_lesen (STUDENTENDATEN *const s, FILE *datei);
    
    /*==================================================================*\
     *  Hauptprogramm
    \*==================================================================*/
    
    int main (int argc, char **argv)
    {
    
        int i = 0;
        int j = 0;
        int z = 0;
        int abbruch = 0;
        FILE *datei;
    
        if(argc < 2)
        	return 0;
    
        datei = fopen(argv[1], "r");
    
        STUDENTENDATEN satz[ANZAHL];
    
        while (satz_lesen (&satz[i], datei) != EOF && i < ANZAHL)
        {
                i++;
        }
    
        fclose(datei);
    
        i = j;
    
        while(abbruch == 0)
        {
            abbruch = 1;
            printf("Wollen Sie den Datensatz sortieren und wenn ja, wonach?\n");
            printf("Ja, nach Matrikelnummer(1) , Ja, nach dem Nachnamen(2), Nein, nicht sortieren(0)\n");
            scanf("%i", &z);
    
            switch (z)
            {
                case 0:
                        printf("Eingegeben wurde %i", z);
                break;
                case 1:
                        printf("Eingegeben wurde %i", z);
                break;
                case 2:
                        printf("Eingegeben wurde %i", z);
                break;
                default:
                        abbruch = 0;
                        printf("Falsche Eingabe.\n");
            }
        }
    
        return 0;
    }
    
    /*==================================================================*\
     *  Eingabefunktion
    \*==================================================================*/
    
    int satz_lesen (STUDENTENDATEN *const s, FILE *datei)
    {
        if (EOF == fscanf (datei, "%s", s->vorname))
        return EOF;
        if (EOF == fscanf (datei, "%s", s->nachname))
        return EOF;
        if (EOF == fscanf (datei, "%d", &s->matrikelnr))
        return EOF;
        if (EOF == fscanf (datei, "%d", &s->plz))
        return EOF;
        if (EOF == fscanf (datei, "%s", s->wohnort))
        return EOF;
        if (EOF == fscanf (datei, "%s", s->strasse))
        return EOF;
        if (EOF == fscanf (datei, "%d", &s->hausnr))
        return EOF;
    
        return 0;
    }
    


  • Vielen Dank, da habe ich etwas sehr wichtiges gelernt. Mir wurde nicht vermittelt, dass wenn nach einer Eingabeumlenkung weitere Eingaben nötig werden ich diese nicht mehr über die Standarteingabe machen kann. Könnte man die Eingabeumlenkung vielleicht auf einen Programmteil beschränken? Sodass die Eingabe erst auf eine Datei gelenkt ist und danach auf stdin zurückgelenkt wird? Das ist nur theoretisch ich mach das jetzt mit der Parameterübergabe und es funktioniert wie gewünscht.



  • Unter Windows geht das mit den API-Funktionen GetStdHandle / SetStdHandle.


Anmelden zum Antworten