Streamlänge prüfen oder Eingabe überprüfen
-
Hallo, ich hab folgendes Problem.
Schwer zu erklären aber ich versuchs mal
Ich habe folgenden Bildschirm
Eingabe von verschiedenen Zahlen
zb
Zahl1:3
Zahl2:4
Zahl3: hier gebe ich nun nichts ein und drücke nur die Enter Taste.Hier nun die Frage: Kann ich irgendwie eine Exception auswerfen wenn ich nur die Enter Taste drücke OHNE Inhalt.Von mir aus "Geben Sie irgendwas ein hauptsache es steht da was" oder so. Die anderen Inhalte werden nach drücken der Enter Taste in einem Array gespeichert. Durch drücken der Taste Enter wartet er aber nur auf eine Eingabe die aber nicht kommen soll. Geht das irgendwie mit dem Überprüfen ob da nun nichts drin steht oder nicht bzw wie?
-
Schau faq
-
über enter taste drücken ohne inhalt (normalerweise kann man immer noch nach enter eingeben, da >> newlines ignoriert) steht afaik noch nichts in der faq.
hier, so sollte es funktionierenint i; cout << "Eingabe: "; for (;;) { stringstream str; if (cin.get(*str.rdbuf())) { if (str >> i) { cout << "Eingabe war " << i << endl; break; } else { cout << "Sie haben keine Zahl eingegeben!\n"; } } else { cout << "Sie haben nichts eingegeben!\n"; } cout << "Eingabe wiederholen: "; cin.clear(); //falls einmal was nicht klappt, sonst gibt es eine endlosschleife ohne eingabe cin.get(); //das get oben liest kein newline ein. deshalb hier das newline aus dem string rausschleudern }
-
Super danke Enter, schön wärs wenn wir/ich (unser Studentenprojektteam) auch mal auf sowas kommen würden
Aber wir haben eigentlich vor daraus ein Exception Handling zu basteln. Mit dem Beispiel von dir geht das glauben wir etwas schlecht, daher mal ein Ausschnitt aus unserem Quellcode. Wäre nett wenn das einer so umschreiben könnte, dass wir das auch verwenden können. Nochmal Danke für eure Mühe
double getnumber(istream &ein) { double i; // Eingabe ein >> i; // Falls die Eingabe fehlgeschlagen ist wirft er 1 weiter if (ein.fail( )) throw 1; return i; }
und dann der Aufruf
for (i=0;i<10;i++) { cout<<endl<<endl<<endl; cout<<" Zahl"<<i+1<<": "; // Der try-Block für das Exception Handling um Eingabe zu überprüfen try {zahl = getnumber(cin); erfolgreich = true; } catch(const int z) { textcolor(red); cout<<" Falsche Eingabe ! Es sind nur Zahlen erlaubt !"<<endl; textcolor(white); getch(); cin.clear(); while (cin.get() != '\n'); i--; erfolgreich = false; } if(erfolgreich) darray[i] = zahl; }
-
woran hapert's denn?
den code von mir in eine funktion auszulagern?
sichergehen, dass cin.clear() und cin.get() am ende der funktion aufgerufen werden?
schmeißen von exceptions?ein erster ansatz sieht so aus (hab auch eure main etwas aufpoliert... sieht ja grässlich aus, so - btw. der stil ist zwar geschmackssache, aber dein code ist doch etwas unleserlich)
#include <iostream> #include <sstream> using namespace std; class InputError //Weil int schmeißen heißt auf exception handling scheißen { }; class NoInput : public InputError { }; class WrongFormat : public InputError { }; /* get_number liest eine zahl auf einem istream und wirft WrongFormat, wenn sich keine zahl darin befindet, oder NoInput, wenn der eingabestream mit einem newline endet. get_number arbeitet zeilenweise */ int get_number (istream &in) { //da wir mehrere exceptions werfen wollen, müssen wir sichergehen, //dass in.clear() und in.get() den stream reparieren. code wiederholung ist allerdings überflüssig //der destruktor von cleanup wird nämlich auf jedenfall aufgerufen (RAII) struct cleanup { istream ∈ cleanup (istream &in) : in(in) {} ~cleanup () { in.clear(); in.get(); } } cleaner(in); //um zu überprüfen, ob überhaupt etwas eingegeben worden ist, wenden wir einen kleinen trick an. (ist dasselbe, wie oben) //wir lassen von in direkt in den buffer eines streams schreiben, was nur dann fehlschlägt, wenn keine //zeichen im buffer von in sind (das bedeutet, es wurde nichts eingegeben). ansonsten hätten müssten //wir auf eine eingabe warten und druck auf enter würde nichts bewirken. stringstream str; if (in.get(*str.rdbuf())) { int i; //und hier dann ganz normal überprüfen, ob es denn auch wirklich eine zahl war, die eingegeben wurde if (str >> i) return i; else throw WrongFormat(); } else throw NoInput(); } //etwas überarbeitet; hoffe, das macht dir nichts aus. int main () { //bool erfolgreich; //brauchen wir nicht mehr. int darray[10]; int i = 0; while (i<10) //variable i erst so spät wie möglich definieren { //cout<<endl<<endl<<endl; //pfui. wenn schon, dann cout << "\n\n\n"; try { cout<<"Zahl "<<++i<<": "; darray[i] = get_number(cin); cout<<"Erfolgreich. Zahl = " << darray[i] << '\n'; } catch(WrongFormat&) { cout<<"Falsche Eingabe! Es sind nur Zahlen erlaubt!\n"; } catch(NoInput&) { cout <<"Keine Eingabe. Bitte wiederholen.\n"; } } }
ist doch gar nicht so schwer.
jetzt noch ein bisschen flexibler machen.. wenn ich schon dabei bin..#include <iostream> #include <sstream> using namespace std; class InputError { }; class NoInput : public InputError { }; class WrongFormat : public InputError { }; template <class T> struct ExactFormat { static T read (istream &in) { T tmp; if (!(in >> tmp)) throw WrongFormat(); return tmp; } }; template <> struct ExactFormat<string> { static string read (istream &in) { string s; in >> s; return s; } }; struct NotEmpty { stringstream str; NotEmpty (istream &in) { if (!in.get(*str.rdbuf())) throw NoInput(); } stringstream &prepare () { return str; } }; struct ClearAndGet { istream ∈ ClearAndGet (istream &in) : in(in){} ~ClearAndGet () { in.clear(); in.get(); } }; template <class T, class FormatPolicy=ExactFormat<T>, class StreamPolicy=NotEmpty, class CleanUpPolicy=ClearAndGet> class reader { istream ∈ public: reader (istream &in) : in(in) {} T operator () (); }; template <class T, class FormatPolicy, class StreamPolicy, class CleanUpPolicy> T reader<T, FormatPolicy, StreamPolicy, CleanUpPolicy>::operator () () { CleanUpPolicy clean(in); return FormatPolicy::read(StreamPolicy(in).prepare()); } int main () { int i = 0; while (i<10) { try { cout<<"Eingabe "<<++i<<": "; string x = reader<string>(cin)(); cout<<"Erfolgreich. Eingabe: " << x << '\n'; } catch(WrongFormat&) { cout<<"Falsche Eingabe! Es sind nur Zahlen erlaubt!\n"; } catch(NoInput&) { cout <<"Keine Eingabe. Bitte wiederholen.\n"; } } }
dann kannst du z.b. eine format-policy angeben, wenn du weißt, dass dein endbenutzer gerne tausender mit whitespaces streibt
template <class T> struct IgnoreWhitespaces { static T read (istream &in) { char c; stringstream str; while (in.get(c)) if (c != ' ') str << c; return ExactFormat<T>::read(str); } }; //benutzen dann eben so double d = reader<double, IgnoreWhitespaces<double> >(cin)();
ein bisschen overengineered? kann sein...
-
Wow ich bin beeindruckt ! Naja *g* wie gesagt wir sind "noch" Anfänger hoffentlich werden wir auch mal so gut wie du
Erneut 1000 Dank
PS: Es ging im Projekt um Heap Sort Algorithmus, aber wir wollten das halt en bisschen aufpeppen mit Ex. Hand. usw. wenn wir das eh schon in der Vorlesung hatten.
Bis dann