002
21.07.2011, 02:12 Uhr
0xdeadbeef
Gott (Operator)
|
Ich hab dafür vor langer Zeit mal eine Funktionstemplate zusammengeschustert, die das mit stringstream erledigt:
C++: |
#include <iostream> #include <sstream> #include <string>
template<typename result_t> result_t read_type_ref(result_t &dest, std::string const &prompt, std::istream &in = std::cin, std::ostream &out = std::cout) { std::istringstream parser; std::string line;
do { // Vorsicht, Porzellankiste und so. if(!in ) throw std::runtime_error("Eingabefehler"); if(!out) throw std::runtime_error("Ausgabefehler");
parser.clear();
out << prompt << std::flush;
std::getline(in, line);
parser.str(line); parser >> dest; } while(!parser);
return dest; }
template<typename result_t> result_t read_type(std::string const &prompt, std::istream &in = std::cin, std::ostream &out = std::cout) { result_t result; return read_type_ref(result, prompt, in, out); }
|
Zu benutzen beispielsweise als
C++: |
int x = read_type<int >("Bitte geben Sie eine Ganzzahl ein: "); double d = read_type<double>("Jetzt bitte eine Fließkommazahl: ");
|
...wobei der Prompt solange wiederholt wird, bis eine Zahl eingegeben wurde.
Dabei verhält std::istringstream sich genau wie andere Eingabeströme (std::cin ist ein solcher, und wenn du schon mit Dateien gearbeitet hast, std::ifstream auch), nur dass er seine Daten aus einem String bezieht.
Der Ansatz ist dann denkbar simpel: Ich hole erst eine ganze Zeile aus std::cin, stopfe die in den Stringstream und parse daraus. Das ganze wird so lange wiederholt, bis es hinhaut. Die zu erwartenden Fehler (d.h. falsche Eingaben) betreffen dann den Stringstream, und es bleiben auch keine Rückstände in std::cin, die einen später überraschen (beliebte Anfängerverwunderung ist etwa, dass std::cin.get() nicht anhält, wenn nach std::cin >> foo noch ein Zeilenumbruch in std::cin steckt). Unerwartete Fehler (dass der Programmierer einem Streams in die Hand drückt, die schon einen Fehlerstatus haben, dass an anderer Stelle der Strom geschlossen wird und andere Dinge, von denen man nicht erwartet, dass sie tatsächlich passieren) verursachen eine Exception; dafür sind die Dinger ja da.
Ich halte das in diesem Zusammenhang für eine sinnvolle Vorgehensweise, weil der Benutzer bei CLIs in der Regel erwartet, dass seine Eingabe zeilenweise verarbeitet wird und Performance hier keine Rolle spielt (Flaschenhals ist die Reaktionszeit des Anwenders). -- Einfachheit ist Voraussetzung für Zuverlässigkeit. -- Edsger Wybe Dijkstra Dieser Post wurde am 21.07.2011 um 02:25 Uhr von 0xdeadbeef editiert. |