(gelöst) Benutzereingabe "1" OK "1 a" nichtOK!
-
b1419589 schrieb:
Ich danke euch vielmals für eure Hilfe.
@Swordfish, deine Lösung macht genau das, was ich haben möchte, (Dass die Eingabe von "Leerzeichen" + 1 immer noch als 1 akzeptiert wird, spielt keine Rolle.)
nämlich eine Funktion, mit der eine Benutzereingabe nur von 1,2,3 oder 4 in einer Schleife akzeptiert wird und mit der Eingabe von 4 das Programm beendet wird.
Perfekt! Aber ich verstehe es nicht! Ein paar Kommentare wären für mich als Anfänger sehr hilfreich, womit ich in aller Bescheidenheit keine falsche Erwartung zeigen möchte.#include <cctype> // std::isspace() #include <limits> // std::numeric_limits<>::max() #include <iomanip> // std::noskipws() #include <iostream> bool only_whitespace( std::istream & is ) // true, wenn nur white-space Zeichen in is sind. { std::istream::int_type ch = 0; // solange das naechste Zeichen in is while( ch != '\n' && ch != EOF // kein Newline ist und auch das Streamende nicht erreicht ist && std::isspace( ch = is.peek() ) // und ein Leerzeichen, Tab, ... ist (peek() nur ansehen, nicht extrahieren) ) { is.get(); // extrahiere das Zeichen aus is (= werfe das angesehene Zeichen weg). } return ch == '\n' || ch == EOF; // ist die while()-Schleife wegen '\n' oder EOF abgebrochen? // wenn nicht, war es ein anderes Zeichen das nicht isspace() ist. } int main() { int choice; do { // solange while( std::cout << "Input: ", !( std::cin >> std::noskipws >> choice ) // der Extraktionsversuch eines Integers aus cin fehlschlaegt || !only_whitespace( std::cin ) // oder nach dem Extraktionsversuch noch weitere Zeichen auszer white-space in cin stehen || ( choice < 1 || 4 < choice ) // oder das gelesene choice nicht in 1...4 liegt ) { std::cerr << "Input error!\n\n"; // eine Fehlermeldung ausgeben std::cin.clear(); // Fehlerflags loeschen, falls der Extraktionsversuch fehlgeschlagen ist std::cin.ignore( // weitere Zeichen in cin ignorieren std::numeric_limits< std::streamsize >::max(), // Anzahl zu ignorierender Zeichen, vorsichtshalber die groesztmoegliche Anzahl annehmen '\n' // solange kein '\n' daherkommt ); } std::cout << choice << "\n\n"; // getroffene Auswahl ausgeben } while( choice != 4 ); }
-
b1419589 schrieb:
[...] (Dass die Eingabe von "Leerzeichen" + 1 immer noch als 1 akzeptiert wird, spielt keine Rolle.) [...]
Gefixt. Hatte im Original fälschlicherweise
std::skipwsstatt richtigstd::noskipws.
-
@Swordfish, dankeschön! Alles perfekt! Damit wurden alle meine Probleme gelöst und Fragen beantwortet.
-
#include <cctype> // std::isspace() #include <limits> // std::numeric_limits<>::max() #include <iomanip> // std::noskipws() #include <iostream> bool only_whitespace(std::istream & is) // true, wenn nur white-space Zeichen in is sind. { std::istream::int_type ch = 0; // solange das naechste Zeichen in is while (ch != '\n' && ch != EOF // kein Newline ist und auch das Streamende nicht erreicht ist && std::isspace(ch = is.peek()) // und ein Leerzeichen, Tab, ... ist (peek() nur ansehen, nicht extrahieren) ) { is.get(); // extrahiere das Zeichen aus is (= werfe das angesehene Zeichen weg). } return ch == '\n' || ch == EOF; // ist die while()-Schleife wegen '\n' oder EOF abgebrochen? // wenn nicht, war es ein anderes Zeichen das nicht isspace() ist. } int main() { int choice; for (choice = 0; std::cout << "Input: " && !(std::cin >> std::noskipws >> choice) || !only_whitespace(std::cin) || (choice < 1 || 4 < choice);choice++) { std::cerr << "Input error!\n\n"; // eine Fehlermeldung ausgeben std::cin.clear(); // Fehlerflags loeschen, falls der Extraktionsversuch fehlgeschlagen ist std::cin.ignore( // weitere Zeichen in cin ignorieren std::numeric_limits< std::streamsize >::max(), // Anzahl zu ignorierender Zeichen, vorsichtshalber die groesztmoegliche Anzahl annehmen '\n' // solange kein '\n' daherkommt ); } std::cout << choice << "\n\n"; // getroffene Auswahl ausgeben }
-
und? was bringt die Nachplapperei?
-
Die for-Schleife ist nicht richtig!!!
-
Wie wärs mit
std::string str; std::getline(std::cin, str); int choice = boost::lexical_cast<int>(str); // Wirft Exception wenn str nicht nach int konvertiert werden kann?
-
Es gibt an der for-Schleife nichts auszusetzen. Sie macht genau das, was Swordfish mit einer do-while-Schleife auch macht!
-
hustbaer schrieb:
Wie wärs mit
std::string str; std::getline(std::cin, str); int choice = boost::lexical_cast<int>(str); // Wirft Exception wenn str nicht nach int konvertiert werden kann?
Danke hustbaer, aber boost ist für mich jetzt nochmal eine neue Bibliothek. So lerne ich die Grundlagen nicht, wenn ich ständig auf eine Bibliothek ausweiche.
Mit Boost Lexical_cast ist die Konvertierung von string to z.B. int sicherlich einfacher oder besser. Danke für deine Antwort.
-
MarkusMundM schrieb:
#include <cctype> // std::isspace() #include <limits> // std::numeric_limits<>::max() #include <iomanip> // std::noskipws() #include <iostream> bool only_whitespace(std::istream & is) // true, wenn nur white-space Zeichen in is sind. { std::istream::int_type ch = 0; // solange das naechste Zeichen in is while (ch != '\n' && ch != EOF // kein Newline ist und auch das Streamende nicht erreicht ist && std::isspace(ch = is.peek()) // und ein Leerzeichen, Tab, ... ist (peek() nur ansehen, nicht extrahieren) ) { is.get(); // extrahiere das Zeichen aus is (= werfe das angesehene Zeichen weg). } return ch == '\n' || ch == EOF; // ist die while()-Schleife wegen '\n' oder EOF abgebrochen? // wenn nicht, war es ein anderes Zeichen das nicht isspace() ist. } int main() { int choice; for (choice = 0; std::cout << "Input: " && !(std::cin >> std::noskipws >> choice) || !only_whitespace(std::cin) || (choice < 1 || 4 < choice);choice++) { std::cerr << "Input error!\n\n"; // eine Fehlermeldung ausgeben std::cin.clear(); // Fehlerflags loeschen, falls der Extraktionsversuch fehlgeschlagen ist std::cin.ignore( // weitere Zeichen in cin ignorieren std::numeric_limits< std::streamsize >::max(), // Anzahl zu ignorierender Zeichen, vorsichtshalber die groesztmoegliche Anzahl annehmen '\n' // solange kein '\n' daherkommt ); } std::cout << choice << "\n\n"; // getroffene Auswahl ausgeben }@MarkusMundM, nein diese Schleife macht nicht dasselbe, was Swordfish bereits mit einer do-while Schleife gelöst hat.
-
OK.
Aber du kannst ja mal reingucken wie Boost es macht
IIRC verwenden die nen (etwas modifizierten und auf etwas bessere Geschwindigkeit modifizierten) Stringstream.
Da wird dann erstmal der Ausgangswert "reingeschiftet" (stream insertion, "<<" halt).
Und dann wird versucht das "rauszushiften" (stream extraction, ">>") was man haben möchte.Und dann wird geprüft
a) Ob der Stream danach noch "good" ist und
b) Ob der Stream danach leer istWenn beides zutrifft war die Konvertierung erfolgreich.
Finde ich weitaus eleganter als direkt in cin zu gucken ob auch wirklich ein Newline das nächste Zeichen ist.