Verhinderung einer falschen Eingabe



  • Hi,
    ich hab folgendes Problem:
    Ich hab ein Spil programmiert, wo man nur ganze Zahlen eingeben soll.
    Wenn der Benutzer eine Kommazahl mit . als Komma benutzt, dann schneid ich einfach alles hinter dem Komma per double to int ab. Aber wenn der User bspw. 2,5 eingibt, dann stürzt das Programm ab und wenn er eine zeichenkette eingibt verfängt sich das Programm in einer Endlosschleife. Hier mal das Programm:

    #include <stdio.h>
    #include <stdlib.h>
    
    // GLOBALE VARIABLEN DEFINIEREN
    int hoelzer = 100, zug = 2, max = 99, ziehen = 0, spieler = 1, modus = 0;
    double AI = 0, eingabe = 0;
    
    // FUNKTIONEN DEFINIEREN
    int Mensch_Spiel();
    int Computer_Spiel();
    int runden(double d);
    
    int main()
    {
    	modus   = 0;
    	zug   = 2;
    	hoelzer = 100;
    	max     = 99;
    
    	printf_s("Willkommen beim Streichholzspiel. Bitte w\x84hle einen Modus\n\n");
    	printf_s("1 - Spiel gegen Mitspieler\n2 - Spiel gegen Computer\n3 - Beenden\n\n");
    
    	while(!modus) {
    		scanf_s("%lf", &eingabe);
    		modus = eingabe;
    
    		if(modus == 0 || modus > 3) {
    			printf_s("\n\n1 - Spiel gegen Mitspieler\n2 - Spiel gegen Computer\n 3 - Beenden\n\n");
    			modus = 0;
    		}
    	}
    
    	switch(modus) {
    		case 1: system("cls"); Mensch_Spiel(); break;
    		case 2: system("cls"); Computer_Spiel(); break;
    		case 3: return 0;
    	}
    
    	return 0;
    }
    

    Ist jetzt nur die Mainfunktion. Es geht ja auch erstmal nur darum. Habt ihr eine Idee, wie man das abfangen kann? Weil scanf_s erwartet ja einen double-Wert.



  • lies doch statt 'double' strings ein (%s). geht z.b. auch mit gets/fgets und dann mach mit atoi bzw. strol einen integer-wert draus.
    🙂



  • ~fricky schrieb:

    strol

    strtol

    🙂



  • Soweit ich das verstanden hab, liest atoi doch nur Zahlen aus einer Zeichenkette aus, oder? Ich möchte aber, dass zeichenketten nicht akzeptiert werden, sondern gleich nochmal ne neue Eingabe gemacht werden muss.



  • Dann bastel dir eine Funktion, die prüft, ob der String wirklich nur aus Ziffern besteht.

    Zum Beispiel so (ungetestet):

    bool IsPureNumber(char *s) {
    	for(;*s;s++) {
    		if(*s<48 || *s>57) {
    			return false;
    		}
    	}
    	return true;
    }
    


  • Cloppy schrieb:

    Soweit ich das verstanden hab, liest atoi doch nur Zahlen aus einer Zeichenkette aus, oder? Ich möchte aber, dass zeichenketten nicht akzeptiert werden, sondern gleich nochmal ne neue Eingabe gemacht werden muss.

    strtol hat den endptr als Parameter. Mit dem kannst du checken, ob Müll eingegeben wurde.

    Gruß,
    B.B.



  • Cloppy schrieb:

    Soweit ich das verstanden hab, liest atoi doch nur Zahlen aus einer Zeichenkette aus, oder? Ich möchte aber, dass zeichenketten nicht akzeptiert werden, sondern gleich nochmal ne neue Eingabe gemacht werden muss.

    Wie meinst du das? Wenn der Benutzer etwas eingibt, ist das immer erstmal eine Zeichenkette. Ob scanf direkt eine Konvertierung vornimmt, oder im Anschluss eben atoi, strol oder ähnliches, ist doch völlig egal. Wenn du allerdings einfach den eingegebenen String auf unzulässige Zeichen prüfen willst, dann mach sowas wie in meinem Beispiel.

    Im Übrigen ist es doch auch nicht ratsam, zwar Eingaben wie "2 Spieler" abzuweisen, wie du es ja willst, aber dann eine Eingabe wie "2.5" zuzulassen, weil es ja eine Zahl ist. Ich würde ihn in dem Fall auch nochmal eingeben lassen. Am Ende hat er gedanklich gerundet und wollte damit sagen, dass er ein 3-Spieler-Spiel will... 😉



  • Big Brother schrieb:

    Cloppy schrieb:

    Soweit ich das verstanden hab, liest atoi doch nur Zahlen aus einer Zeichenkette aus, oder? Ich möchte aber, dass zeichenketten nicht akzeptiert werden, sondern gleich nochmal ne neue Eingabe gemacht werden muss.

    strtol hat den endptr als Parameter. Mit dem kannst du checken, ob Müll eingegeben wurde.

    Gruß,
    B.B.

    Auch wieder wahr! 😃



  • Big Brother schrieb:

    strtol hat den endptr als Parameter. Mit dem kannst du checken, ob Müll eingegeben wurde.

    das haben wir doch letztens erst von supertux gelernt.
    🙂



  • Ich bin entweder zu doof, oder steh aufm Schlauch. Hab jetzt folgenden Code, aber geändert hat sich nix.

    #include <stdio.h>
    #include <stdlib.h>
    
    // GLOBALE VARIABLEN DEFINIEREN
    int hoelzer = 100, zug = 2, max = 99, ziehen = 0, spieler = 1;
    double AI = 0;
    char eingabe[2] = "";
    char * pEnd;
    long int modus = 0;
    
    // FUNKTIONEN DEFINIEREN
    int Mensch_Spiel();
    int Computer_Spiel();
    int runden(double d);
    
    int main()
    {
    	modus   = 0;
    	zug     = 2;
    	hoelzer = 100;
    	max     = 99;
    
    	printf_s("Willkommen beim Streichholzspiel. Bitte w\x84hle einen Modus\n\n");
    	printf_s("1 - Spiel gegen Mitspieler\n2 - Spiel gegen Computer\n3 - Beenden\n\n");
    
    	while(!modus) {
    		scanf_s("%s", &eingabe);
    		modus = strtol(eingabe, &pEnd, 2);
    
    		printf_s("Ergebnis: %d", modus);
    
    		system("PAUSE");
    
    		if(modus == 0 || modus > 3) {
    			printf_s("\n\n1 - Spiel gegen Mitspieler\n2 - Spiel gegen Computer\n 3 - Beenden\n\n");
    			modus = 0;
    		}
    	}
    
    	switch(modus) {
    		case 1: system("cls"); Mensch_Spiel(); break;
    		case 2: system("cls"); Computer_Spiel(); break;
    		case 3: return 0;
    	}
    
    	return 0;
    }
    


  • ^^ die 2 als basis im 'strtol' ist bestimmt falsch. oder willst du, dass der benutzer binärzahlen eingeben soll?
    🙂



  • ~fricky schrieb:

    Big Brother schrieb:

    strtol hat den endptr als Parameter. Mit dem kannst du checken, ob Müll eingegeben wurde.

    das haben wir doch letztens erst von supertux gelernt.
    🙂

    immerhin war mein Beitrag doch nicht so nutzlos (wie ich ursprünglich dachte, da sich keine meldete).

    @_matze: Ascii Werte "hard"-zucodieren finde ich idR nicht gut, am besten

    if(*s<'0' || *s>'9')
    

    hat unter anderem den Vorteil, dass es leicht lesbarer ist. Wobei ich eher

    if(isdigit(i) == 0)
    

    benutzt hätte.

    edit: @Cloppy: wie fricky schon angedeutet hat: nimm 10 oder 0 statt die 2 in strtol. Und was nutzt dir strtol, wenn du pEnd nie auswertest?


Anmelden zum Antworten