Probleme mit scanf



  • HansKlaus schrieb:

    Den eingabepuffer kannst du mit while(fgetc(stdin)!=EOF); leeren.

    Nein, das geht nicht.

    stdin ist (meist) zeilengepuffert. D.H die eingabe wird erst übernommen, wenn die Entertaste gedrückt wurde.

    Für scanf ist die Entertaste nur ein Whitespace, wie das Leerzeichen.

    Das Problem ist, dass scanf bei, für den Formatspecifier, ungültigen Zeichen abbricht und das Zeichen wieder in den Eingabestrom zurückstellt.

    Das Zurückschreiben ist auch keine Magie, dafür gibt es ungetc/ungetch.
    Man kann also selber alle ungültigen Zeichen überlesen und das erste gültige Zeichen wieder zurückschreiben.

    Bis zum Zeilenende lesen ist eine Möglichkeit.



  • Danke für die hilfreichen Antworten. Eine zusätzliche Funktion ist zwar gut, aber ist für mich zuviel Overhead.

    Hier nun eine Lösung, was haltet ihr davon ?

    do {
    	if (invalid_input)
    		printf(" Ihre Eingabe war inkorrekt. Bitte w\x84 \bhlen sie einen Wert zwischen 1 und %i", avail_words - 1);
    
    	printf("\n Ihre Eingabe : ");
    
    	scanf("%i", &eingabe);
    	while (fgetc(stdin) != 10);	// Enter und restlichen Müll einlesen und wegschmeißen
    
    	invalid_input = TRUE;
    
    } while (!(eingabe >= 1 && eingabe < avail_words));
    


  • Das ist besser. Macht aber bei Eingaben wie 123.abc immer noch das, was du wohl willst. Versuchs so:

    #include <stdio.h>
    #include <limits.h>
    
    #define TRUE (1)
    #define FALSE (0)
    
    int main (void)
    {
        int invalid_input = FALSE;
        int eingabe;
        int avail_words = INT_MAX;
        do {
            if (invalid_input)
                printf(" Ihre Eingabe war inkorrekt. Bitte w\x84 \bhlen sie einen Wert zwischen 1 und %i", avail_words - 1);
    
            printf("\n Ihre Eingabe : ");
    
            if (scanf("%i", &eingabe) != 1)
                eingabe = avail_words;  /* das ist ein wert, der die schleife nicht
                                           beendet */
    
            while (fgetc(stdin) != 10); // Enter und restlichen Müll einlesen und wegschmeißen
    
            invalid_input = TRUE;
    
        } while (!(eingabe >= 1 && eingabe < avail_words));
        printf("Eingabe: %d\n", eingabe);
        return 0;
    }
    

    Ich hab nur geändert, dass das Ergebnis von scanf() genau 1 sein muss. So sollte es klappen.



  • und keine Magic Numbers wie 10. Da schreibt man '\n' und jeder weiß was gemeint ist.
    (auch bei anderen Zeichensätzen)



  • nur daß '\n' je nach Plattform 10, 13 oder 13 10 sein kann.



  • versionsnummer schrieb:

    nur daß '\n' je nach Plattform 10, 13 oder 13 10 sein kann.

    So mag es in einer Datei aussehen.
    Bei Ein-/Ausgabe, die nicht im binary-Mode arbeitet, wird das durch '\n' beschrieben.



  • echo -e "#include \"stdio.h\"\nint main(){ printf(\"hallo\\\\n\");}" | wine gcc -o t_e_s_t.exe -xc - && wine ./t_e_s_t.exe | hexdump -C
    

    68 61 6c 6c 6f 0d 0a

    echo -e "#include \"stdio.h\"\nint main(){ printf(\"hallo\\\\n\");}" | gcc -o t_e_s_t -xc - && ./t_e_s_t | hexdump -C
    

    68 61 6c 6c 6f 0a



  • Imlerith schrieb:

    Eine zusätzliche Funktion ist zwar gut, aber ist für mich zuviel Overhead.

    Depp.



  • manchmal reicht in der tat ein "\n" und manchmal muss es "\r\n" sein. aber "newline" ist doch genormt, oder irre ich da?



  • versionsnummer schrieb:

    echo -e "#include \"stdio.h\"\nint main(){ printf(\"hallo\\\\n\");}" | wine gcc -o t_e_s_t.exe -xc - && wine ./t_e_s_t.exe | hexdump -C
    

    68 61 6c 6c 6f 0d 0a

    echo -e "#include \"stdio.h\"\nint main(){ printf(\"hallo\\\\n\");}" | gcc -o t_e_s_t -xc - && ./t_e_s_t | hexdump -C
    

    68 61 6c 6c 6f 0a

    Unsinn.
    Du weißt nicht, was für eine Unwissenheit du hier verbreitest.
    Wie immer heißt es hier: Klappe halten, wenn man keine Ahnung hat.

    DirkB hat völlig recht, == 10 ist immer falsch, == '\n' ist immer richtig, da die Lineendconvention implementierungsabhängig (hier auch plattformabhängig) ist; bei zeichenorientierten Streams (stdin,stderr,stdout+fopen(..."r") kapselt der Compiler die Binärausprägung der konkreten Lineendconvention automatisch bei der Verwendung von '\n', im Gegensatz zu dir immer und in jedem Fall richtig.



  • LOL



  • verionsnummer schrieb:

    LOL

    Genau. Lache nur ruhig über dich selber, halte die Klappe und verziehe dich dorthin wo du herkamst.



  • Der Test von versionsnummer bestätigt doch nur das Geschriebene bezüglich \n

    Im Code steht \n. In der Ausgabe steht die Zeilenendekennung vom Betriebssystem.


Anmelden zum Antworten