try/catch in do/while = endlosschleife?
-
Hi, wir fangen bei uns an der Uni gerade mit c++ an, und sollen ein kleines Konsolen Programm schreiben, das u.A. exception-handling benutzt...
Für eine Menüsteuerung dachte ich mir daher, man könne einfach per try-catch Fehleingaben abfangen. Ich benutze zum einlesen den std::cin Befehl. Wird allerdings eine Exception geworfen, so wiederholt sich zwar die do-while schleife, der cin Befehl wird aber übersprungen...
Hier mein Programmcode:
int auswahl; bool eingabe_ok = false; cout << "\n +++++ " << getName() << ": Wähle eine Funktion:"; // Erwartet wird die Eingabe "1" oder "2" do{ cout << "\n +++++ Triff deine Auswahl: "; try{ cin >> auswahl; if(auswahl == 1 || auswahl == 2) eingabe_ok = true; else cout << "\n +++++ Bitte korrigieren Sie Ihre Eingabe."; }catch(...){ cout << "\n +++++ Bitte korrigiere deine Eingabe."; } }while(eingabe_ok == false);
Gibt man nun was anderes als 1 oder 2 ein (bla, blubb, foo, alles was halt ein String ist), so kommt ununterbrochen die Ausgabe:
+++++ Triff deine Auswahl:
+++++ Bitte korrigiere deine Eingabe.
+++++ Triff deine Auswahl:
+++++ Bitte korrigiere deine Eingabe.
+++++ Triff deine Auswahl:
+++++ Bitte korrigiere deine Eingabe.
+++++ Triff deine Auswahl:
+++++ Bitte korrigiere deine Eingabe.Wenn es am cin Befehl liegt, könnte mir dann jemand den korrigierten Code geben?
-
so benutzt du try/catch auch völlig falsch
so benutzt man es richtig
int foo(int a) throw char* //muss man aber nicht schreiben, mehr dazu unten { if ( a == 0 ) throw "Fehler"; else return a*a*a; } int main() { int i; cin >> i; try { foo(i); catch(const char* a); cout << a << endl; }
das throw (oder wars throws??) ist nicht nötig, man kennzeichnet so nur in der funktions deklaration dass eine exceptions geworfen werden kann
schriebt man nichts hin kann alles passieren, schreibt man throw "Datentyp" dahin wird eine exception von genau diesen typ geworfen (in dem beispiel ein char* string), lässt man die klammern bei dem throw leer kann nichts geworfen werdenich halte dein programm design jedoch nicht so für gut weil man exceptions eig nurw enig braucht und wennd ann nur wenn etwas vorhersehbares fehler erzeugt, was man nicht umgehen kann
aber naja denk ein wenig drüber nach dann schaffst du das, das technische sollte ejtzt kein problem mehr sein
-
Das Problem ist ein anderes. Durch das misslungene Einlesen eines Integers wird das Failbit von Cin gesetzt. Das musst Du dann erst zurücksetzen. So geht es:
int main() { int auswahl; bool eingabe_ok = false; do { cout << "\n +++++ Triff deine Auswahl: "; cin >> auswahl; if(!cin || auswahl < 1 || auswahl > 2) { cout << "\n +++++ Bitte korrigieren Sie Ihre Eingabe."; std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); }else eingabe_ok = true; } while (eingabe_ok == false); return 0; }
-
und das problem ja...
dachte es geht ihm hauptsächlich um das try catch
-
@Skym0sh0,
throws
? Wir sind hier nicht in Java! lol
Grundsätzlich hält man es in C++ so, dass man bei der Funktion nichts angibt über die möglichen geworfenen Exceptions, da dies "Fehleranfällig" ist. Gerade in den Templates kann man im allgemeinen nicht wissen, was ein Template für eine Exception werfen kann, wodurch man diese Spezifikation bei der Funktion nicht angeben kann. Zudem wird sie anders angegeben, dass solltest du nochmals nachlesen.Zu Exceptions haben wir übrigens drei sehr gute Artikel im Magazin:
http://magazin.c-plusplus.net/artikel/Exception-Handling
http://magazin.c-plusplus.net/artikel/Modernes Exception-Handling Teil 1 - Die Grundlagen
http://magazin.c-plusplus.net/artikel/Modernes Exception-Handling Teil 2 - Hinter den KulissenUnd das beschriebene Problem vom Threadersteller hat definitiv mit dem
failbit
vonstd::cin
zu tun.
std::ignore
sollte man allerdings meiner Meinung nach so benutzen:std::cin.ignore(std::cin.rdbuf()->in_avail());
Das Problem ist nämlich, dass nicht alle Betriebsysteme als neue Linie den Linefeed nehmen. Soweit ich weiss, hat man in diesem Punkt keine Garantie. Kann mich da aber auch täuschen. Jedenfalls hat man bei meinem Beispiel sicher alles weg, was drin ist, ausser die Standardimplementation ist fehlerhaft, aber dann ist Hopfen und Malz verloren
Im übrigen, man kann auch einen
std::cin
dazu bringen, dass er bei einem Fehler eine Exception wirft:std::cin.exceptions(std::istream::eofbit | std::istream::failbit | std::istream::badbit);
http://www.cplusplus.com/reference/iostream/ios/exceptions.html
Auf die
bool
Variable kann man übrigens auch verzichten. Indem man eine Endlosschleife und einebreak
Anweisung nimmtUnd wenn man noch ganz fanatisch ist, kann man sowas in eine Templatefunktion auslagern, damit man für alle Typen eine entsprechend geprüfte Eingabe hat. Als Parameter kann man dann ein Eingabetext, Fehlertext und als Referenz die zu befüllende Variable übergeben
Grüssli
-
naja hab noch nicht so viel mit exceptions gemacht weil man sie ja eig ganz gut vermeiden kann bei kleineren simplen programmen
naja das failbit ist zwar das fehlerproblem aber er will doch eigendlich exception handling üben...
von daher meinte ich das
PS: und ja meine erste richtige programmiersprache war java xD machen wir derzeitig auch in der schule