Konsolenfensterschließen verhindern: warum cin clear und co



  • in der Faq wird als problem beschrieben, dass ein einfaches cin.get() eventuell nicht ausreicht:

    - Da die Eingabe gepuffert ist, kann es passieren, dass Daten aus dem Puffer als Eingabe gewertet werden und sich das Programm daraufhin trotzdem sofort schließt

    naja, ich wollte wissen ob das bei dem oben genannten auch passieren kann. Falls nämlich ja wäre das ja nicht nur fürs Fensterschließen-verhindern wichtig... dann könnten ja auch Eingabefragen an den benutzer mitten im programm dadurch zunichte gemacht werden. Ich bin mal davon ausgegangen dass es also in dem fall nicht passieren würde.



  • Shinja schrieb:

    in der Faq wird als problem beschrieben, dass ein einfaches cin.get() eventuell nicht ausreicht:

    - Da die Eingabe gepuffert ist, kann es passieren, dass Daten aus dem Puffer als Eingabe gewertet werden und sich das Programm daraufhin trotzdem sofort schließt

    naja, ich wollte wissen ob das bei dem oben genannten auch passieren kann. Falls nämlich ja wäre das ja nicht nur fürs Fensterschließen-verhindern wichtig... dann könnten ja auch Eingabefragen an den benutzer mitten im programm dadurch zunichte gemacht werden. Ich bin mal davon ausgegangen dass es also in dem fall nicht passieren würde.

    {
        std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
        std::cin.get();
    }
    

    Die C++-Version löscht zuerst alle Fehlbits die eine Eingabe verhindern könnten und ignoriert dann soviele Zeichen wie im Puffer vorhanden sind.

    😉



  • ich nehme das mal als ja, auch die art wie dus machen wolltst gehts nicht.

    Heißt das also, dass ich eigentlich vor jedem cin

    std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
    

    schreiben müsste, weil es sonst zu ner Fehleingabe kommen könnte?

    Falls ja würde ich mich auch über ne Erklärung der 2. zeile freuen, ich versteh zwar was sie wohl machen soll aber nicht wie sie es macht.



  • Nein musst du nicht!
    das cin.clear nutzt du um Fehlerstatuse zu löschen und aus Sicherheit das nichts mehr im Eingabebuffer ist.
    std::cin.ignore(std::cin.rdbuf()->in_avail());
    und dann musst du die im Eingabebuffer die befindlichen Zeichen löschen.
    Du kannst es zum Beispiel bei Fehlereingaben nutzen (Ein Integer wert wird verlangt und ein String wird eingetippt) und am ende um die Konsole nicht zu schließen
    Verstanden?



  • Nein, tut mir leid ich häng da grad ein bisschen:

    man braucht den Eingabepuffer NICHT mitten im Programm zu löschen

    int main
    {
     int a;
     cin>>a;
     string b;
     cin>>b;
     cout<<a<<b;
    }
    

    (nur ein sehr dummes beispiel) Dieses Programm kann keine Probleme wegen dem Eingabepuffer haben.

    wenn ich hingegen die das Konsolenfenster geoeffnet lassen will am Programmende muss ich den Eingabepuffer löschen.

    {
     int a;
     cin>>a;
     cout<<a;
     string b;
     cin>>b;
    }
    

    Das Konsolenfenster könnte trotzdem schließen, weil da noch etwas im Eingabepuffer steht.

    Das ist zumindest so, wie ich dich verstanden hab:

    - Da die Eingabe gepuffert ist, kann es passieren, dass Daten aus dem Puffer als Eingabe gewertet werden und sich das Programm daraufhin trotzdem sofort schließt

    Heißt das also, dass ich eigentlich vor jedem cin

    std::cin.clear();
        std::cin.ignore(std::cin.rdbuf()->in_avail());
    

    schreiben müsste, weil es sonst zu ner Fehleingabe kommen könnte?

    Nein musst du nicht!

    Irgendwie komm ich da net mit



  • #include <iostream>
    using namespace std;
    int main()
    {
     int a;
     cin>>a;
     char b[5];
     cin>>b;
     cout<<a<<b;
    }
    

    okay ich werde es dir so gut wie möglich jetzt erklären!
    jetzt tu mal dieses Programm Kompilieren!
    Und sag mir mal was für ein Compiler du benutzt!
    so starte die .exe Anwendung und gebe, da int eine zahl ist, am anfang einen Buchstaben ein also ein Fehler, da ein integer verlangt wird.
    So das programm sollte folgendes ausgeben:
    a
    4314411
    und dann sofort beenden! ohne das du die b eingeben kannst!
    so und dass wollen wir verhindern dafür brauchen wir das cin.clear und das
    std::cin.ignore(std::cin.rdbuf()->in_avail());

    #include <iostream>
    using namespace std;
    int main()
    {
    	int a;			//Integer a
    	cin>>a;	
    	while(true)		//Endlosschleife
    	{
    
    		if (cin.fail()) //falls im Eingabebuffer ein fehler ist wie zum Beipiel ein A
    		{
    			cin.clear();								//Eingabebufferlöschen
    			cin.ignore(std::cin.rdbuf()->in_avail());	//Restzeichenlöschen
    			cout<<"Eingabe falsch! Wiederholen:"<<endl;	
    			cin>>a;										//neue Eingabe
    		}
    		else
    			break;		//Schleifenabruch
    	}
    	char b[2];		
    	cin>>b;
    	while(true)
    	{
    		if (cin.fail()) //falls im Eingabebuffer ein fehler ist
    	{
    			cin.clear();
    			cin.ignore(std::cin.rdbuf()->in_avail());
    			cout<<"Eingabe falsch!";
    			cin>>b
    	}
    		else
    			break;
    	}
    	cout<<a<<b;		//Ausgabe
    }
    

    Hier wenn du im Erstem ein A eingibst gibt er eine Fehler meldung da cin.fail dann ist. Der Fehler wird gelöscht und eine neue Eingabe wird gefordert.
    Ich hoffe mal das dir das weider hilft bei fragen frag einfach



  • Sehr gut beschrieben. Sowas gehört eigentlich mal ins FAQ, oder steht das schon dadrin und ich habs übersehen?



  • Vielen Dank, jetzt hab ichs kapiert! Das heisst also, dass ich tatsaechlich quasi nach jedem cin diese Kontrolle besser machen sollte (ausser man geht von der Fehlerlosigkeit der Benutzer aus... und die ist denke ich aber sehr selten) Es hat mich oben ein bisschen verwirrt, dass ich das bei eingaben mitten im Programm nicht zu machen braeuchte.

    Nur noch eine kurze Frage:

    statt dieser while(true) koennte man da auch einfach:

    while(cin.fail())
    ...
    

    schreiben?



  • am besten noch so

    do
    {
    //cin und so
    } while(!cin);
    


  • auch wieder wahr.

    Danke! !cin und cin..fail() bedeuten das gleiche, ja?



  • Ja, !cin und cin.fail() bedeuten das gleiche.

    Ich habe das Problem, dass der Code den Dying vorgestellt hatte, nicht so funktioniert, wie ich es wollte. Geb cih beispielsweise ein 's' ein, gerät er danach in eine Endlosschleife, mir ist es nicht möglich, eine neue eingabe zu machen...

    Ich hab auch schon mal probiert, das

    cin.ignore(std::cin.rdbuf()->in_avail());
    

    durch ein

    cin.seekg(0L,ios:.end)
    

    zu ersetzen. ( Hab ich aus einem Buch)
    klappt beides nicht



  • Hm kann sein weil ich im code ein fehler hab

    #include <iostream>
    using namespace std;
    int main()
    {
        int a;            //Integer a
        cin>>a;   
        while(true)        //Endlosschleife
        {
    
            if (cin.fail()) //falls im Eingabebuffer ein fehler ist wie zum Beipiel ein A
            {
                cin.clear();                                //Eingabebufferlöschen
                cin.ignore(std::cin.rdbuf()->in_avail());    //Restzeichenlöschen
                cout<<"Eingabe falsch! Wiederholen:"<<endl;   
                cin>>a;                                        //neue Eingabe
            }
            else
                break;        //Schleifenabruch
        }
        char b[2];       
        cin>>b;
        while(true)
        {
            if (cin.fail()) //falls im Eingabebuffer ein fehler ist
        {
                cin.clear();
                cin.ignore(std::cin.rdbuf()->in_avail());
                cout<<"Eingabe falsch!";
                cin>>b; //<<da war der fehler hab das selimikon vergessen
                        //Manche Compiler juckt das nicht und es kommen fehler...
        }
            else
                break;
        }
        cout<<a<<b;        //Ausgabe
    }
    

    Wenn es nicht dann weiß ich auch nicht was dein problem ist...



  • hi, hatte deinen Code mit copy & paste übernommen, klappte aber trotzdem wie gesagt
    nicht. Hab jetzt aber aus nem anderen tut ne Lösung die funktioniert:

    cin.ignore(std::numeric_limits<int>::max(),'\n');
    

    statt

    cin.ignore(std::cin.rdbuf()->in_avail());
    

    Verstehe aber immer noch nicht, warum die Variante mit

    cin.ignore(std::cin.rdbuf()->in_avail());
    

    nicht funktioniert. Jemand ne Idee?



  • cin.ignore(std::numeric_limits<int>::max(),'\n');
    

    solange du das kapierst ist alles gut aber pass auf der leert den Buffer nur bis '\n' 😉 was für ein Compiler?



  • hab dev-c++, weiß leider net, was da für ein compiler hintersteckt...
    Bis '\n' zu löschen sollte aber doch für die misten Eingaben reichen, oder?



  • !cin und cin.fail() sind nicht das gleiche, ersteres ist wahr wenn !cin.good() wahr ist bzw. cin.good() falsch ist und letzteres ist nur wahr wenn das failbit gesetzt ist. Es gibt aber auch noch das badbit und das eofbit.
    Und ich glaub die stream-callbacks können da auch noch mitmischen, bin ich mir aber nicht zu 100% sicher.



  • lolz schrieb:

    !cin und cin.fail() sind nicht das gleiche, ersteres ist wahr wenn !cin.good() wahr ist bzw. cin.good() falsch ist und letzteres ist nur wahr wenn das failbit gesetzt ist. Es gibt aber auch noch das badbit und das eofbit.

    Falsch - schau dir einfach mal ios::operator!() und ios::fail() an, dann siehst du, was sie machen (op! gibt normalerweise fail() zurück und dieses wiederum überprüft das failbit und badbit).

    (außerdem wird auch bei einem EOF das badbit gesetzt)


Anmelden zum Antworten