STDIN "sauber" flushen in C++
-
Guten Tag,
Da fflush(stdin) ja offenbar undefiniertes Verhalten verursacht,
wollte ich mal fragen wie man in C++ eigentlich "sauber" den
stdin buffer leert.cout << flush;
Funktioniert bei mir leider nicht.. (cin kehrt sofort zurück).
Die einzige funktionierende Lösung die ich so habe ist:
int c; //... while ((c = getchar()) != EOF && c != '\n');
Na gut das funktioniert zwar, sieht aber irgendwie unschön aus.
Gibts da nichts besseres?
-
Standard C++: Nein.
-
Die übliche Beschwörungsformel ist
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
-
seldon schrieb:
Die übliche Beschwörungsformel ist
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Funktioniert aber leider nicht.. cin kehrt sofort zurück.
-
#include <iostream> #include <limits> #include <string> int main() { int x; std::string s; std::cin >> x; std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::getline(std::cin, s); std::cout << x << s << std::endl; }
funktioniert bei mir problemlos. Allerdings: Wenn jemand etwas in x zu pressen versucht, was sich nicht als int parsen lässt (jetzt mal wild geraten, dass das dein Problem sein könnte), musst du den Fehlerstatus von std::cin aufheben, bevor du wieder daraus lesen kannst. Etwa
#include <iostream> #include <limits> #include <string> int main() { int x = 0; std::string s; std::cin >> x; std::cin.clear(); // <-- hier std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::getline(std::cin, s); std::cout << x << s << std::endl; }
-
seldon schrieb:
Die übliche Beschwörungsformel ist
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Wieso nicht einfach ?
cin.sync()
In Verbindung mit clear hat das bei mir noch nie versagt.
-
Ja, stimmt so funktioniert es.
Das einzige Problem ist jetzt noch dass ich danach das failbit überprüfe,
bzw. ich fordere so lange zur Eingabe einer Zahl auf, bis auch eine Zahl
eingegeben wurde. Wenn ich jetzt cin.clear() benutze funktioniert diese
Abfrage natürlich nicht mehr.Ich kann den buffer aber leider auch schlecht am Anfang leeren,
da dann keine Eingabe aller Optionen hintereinander nur durch Leerzeichen
getrennt möglich wäre.
-
@Dweb
std::cin.sync();
funktioniert bei mir nicht. Wahrscheinlich verlässt du dich dabei auf eine Windows-Spezialität (oder eine der Standardbibliothek, die du benutzt).
@usernameC++: Was die Fehlerbehandlung angeht, du kannst dir den Zustand ja merken, bevor du ihn löschst.
-
ich würde per std::getline in einen string einlesen, diesen in einen stringstream schreiben und daraus die daten extrahieren.
so umgehst du den ganzen mist.
-
line schrieb:
ich würde per std::getline in einen string einlesen, diesen in einen stringstream schreiben und daraus die daten extrahieren.
so umgehst du den ganzen mist.Ich wollte das gerade schreiben...
Meiner Meinung nach ist das die beste Lösung.
-
Die beste Lösung ist und bleibt: mische niemals formatierte und unformatierte Eingabe!
-
Da habt ihr alle recht. Ich benutze für Benutzereingaben von der Konsole das hier:
#ifndef INCLUDED_READ_TYPE_HH #define INCLUDED_READ_TYPE_HH #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 { 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); } #endif
benutzbar so:
int x = read_type<int>("Zahl eingeben: ");
...denn der übliche Anwendungsfall ist ja, noch mal nachzufragen, wenn der Benutzer sich vertippt hat. Und Performance sollte in diesem Zusammenhang nur äußerst selten von Interesse sein.