Eingabepuffer leeren
-
Lichtlein schrieb:
streambuf * pbuf; pbuf = cin.rdbuf(); int size = pbuf->in_avail(); cin.ignor(size);Es verändert den Programmablauf leider irgendwie in keiner Weise.
-
Ad aCTa schrieb:
Ich verweise gern noch mal auf sync(). Alle anderen Lösungen sind Quatsch.
Mit
sync()funktioniert es aber auch nicht!
-->Test am Code
-
Ad aCTa schrieb:
> Wie schon gesagt, liegt dass daran, dass das einfach nicht vorgesehen ist.
Ich dachte, dafür gibt's
std::basic_istream<char, std::char_traits<char>>::sync().Sicher? Also zumindest bei mir funktioniert das damit nicht. Und die Beschreibung im Standard was sync() machen soll ist ziemlich unverständlich, jedoch würde ich es nicht so interpretieren, dass das geforderte Verhalten folgt.
Lichtlein schrieb:
Das kann man über den Stream Buffer machen.
streambuf * pbuf; pbuf = cin.rdbuf(); int size = pbuf->in_avail(); cin.ignor(size);Lichtlein
Leider liefert in_avail() nur die Mindestzahl der lieferbaren Zeichen. Bei den meisten Streamtypen ist dies immer 0
. Ansonsten würde es funktionieren.
-
#include <iostream> #include <string> void out_in_avail(std::ostream& os, std::streambuf* buf) { os << buf->in_avail() << std::endl; } int main() { std::string s1; std::cin >> s1; out_in_avail(std::cout, std::cin.rdbuf()); std::cin.sync(); out_in_avail(std::cout, std::cin.rdbuf()); }Liefert bei mir:
$ > Hallo $ > 1 <--------- Das Newline-Zeichen $ > 0Und genau das soll es auch tun.
-
Wenn sync() nicht das tut, was es eigentlich sollte (nämlich alle Zeichen im Eingabepuffer zu verwerfen und den Stream damit zu synchronisieren), kann man es auch mal mit diesem dreckigen Hack probieren:
#include <iostream> #include <string> void out_in_avail(std::ostream& os, std::streambuf* buf) { os << buf->in_avail() << std::endl; } void iflush(std::istream& ios) { std::ostream os(ios.rdbuf()); os.flush(); ios.rdbuf(os.rdbuf()); } int main() { std::string s1; std::cin >> s1; out_in_avail(std::cout, std::cin.rdbuf()); iflush(std::cin); out_in_avail(std::cout, std::cin.rdbuf()); std::cin.get(); }
-
Nope, liefern bei mir beide
Hallo 0 0und es wird am Ende beim get trotzdem nicht gewartet. Getestet unter einem Linux, sowohl mit dem neuesten GCC als auch mit dem neuesten Intel-Compiler.
Und wie ich das sehe, ist dieses Verhalten auch durch den recht lax formulierten Standard gedeckt. Vermutlich gibt es auch gute Gründe dafür warum der Standard so formuliert ist und warum die Compilerhersteller sich nicht die Mühe geben es trotzdem besser zu machen, aber das würde zu ziemlich viel Spekulationen über Dinge führen mit denen ich mich nicht wirklich gut auskenne (Mein Wilder Tipp: Es hat wahrscheinlich was mit dem IO-Modell von POSIX zu tun).
-
Tja, VS 2008 und 2010 machen das so. Aber beim 2. Beispiel sollte es eigentlich überall klappen. Es sei denn, die Definition von ostream::flush() ist auch so lax.
-
-
Das betrifft den Standard-Eingabestrom des Betriebssystems selbst (stdin) und hat nichts direkt mit den C++-Streams (std::istream) und Puffern zu tun. Als einziges hat man die Semantik des "Istream-Flushens" übernommen: dass es möglichst nicht gehen soll.
-
std::cin.sync();
-
Toll, dass du jetzt auch noch mal sync() erwähnt hast.

-
Meine damalige Lösung in meinem Beleg, die zumindest für mich funktionierte und den Buffer leerte:
// clear() setzt den Stream zurück // ignore(std::cin.rdbuf()->in_avail()) ignoriert alle im eingabepuffer enthaltenen zeichen (Trick von IIRC@www.c-plusplus.net) // ignore() ignoriert alle restlichen Zeichen (wird unter Linux benötigt) // Dadurch wird keine Endlosschleife ausgelöst wenn eine leere Eingabe getätigt wurde #ifdef __unix__ #define Menue_clearBuffer() std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); std::cin.ignore(); #else #ifdef _MSC_VER #define Menue_clearBuffer() std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); #else #define Menue_clearBuffer() std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); std::cin.ignore(); #endif #endif // cin/cout Helper funktionen um den Quellcode übersichtlicher zu gestalten #define Menue_newLine() std::cout << std::endl; #define Menue_readLine(label,variable) std::cout << label << ": "; std::cin >> variable; Menue_clearBuffer(); #define Menue_printLine(output) std::cout << output; Menue_newLine(); #define Menue_printTabbedLine(_left, _right, _space) std::cout << std::setw(_space) << std::left << _left << _right; Menue_newLine(); #define Menue_printSeperator(character) for(int __i = 0; __i < 79; __i++) std::cout << character; Menue_newLine() #define Menue_inputWait() Menue_newLine(); Menue_printLine("Naechste Eingabe erst in 2 Sekunden moeglich."); Sleep(2000); #define Menue_addCommandCall(command, function) if(input == command){ function; continue; }
-
Ein interessanter Beitrag zum Thema, den ich schon länger posten wollte, aber nicht gleich gefunden habe.
7H3 N4C3R (<a href= schrieb:
Link)">Der Wunsch den Tastaturcache [zu löschen] deutet auf falsches Verständnis der Eingabemechanismen hin.
In den meisten Fällen werden C-Streams mit C++-Streams vermischt oder formatierter mit unformatiertem Input.
Den "Tastatur-Cache" zu leeren wäre also i.d.R. eine symptomatische und keine ursächliche "Behebung". IMHO sind solche "Cache-Leerungs-Aktionen" ein echter Bug, der quasi nie am Input liegt, sondern am Programm selbst.
In einem Beispiel vorher wurde zum Beispiel das hier gebracht:
string s1, s2; cin >> s1; getline( cin, s2);operator >> ist formatierter Input und lässt das '\n' im Stream stehen, ignoriert es beim Lesen dafür aber auch.
getline dagegen ist unformatierter Input und macht nicht das, was man intuitiv erwarten würde, wenn vorher formatierter Input verwendet wurde.Regel 1: Mische niemals formatieren mit unformatiertem Input.
Regel 2: Falls du es doch tust, pass gut auf. Du musst immer wissen, welche Inputform vorher auf den Stream angewandt wurde, und vor allem wie sich diese verhält.
-
Source2702 schrieb:
Ist zwar nicht C++ aber vielleicht hilfts ja weiter:
fflush (stdin)
Zumindest unter Windows löscht man damit den Eingabepuffer.
http://msdn.microsoft.com/en-us/library/9yky46tz(VS.71).aspxIst wahrscheinlich die einzige Möglichkeit unter Windows. Danke