Eingabe überprüfen



  • Hallo!
    Ich, C++-Anfänger, schreibe gerade ein Spiel und habe folgendes Problem.
    Ich erwarte vom Spieler, dass er eine Eingabe tätigt.
    Zur Wahl stehen ihm die Integer 1, 2 oder 3.
    Mein Programm soll nun prüfen, ob die Eingabe gültig ist.
    Gültig sollen nur diese 3 Ziffern sein und alle anderen Zeichen (Buchstabe, Sonderzeichen, Zahlen) nicht.

    Für alle anderen Zahlen als 1, 2 und 3 habe ich folgenden Code:

    else if(level > 3 || level < 1)
    	{
    		cout << "Ihre Eingabe ist ungueltig!\n";
    		_getch();
    		goto Leveleingabe;
    	}
    

    und für fehlerhafte Eingabe folgenden Code:

    else if(cin.fail())
    	{
    		cout << "Ihre Eingabe ist ungueltig!\n";
    		_getch();
    		eingabeloeschen();
    		cin.clear();
    		cin.ignore(1000, '\n');
    		goto Leveleingabe;
    	}
    

    Beides löst mein Problem, ABER sobald ich beide Schleifen in meinen Code setze (ich blende immer die andere beim Testen aus, indem ich es als Kommentar zwischen "/* ... */" setze), habe ich ein Problem und zwar es entsteht eine Endlosschleife. Um es auszuprobieren kann ich Euch mal den ganzen Code hier zeigen (bin noch am Anfang - also Code noch unvollständig!):

    #include "stdafx.h"
    #include <iostream>
    #include <conio.h>
    #include <windows.h>
    #include <math.h>
    #include "ctime"
    
    using namespace std;
    
    int b,h,i,x,y,level; //global
    int feld [100][100];
    
    void gotoxy(int x,int y)
    {
    	HANDLE hConsole;
    	COORD cursorLoc;
    	std::cout.flush();
    	cursorLoc.X = x;
    	cursorLoc.Y = y;
    	hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    	SetConsoleCursorPosition(hConsole, cursorLoc);
    }
    
    void eingabeloeschen()
    {
    	int i = 0;
    
    	gotoxy(0,0);
    
    	do
    	{
    	std::cout << "                                                                               \n";
    	i++;
    	}
    	while(i<8);
    
    	gotoxy(0,0);
    }
    
    void felderstellen()
    {
    		for(y=0; y<b+2; y++)
    	{
    			gotoxy(0,y);
    			cout<<"#";
    			gotoxy(b+1,y);
    			cout<<"#";
    	}
    
    	for(x=0; x<h+2; x++)
    	{
    			gotoxy(x,0);
    			cout<<"#";
    			gotoxy(x,h+1);
    			cout<<"#";
    	}
    
    			for (x=1; x<b+1; x++) 
      { 
    		for (y=1; y<h+1; y++) 
        {
    			feld[x][y] = 0;  // Spielfeld = 0 -> Wasser
    			gotoxy(x,y);
    		  cout << "~"; // Wasser -> ~
    	}
      } 
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	Leveleingabe:
    	cout << "Waehlen Sie eine Schwierigkeitsstufe aus:\n";
    	cout << "Einfach (1)\nMittel (2)\nSchwer (3)\n";
    	cin >> level;
    
    	eingabeloeschen(); // löscht (0,0) bis (80,0) und (0,7) bis (80,7) und kehrt auf (0,0) zurueck
    
    	if(level==1)
    	{
    		b = 5;
    		h = 5;
    	}
    	else if(level==2)
    	{
    		b = 8;
    		h = 8;
    	}
    	else if(level==3)
    	{
    		b = 12;
    		h = 12;
    	}
    	else if(level > 3 || level < 1)
    	{
    		cout << "Ihre Eingabe ist ungueltig!\n";
    		_getch();
    		goto Leveleingabe;
    	}
    	else if(cin.fail()) // http://www.tutorials.de/c-c/256971-pruefen-ob-eingabe-int-ist.html oder "c++ eingabe kein int" bei google
    	{
    		cout << "Ihre Eingabe ist ungueltig!\n";
    		_getch();
    		eingabeloeschen();
    		cin.clear();
    		cin.ignore(1000, '\n');
    		goto Leveleingabe;
    	}
    
    	felderstellen();
    
    	_getch();
    	return 0;
    }
    

    Ich hoffe Ihr könnt mir helfen!

    lg fener000



  • Hä? Ich weis nicht, ob ich dein Problem verstehe. Dazu ist das Programm etwas zu schlecht und deine Aussagen zu wage.

    Aber ein Fehlerfall kann auftreten dadurch dass du den fehlerhaften Eingabepuffer nie löschst, also nicht resetest.


  • Mod

    Du solltest zuerst prüfen, ob die Eingabe an sich erfolgreich war. Denn was für einen Wert hat level , wenn gar kein Integer eingegeben wurde? Wenn du mit diesem Wert im Fall von Zeile 93 landest, dann hast du eine Endlosschleife.

    Oder dein Problem ist ein ganz anders und ich habe bloß irgendeinen von mehreren Fehlern gefunden. Code mit globalen Variablen (noch dazu teilweise einbuchstabige Bezeichner!) und goto ist ungeheuer schwer zu lesen und fehleranfällig. Es kann daher sehr gut sein, dass da noch viel mehr Fehler drin sind. Beides solltest du daher vermeiden. Wenn du dein Programm ohne diese Stilfehler nochmal neu schreibst, werden sich auch die Logikfehler sehr wahrscheinlich von alleine auflösen.



  • @skym0sh0: Ich meine, ich hätte mich eig. klar ausgedrückt.
    Ja, kann gut sein, dass das Programm "schlecht" ist,
    Programmieren lerne ich erst seit wenigen Wochen.

    In der ersten Schleife hatte ich vergessen den Eingabepuffer zu leeren.
    Ich danke dir, jetzt ist das Problem gelöst.

    @SeppJ: Ich danke dir. Werde die Variablen sinvoller benennen. Das Vermeiden von goto's fällt mir leider etwas schwer, aber ich werde mich bemühen goto's zu vermeiden.

    lg fener000


  • Mod

    fener000 schrieb:

    In der ersten Schleife hatte ich vergessen den Eingabepuffer zu leeren.
    Ich danke dir, jetzt ist das Problem gelöst.

    Nicht wirklich elegant. Der Fehler war zunächst ein Logikproblem, jetzt hast du diesen Fehler drin gelassen, dafür aber zusätzlichen Code eingefügt, der den Fehler im Nachhinein korrigiert.



  • Zur Überprüfung der Eingabe wäre das doch passender, oder?

    else if(!(level == '1' || level == '2' || level == '3'))
    	{
    		cout << "Ihre Eingabe ist ungueltig!\n";
    		_getch();
    		eingabeloeschen();
    		cin.clear(); 
        cin.ignore(1000, '\n');
    		goto Leveleingabe;
    	}
    

    Ich verstehe gerade nicht, welchen Fehler du meinst.


  • Mod

    fener000 schrieb:

    Ich verstehe gerade nicht, welchen Fehler du meinst.

    Den, den ich beschreiben habe. Wenn die Eingabe kein Integer war, dann prüfst du einen Müllwert da drauf, ob er <1 oder >3 ist. Wenn dies zutrifft, dann kommst du (bei deinem Ursprungscode) in die Endlosschleife, da dann kein clear() stattfindet, um den Fehlerzustand zurück zu setzen. Jetzt hast du für den Fall <1 oder >3 eben nochmals ein clear() und ignore eingefügt, aber der Fehler ist doch, dass du überhaupt erst einen Müllwert überprüft hast! Im normalen Fall, dass zwar eine gültige Eingabe stattfand, aber diese <1 oder >3 war, willst du doch eigentlich weder clear noch ignore machen!



  • Ahhh... jetzt verstehe ich's!
    Ich danke dir. Hat sich ja mit dem neuen code geklärt.

    lg fener000


Anmelden zum Antworten