Warum bricht diese Funktion nicht ab, wenn der Wertebereich von int bei der Eingabe über cin überschritten wird?
-
#include <iostream> /* Programm bricht nicht ab, wenn n groeßer ist als der * Variablentyp speichern kann * z.B. fuer 4 Byte großes int darf die Eingabe fuer n nicht groesser * als 2147483647 sein */ using namespace std; int main() { int n = 0; cout << sizeof(n) << endl; do { cout << "Geben sie Eine Zahl ein. (Abbruch mit 0) "; cin >> n; cout << endl; cout << "n = " << n << endl; } while (n > 0); return 0; }Wieso schneidet cin die Eingabe nicht einfach ab oder liefert eine Fehlermeldung, wenn der Wert zu groß ist?
Stattdessen läuft das Programm einfach in einer Endlosschleife weiter.Getestet habe ich es mit gcc 3.4.5 aus dem MinGW Paket unter Windows.
-
Wenn ein Fehler passiert beim Einlesen mit
std::cin, dann wird der Stream als ungültig markiert. Jeder weitere Lesevorgang wird automatisch abgebrochen.nbleibt auf 0 und du hast deine Endlosschleife.Du kannst entweder das Verhalten ändern, in dem du Exceptions fliegen lässt:
http://www.cplusplus.com/reference/iostream/ios/exceptions/Oder du prüft jeweils auf die Gültigkeit des Streams und ob die Einleseoperation erfolgreich war. Danach setzt du den Stream wieder zurück:
http://www.cplusplus.com/reference/iostream/ios/good/
http://www.cplusplus.com/reference/iostream/ios/clear/
http://www.cplusplus.com/reference/iostream/istream/ignore/Grüssli
-
dravere_test schrieb:
Wenn ein Fehler passiert beim Einlesen mit
std::cin, dann wird der Stream als ungültig markiert. Jeder weitere Lesevorgang wird automatisch abgebrochen.nbleibt auf 0 und du hast deine Endlosschleife.Ok,aber wenn n auf 0 bleibt, warum habe ich dann eine Endlosschleife.
Normalerweise würde das Programm die while Schleife dann verlassen müssen, wenn n 0 bleibt.Aber genau das passiert ja nicht.
n nimmt irgendeinen Wert an.cin versucht also zu funktionieren und scheint den Lesepuffer durch den ersten überhohen Eingabewert immer ohne Eingabe von Enter zu füllen, so daß while nie abbrechen kann, da n immer einen Wert hat.
Du kannst entweder das Verhalten ändern, in dem du Exceptions fliegen lässt:
http://www.cplusplus.com/reference/iostream/ios/exceptions/Oder du prüft jeweils auf die Gültigkeit des Streams und ob die Einleseoperation erfolgreich war. Danach setzt du den Stream wieder zurück:
http://www.cplusplus.com/reference/iostream/ios/good/
http://www.cplusplus.com/reference/iostream/ios/clear/
http://www.cplusplus.com/reference/iostream/istream/ignore/Grüssli
Danke, ich werde mir das mal durchlesen.
-
Eh, ja, natürlich, die Schleife bricht ab, sofern du eine zu hohe Zahl gleich zu Beginn eingibst. Wenn du aber zuerst eine Zahl eingibst, welche gespeichert werden kann (z.B. 1234), und danach eine zu grosse Zahl (z.B. 9999999999999999999999999), dann befindest du dich in der Endlosschleife, weil
nseinen alten Wert behält.Also einfach gesagt:
nbehält seinen alten Wert, wenn die Eingabe ungültig ist.Grüssli
-
Dravere schrieb:
Eh, ja, natürlich, die Schleife bricht ab, sofern du eine zu hohe Zahl gleich zu Beginn eingibst. Wenn du aber zuerst eine Zahl eingibst, welche gespeichert werden kann (z.B. 1234), und danach eine zu grosse Zahl (z.B. 9999999999999999999999999), dann befindest du dich in der Endlosschleife, weil
nseinen alten Wert behält.Also einfach gesagt:
nbehält seinen alten Wert, wenn die Eingabe ungültig ist.Grüssli
Aber müßte dann nicht beim dritten mal die Schleife anhalten und nach einer weiteren Eingabe warten?
-
Überlauf schrieb:
Aber müßte dann nicht beim dritten mal die Schleife anhalten und nach einer weiteren Eingabe warten?
Nein. Wenn der Stream ungültig ist, dann bleibt er ungültig, bis du ihn zurücksetzt. Wenn er ungültig ist, wird jede Operation darauf direkt verworfen.
Grüssli
-
Dravere schrieb:
Überlauf schrieb:
Aber müßte dann nicht beim dritten mal die Schleife anhalten und nach einer weiteren Eingabe warten?
Nein. Wenn der Stream ungültig ist, dann bleibt er ungültig, bis du ihn zurücksetzt. Wenn er ungültig ist, wird jede Operation darauf direkt verworfen.
Grüssli
Verstehe, ich müßte also Sicherheitshalber so eine art cin.clear ausführen um die Schleife zu verhindern?
-
Überlauf schrieb:
Dravere schrieb:
Überlauf schrieb:
Aber müßte dann nicht beim dritten mal die Schleife anhalten und nach einer weiteren Eingabe warten?
Nein. Wenn der Stream ungültig ist, dann bleibt er ungültig, bis du ihn zurücksetzt. Wenn er ungültig ist, wird jede Operation darauf direkt verworfen.
Grüssli
Verstehe, ich müßte also Sicherheitshalber so eine art cin.clear ausführen um die Schleife zu verhindern?
Ja. Jedoch sind die ungültigen Eingaben noch immer im Stream (sie wurden ja nicht gelesen!), d.h. der nächste Versuch wird wieder scheitern. Du müsstest daher noch festlegen, wie mit diesen Eingaben verfahren werden soll. Eine einfache aber effektive Möglichkeit ist ignore().