If(Eingabebuffer gefüllt){...}



  • Hallo,

    ein Problem, das ich bereits zweimal hatte:

    Derzeit in diesem Code:

    #include <iostream>
    #include <iomanip>
    #include <fstream>
    #include <cmath>
    
    void coordsystem(int xpon, int ypon, int format);
    void saveinfile(int ded);
    
    int main()
    {
    	int xpos, ypos, format = 10000, wdh = 1, tries = 0, xyrelation = 1, ymax = format * xyrelation;
    
    	std::cout << "Please enter the width of your console in characters: ";
    	std::cin >> format;
    	std::cout << "Please enter the relation between x | y: 1 | ";
    	std::cin >> xyrelation;
    	ymax = format * xyrelation;
    	std::cout << std::endl << std::endl;
    	std::cout << "Please enter the coords of one point ( [-]" << format / 2 << " , [-]" << ymax / 2 << " ): x : ";
    
    	do
    	{
    
    		if (tries == 0)
    		{
    			if (wdh == 2)
    			{
    				std::cout << "\n\nPlease try it again: ";
    				for (int i = 1; i <= 31 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)); i++)
    				{
    					std::cout << " ";
    					if (i == 31 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)))
    					{
    						std::cout << "x : ";
    					}
    				}
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');				// hier liegt das Problem: bei Eingabe eines Buchstaben wird die nächst Eingabe ignoriert
    			}
    
    			std::cin >> xpos;
    
    			if (std::cin.fail())
    			{
    				std::cin.clear();
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    				std::cout << "\n\n\nERROR m000: Incorrect Input!\n\n";
    				wdh = 2;
    				tries = 0;
    			}
    			else if (xpos > format / 2)
    			{
    				std::cout << "\n\n\nERROR m001: Invalid XPOS!\n\n";
    				wdh = 2;
    				tries = 0;
    			}
    			else if(std::cin.good())
    			{
    				tries = 0;
    				wdh = 0;
    
    				for (int i = 1; i <= 52 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)); i++)
    				{
    					std::cout << " ";
    					if (i == 52 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)))
    					{
    						std::cout << "y : ";
    					}
    				}
    
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');				// hier noch einmal
    				std::cin >> ypos;
    				if (std::cin.fail())
    				{
    					std::cout << "\n\n\nERROR m000: Incorrect Input!\n\n";
    					std::cin.clear();
    					std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    					wdh = 2;
    					tries = 1;
    				}
    				else if (ypos > ymax / 2)
    				{
    					std::cout << "\n\n\nERROR m002: Invalid YPOS!\n\n";
    					wdh = 2;
    					tries = 1;
    				}
    				else
    				{
    					wdh = 0;
    					tries = 0;
    				}
    			}
    		}
    		else if (tries == 1)
    		{
    			tries = 0;
    			//wdh = 0;
    			if (wdh == 2)
    			{
    				std::cout << "\n\nPlease try it again: ";
    				for (int i = 1; i <= 31 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)); i++)
    				{
    					std::cout << " ";
    					if (i == 31 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)))
    					{
    						std::cout << "y : ";
    					}
    				}
    			}
    			else
    			{
    				for (int i = 1; i <= 52 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)); i++)
    				{
    					std::cout << " ";
    					if (i == 52 + (std::floor(log10(abs(format / 2)) + 1)) + (std::floor(log10(abs(ymax / 2)) + 1)))
    					{
    						std::cout << "y : ";
    					}
    				}
    			}
    
    			std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');					// und hier schließlich auch noch einmal
    			std::cin >> ypos;
    
    			if (std::cin.fail())
    			{
    				std::cout << "\n\n\nERROR m000: Incorrect Input!\n\n";
    				std::cin.clear();
    				std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    				wdh = 2;
    				tries = 1;
    			}
    			else if (ypos > ymax / 2)
    			{
    				std::cout << "\n\n\nERROR m002: Invalid YPOS!\n\n";
    				wdh = 2;
    				tries = 1;
    			}
    			else
    			{
    				wdh = 0;
    				tries = 0;
    			}
    		}
    
    	} while (wdh > 0);
    
    	coordsystem(xpos, ypos, format);
    
    	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	std::cin.get();
    	return 0;
    }
    
    void coordsystem(int xpon, int ypon, int format)
    {
          ...
    }
    
    void saveinfile(int ded)
    {
          ...
    }
    

    Und zwar, dass ich überprüfen will, ob im Eingabebuffer noch etwas drinnen ist, um das dann entsprechend daraus zu leeren.
    Bei

    std::cin.ignore(std::numeric_limits<std::streamsize>::max()
    

    ist das Problem, dass, wenn kein '\n' im Puffer ist, die nächste Eingabe gleich auch noch ignoriert wird, oder eben bis zum nächsten Enter.

    #include <iostream>
    #include <conio.h>
    #include <windows.h>
    #include <string>
    using namespace std;
    
    bool PW(string);
    void PWtrue();
    int PWfalse(int i);
    
    int main(void)
    {
    	for(int i = 3; i >= 1; i--)
    	{
    		cout << "Passwort eingeben: ";
    		if(PW("Notebook"))
    		{
    			PWtrue();
    			break;
    		}
    		else
    		{
    			system("cls");
    			if(PWfalse(i) == 1)
    			{
    				return 0;
    			}
    			system("cls");
    		}
    	}
    	return 0;
    }
    
    bool PW(string rightPW)
    {
    	char lastsign;
    	string wholePW;
    	cin.sync ();
    	lastsign = getch ();
    
    	while(lastsign != 0x0D)
    	{
    
    		if(lastsign != 0x08)
    		{
    				wholePW += lastsign;
    				putch('*');									
    		}
    		else if(lastsign == 0x08 && wholePW.length() > 0)
    		{
    			wholePW.resize(wholePW.length() - 1);
    			cout << "\b \b";					
    		}
    		lastsign = getch ();
    	}
    	if(wholePW == rightPW)
    	{
    		return true;
    	}
    	else
    	{
    		return false;
    	}
    
    }
    
    void PWtrue()
    {
    	system("cls");
    	for(int h = 1; h <= 3; h++)					
    	{
    		cout << "Passwort akzeptiert!\n\n\nProgramm wird gestartet";
    		for(int f = 1; f <= 3; f++)	
    		{
    			cout << " .";
    			Sleep(600);
    		}                            // an dieser Stelle, wenn man während dem Sleep irgendwelche Zeichen eingibt; bei Enter wird auch die nächste Eingabe natürlich übersprungen
    		if(h <= 2)										
    		{
    			system("cls");
    		}
    	}
    }
    
    int PWfalse(int i)
    {
    	if(i == 1)
    	{
    		cout << "\a";
    		system("cls");
    		for(int h = 1; h <= 3; h++)	
    		{
    			cout << "Programm wird beendet";
    			for(int f = 1; f <= 3; f++)	
    			{
    				cout << " .";
    				Sleep(600);
    			}                    // ebenso hier, wobei es hier natürlich nicht von Bedeutung ist
    			if(h <= 2)	
    			{
    				system("cls");
    			}
    		}
    		return 1;
    	}
    	else
    	{
    		cout << "\a";
    		for(int a = 5; a >= 0; a--)
    		{
    			system("cls");
    			cout << "Passwort abgelehnt!\n\n\n\nErneuter Versuch in " << a << " Sekunden moeglich.\n\nNoch " << i - 1 << " Versuche uebrig.";
    			Sleep(999);
    		}               // und hier natürlich auch
    		return 2;
    	}
    }
    

    Ich hoffe mein Problem wurde bis hierher klar.
    Die Codes sind nicht komplett relevant, ich wollte nur den Zusammenhang klar machen. An den entsprechenden Stellen habe ich Kommentare hinzugefügt. Gerade beim zweiten Beispiel weiß ich allerdings auch, dass es nicht unbedingt perfekt ist, das habe ich sehr am Anfang geschrieben, als ich mich gerade erst mit C++ zu beschäftigen begann, was auch erst ein paar Wochen her ist. Für Verbesserungen bin ich natürlich trotzdem offen. 😉
    Die beiden Beispielprogramme sind nur kleine (mir selbst erdachte) Übungen. Bisher habe ich immer eine Lösung finden können, doch an diesem Problem scheitere ich irgendwie...
    Auch Google hat mir nicht weitergeholfen.

    Und, um nicht noch ein weiteres Thema eröffnen zu müssen:
    gibt es eine bessere Möglichkeit als conio.h für Funktionen, die den gleichen Zweck wie

    getch()
    
    getche()
    

    und

    _kbhit()
    

    erfüllen. Diese sind, wie ich gelesen habe, anscheinend nicht sehr empfehlenswert, da sie nicht im C++-Standard definiert sind.

    Ich danke euch schon einmal, in der Hoffnung, dass es überhaupt Möglichkeiten gibt. 🙂

    Sollte ich hier an falscher Stelle sein, so bitte sagen, wo dieses Thema eher hingehört.



  • Ich verstehe dein Problem nicht. Das cin.ignore() verwirft die Eingabe bis zum Zeilenumbruch. Wenn kein Zeilenumbruch kommt wird weiter verworfen. Daher macht man das normalerweise wenn beim einlesen ein Fehler auftritt.



  • Wenn man, im ersten Beispiel, z.B. 121212121212 oder irgendeinen Buchstaben, also eine ungültige Eingabe eingibt, dann werden zwar diese Eingaben verworfen, aber das Enter löst irgendwie nicht das Ende von std::cin.ignore() aus, womit die nächste Eingabe ignoriert wird, bis man dann Enter drückt.
    Deshalb würde es mich (auch unabhängig von dem Beispiel; durch dieses bin ich nur auf das Thema gekommen) interessieren, ob man überprüfen kann, ob etwas im Eingabepuffer ist.
    Ich hoffe, dass das irgendwie nachvollziehbar ist. 🙂



  • Und warum rufst du ignore bei if (wdh == 2) auf?

    Ohne das jetzt probiert zu haben würde ich darauf tippen, dass du eine falsche Eingabe abfängst, dann setzt du wdh=2 und kommst im nächsten Schleifen durchlauf in den if Zweig und ignorierst die Eingabe bis du wieder ein Zeilenumbrich einliest.

    Edit: zu deiner anderen Frage: http://stackoverflow.com/questions/1927853/how-to-check-if-there-is-anything-in-cin-c



  • Tatsächlich, das ist wohl ein std::cin.ignore() zu viel. 😉
    Danke dir, scheint so zu klappen. Ich hatte das glaube ich wegen Eingaben wie "12a" eingefügt, aber dafür habe ich ja bereits ein std::cin.ignore() eingebaut.
    Außerdem musste ich noch das letzte rausnehmen, da das auch nur blockiert hat.

    Und, da es ja anscheinend nicht anders geht, kann man durchaus getch(), getche() und _kbhit() verwenden oder gilt das eher zu vermeiden?
    Da scheinen sich die Meinungen, die ich gefunden habe, zu teilen.
    Und den Sinn von std::cin.peek() habe ich noch nicht ganz verstanden. Ich verwende dafür meistens getchar(), wobei ich std::cin normalerweise bevorzuge, oder gibt es da irgendeinen Unterschied?



  • Skylac06 schrieb:

    Und, da es ja anscheinend nicht anders geht, kann man durchaus getch(), getche() und _kbhit() verwenden oder gilt das eher zu vermeiden?

    ist halt plattformabhängig.

    Skylac06 schrieb:

    Und den Sinn von std::cin.peek() habe ich noch nicht ganz verstanden. Ich verwende dafür meistens getchar(), wobei ich std::cin normalerweise bevorzuge, oder gibt es da irgendeinen Unterschied?

    peek sagt dir nur das nächste zeichen, ohne es aus dem stream zu entfernen. hättest du aber auch durch google rausfinden können...
    ist z.b. sinnvoll für parsing:

    if( std::is_digit(std::cin.peek()) )
    {
      int tmp; tmp << std::cin;
      std::cout << "zahl :" << tmp << '\n';
    }
    

    getchar habe ich noch nie selbst aufgerufen. wenn ich das möchte, kann ich noch immer char x; std::cin >> x; machen.

    bb



  • Okay, danke euch beiden. 😉


Anmelden zum Antworten