Kontrollieren ob die Eingabe eine Zahl ist
-
Hallo erst mal. Mir ist bewusst, dass dazu x-threads und Hilfen gibt's im Netz. Aber ich bin ein Neuling nicht nur für C++ sondern auch für das Programmieren an sich. Und leider verstehe ich diese codesnipsel nicht und wenn doch, weiß ich nich wie ich es zusamenfügen soll. Ich habe hier ein Programm geschrieben, dass mir die Nullstellen berechnet. Funktioniert auch wunderbar.
#include <iostream> #include <math.h> using namespace std; int main () { cout << "Geben Sie den Koeffizienten p ein:"; double p; cin >> p; cout << "Geben Sie den Koeffizienten q ein:"; double q; cin >> q; double b; b =((p*p)/4)-q; if (b<0) cout<<"keine reelle Loesung"<<endl; else { if (b==0) cout<<"Es gibt eine reelle Loesung x="<<(-p/2)<<endl; else cout<<"Es gibt zwei reelle Loesungen x_1="<<(-p/2)+sqrt(b)<<" und x_2="<<(-p/2)-sqrt(b)<<endl; } }
Wie könnte man jetzt am einfachsten testen ob wirklich eine zahl eingegeben wurde?
Vielen Dank!
-
Wenn keine Zahl eingegeben wurde, ergibt eine anschließende Auswertung des Streams 0/false. Ungetestet:
template <typename T> void read_or_ignore(T &var, std::istream &in) { while (!(in >> var)) // Solange Auslesen nicht erfolgreich war { in.clear(); // Fehlerstatus zurücksetzen in.ignore(1); // Nächstes Zeichen verwerfen } } // ... double p; read_or_ignore(p, cin);
-
Wie ich mal aus deinem recht anspruchslosen Code herleite, bist du noch Anfänger.
Wenn du einen int als Eingabe erwartest, aber irgendwas anderes eingegeben wird, wird std::cin in den Fehlerstatus versetzt. Du kannst dann nix mehr eingeben lassen.
Das kann man mitcin.clear();
wieder wegbekommen.
Nützt nur leider wenig, da das Fehlerhafte Zeichen noch im Puffer drin ist und bei der nächstens Eingabe wieder ausgewertet wird.
Du kannst es aber überlesen, mitcin.ignore(1000, /*Anzahl der zeichen, die ignoriert werden sollen, soltle groß genug sein wenn der Benutzer mal wieder übertreibt*/, '\n' /*alle zeichen bis zu einem newline werden überlesen*/);
Damit kannste das also loswerden.
Jetzt willst du aber noch rausfinden, ob denn was falsch gemacht wurde.
Überprüfen, ob cin im Fehlerstatus ist, kannste zb. mit der Memberfunktionfail()
if(cin.fail()) /* das was oben besprochen wurde*/;
Du kannst das aber auch abkürzen mit
if(!cin)
Das kannst du auch gleich mit einer Eingabe verknüpfen: Wenn was falsch eingebeben wurde, ist fail() true. Mann setzt um die Eingabe also zusätzliche Klammern und überprüft dann.
Schlussendlich sieht's dann so wie bei SeppJ aus:
int a; if(!(cin >> a)) { std::cin.clear(); std::cin.ignore(1000, '\n'); //'\n' ist dein Enter! }
Und am besten noch in einer Schleife verpackt:
while(!(cin >> a)) //...
-
std::cin.ignore(1000, '\n');
Ney, mach doch gleich
std::cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
//'\n' ist dein Enter!
Das kann man aber schöner sagen :p
Ja,
std::cin
s failbit wird dann gesetzt (unterscheide zwischen failbit und badbit).
-
Hab' ich nicht gemacht, weil ich ihm dann auch noch hätte erklären müssen was numeric_limits ist. Außerdem ist's eher unwahrscheinlich, dass jemand so viel eingibt..
Für unseren Anfänger:
mit
std::numeric_limits<Standard-Datentyp>::max()
bekommt man den maximalen Wert, der in diesem Datentyp speicherbar ist. Mit streamsize ist das in diesem Fall eben die maximale Anzahl an Zeichen, die eingegeben werden kann. Man muss dafür die Header
<limits>
mit einbinden.
Unnötiger Mehraufwand in diesem Fall, s' gibt sowieso keiner so viel ein, nimm einfach nen Wert der dir groß genug scheint (bei richtigen "Projekten" darfst du davon aber natürlich nicht ausgehen.), die 1000 hab ich nun schon oft bei richtigen Projekten gesehen und einfach mal auch genommen.
-
numeric_limits<streamsize>::max() ist ein Sonderwert, bei dem der Stream beliebig lang ignoriert. (Bis man auf das entsprechende Zeichen trifft.)
-
Tja, danebengeraten.
Ich hab mir das einfach nur vom Namen abgelitten. Wär auch mal wieder viel zu verständlich, dass streamsize = Größe des Eingabepuffers ist (ist der etwa "beliebig" lang oder was?).
-
cooky451 schrieb:
numeric_limits<streamsize>::max() ist ein Sonderwert, bei dem der Stream beliebig lang ignoriert. (Bis man auf das entsprechende Zeichen trifft.)
Wieso sollte das ein Sonderwert sein? Das ist ein Integerwert. Der ignoriert bestimmt nichts. Incognito hat es genau richtig beschrieben, zumindest bis dahin, wo er sagt, dass eh niemand so viel eingibt. Dafür gibts dann ja den Delimiter.
-
Tachyon schrieb:
cooky451 schrieb:
numeric_limits<streamsize>::max() ist ein Sonderwert, bei dem der Stream beliebig lang ignoriert. (Bis man auf das entsprechende Zeichen trifft.)
Wieso sollte das ein Sonderwert sein?
streamsize
ist eintypedef
aufint
/long
. Vielleicht prüft ja internistream::ignore
aufn = numeric_limits<streamsize>::max()
(und falls das wahr ist, wird beliebig lang ignoriert). Plausibel wärs.
Sonst hat icognito aber auch nur halb Recht; Ich empfehle ihm den Satz von Murphy.
-
Hacker schrieb:
Tachyon schrieb:
cooky451 schrieb:
numeric_limits<streamsize>::max() ist ein Sonderwert, bei dem der Stream beliebig lang ignoriert. (Bis man auf das entsprechende Zeichen trifft.)
Wieso sollte das ein Sonderwert sein?
streamsize
ist eintypedef
aufint
/long
. Vielleicht prüft ja internistream::ignore
aufn = numeric_limits<streamsize>::max()
(und falls das wahr ist, wird beliebig lang ignoriert). Plausibel wärs.
Sonst hat icognito aber auch nur halb Recht; Ich empfehle ihm den Satz von Murphy.Plausibel wäre, dass der Stream einfach nicht mehr aufnehmen kann, als der Endwert des Typs zur Repräsentation der Größe angibt. Da der Stream nicht aufnehmen kann kann, muss man dann auch nicht beliebig lange ignorieren, sondern eben nur so lange, bis nicht die maximal mögliche Kapazität erreicht wurde.
Was der Stream dann damit vielleicht macht, ist Spekulation und vermutlich implementierungsabhängig.
-
Tachyon schrieb:
Was der Stream dann damit vielleicht macht, ist Spekulation und vermutlich implementierungsabhängig.
Es gibt da so ein Dokument, das nennt sich C++-Standard. Sollte man mal überflogen haben. Da muss sich die Implementierung dran halten. Dann muss man auch nicht spekulieren oder sich selber zusammenreimen.
cooky451 hat natürlich Recht.
-
SeppJ schrieb:
[...]Es gibt da so ein Dokument, das nennt sich C++-Standard. [...]
Dann les' noch mal. Wie Du aus der Aussage im Standard cookies Aussage ableitest, ist mir nicht ganz klar.
-
Tachyon schrieb:
SeppJ schrieb:
[...]Es gibt da so ein Dokument, das nennt sich C++-Standard. [...]
Dann les' noch mal. Wie Du aus der Aussage im Standard cookies Aussage ableitest, ist mir nicht ganz klar.
Siehe 27.7.2.3, Klausel 25, 1. Punkt. Das ist eine Implikation.
(Edit)
C++-Standard schrieb:
Characters are extracted until
any of the following occurs:
- if n != numeric_limits<streamsize>::max() (18.3.2), n characters are extracted
-
Und das impliziert, wenn
n == numeric_limits<streamsize>::max()
wird beliebig lange konsumiert? Das halte ich doch für eine sehr gewagte Implikation.
-
Tachyon schrieb:
Und das impliziert, wenn
n == numeric_limits<streamsize>::max()
wird beliebig lange konsumiert? Das halte ich doch für eine sehr gewagte Implikation.Was ist daran gewagt? Das ist handfeste Logik.
Da steht: Wenn nicht (B und C), dann A. Mit B "n erreicht" und " C "n ist nicht max" und A "es wird weiter extrahiert". Daraus folgt: Wenn nicht C, dann A.
-
Na gut. Hast recht. Man (ich) sollte vielleicht alles lesen, und nicht nur die Beschreibung der Sonderfälle.