Eingabeabfrage mit cin.get
-
Hallo
cin und sscanf sind auch nicht dazu gedacht, zusammenzuarbeiten. Benutze entweder C++ oder C.
bis bald
akari
-
hm.. mche sowas glaube ich immer mit
fflush(stdin);funktioniert bei mir eigentlich immer
-
@Ozzy: Warum holtst du dir deine drei Zahlen nicht direkt von der Eingabe? (das geht mit
cin>>k>>m>>n;wesentlich sicherer als mit sscanf())@Turmfalke: fflush(stdin) ist erstens Müll (undefinied behaviour - der MSVC macht zufällig das, was du erwartest) und zweitens in C++ fehl am Platz. Da sollte man lieber sync() (ist das überhaupt im Standard?) oder ignore() verwenden, um den Eingabepuffer aufzuräumen.
-
CStoll schrieb:
@Da sollte man lieber sync() (ist das überhaupt im Standard?) oder ignore() verwenden, um den Eingabepuffer aufzuräumen.
snyc() ist zwar Standard, hat aber nichts mit leeren des Eingabepuffers zu tun. sync() synchronisiert den internen Puffer mit der externen Streamrepräsentation. Was das genau heißt ist im Standard nur für Ausgabeströme spezifiziert: der Puffer wird, analog zu overflow, rausgeschrieben.
Für Eingabeströme passiert typischerweise nichts. Bei Dateien *könnte* ein Abgleich zwischen dem Dateiinhalt (der sich ja geändert haben könnte) und dem internen Puffer stattfinden (mir ist allerdings keine Implementation bekannt, die das tut).
Zum "flushen" von Eingabeströmen ist sync() allerdings ungeeignet, da nichts im Standard darauf hindeutet, dass dies eine intendierte Semantik von sync ist.
Hierfür ist ignore besser geeignet. Wobei die gern verwendete Kombination mit in_avail() auch nicht sehr sinnvoll ist, da in_avail() nicht die Anzahl der Zeichen im Input-Buffer liefert, sondern lediglich wieviele Zeichen *mindestens* noch aus dem Stream gelesen werden können. Da sich dies für viele Ströme aber nicht so ohne weiteres sagen lässt, liefern viele Implementationen hier schlicht immer 0 zurück.
Soweit die Theorie: in der Praxis funktioniert normalerweise entweder cin.sync() oder aber cin.ignore(cin.in_avail());
-
HumeSikkins schrieb:
CStoll schrieb:
@Da sollte man lieber sync() (ist das überhaupt im Standard?) oder ignore() verwenden, um den Eingabepuffer aufzuräumen.
snyc() ist zwar Standard, hat aber nichts mit leeren des Eingabepuffers zu tun. sync() synchronisiert den internen Puffer mit der externen Streamrepräsentation. Was das genau heißt ist im Standard nur für Ausgabeströme spezifiziert: der Puffer wird, analog zu overflow, rausgeschrieben.
OK, dann landet das wohl in der selben Kategorie wie das berühmt-berüchtigte "fflush(stdin);".
Hierfür ist ignore besser geeignet. Wobei die gern verwendete Kombination mit in_avail() auch nicht sehr sinnvoll ist, da in_avail() nicht die Anzahl der Zeichen im Input-Buffer liefert, sondern lediglich wieviele Zeichen *mindestens* noch aus dem Stream gelesen werden können. Da sich dies für viele Ströme aber nicht so ohne weiteres sagen lässt, liefern viele Implementationen hier schlicht immer 0 zurück.
Und deshalb sollte man auf der sicheren Seite sein, wenn man einen ..hmm.. etwas größeren Wert mitgibt (
cin.ignore(numeric_limits<size_t>::max());sollte reichen).
-
CStoll schrieb:
OK, dann landet das wohl in der selben Kategorie wie das berühmt-berüchtigte "fflush(stdin);".
Besser nicht. fflush(stdin) ist illegal, da fflush nur auf Ausgabeströmen aufgerufen werden darf. Alles andere führt direkt zu undefiniertem Verhalten. So steht es im C Standard. cin.sync() hingegen ist ein völlig legaler Aufruf, der vom Standard keinesfalls verboten wird. Der Standard schreibt nur nicht vor, was *genau* dieser Aufruf bewirkt. Er erlaubt z.B. die gängigste Variante: die Operation bewirkt nichts und liefert erfolg. Was der Standard hingegen nicht erlaubt ist, dass auf einmal Elefanten aus deinen Ohren geflogen kommen. Das ist beim Aufruf von von fflush(stdin) zwar bisher auch nicht vorgekommen, könnte aber durchaus passieren.
CStoll schrieb:
Und deshalb sollte man auf der sicheren Seite sein, wenn man einen ..hmm.. etwas größeren Wert mitgibt (
cin.ignore(numeric_limits<size_t>::max());sollte reichen).Das ist in der Tat eine gute Variante.
-
äm...das habe ich jetzt nicht wirklich verstanden ... ich benutze eigentlich immer fflush(stdin) und es funktioniert einwandfrei und macht was ich von ihm verlange, was spricht dann dagegen ? es geht doch eigentlich darum das das ergebnis richtig ist oder ? der weg ist ja eigentlich irrelevant...
Oder kann mir mal jemand erklären wann fflush(stdin) nicht geht ?
-
Turmfalke schrieb:
äm...das habe ich jetzt nicht wirklich verstanden ... ich benutze eigentlich immer fflush(stdin) und es funktioniert einwandfrei
Es kann nicht einwandfrei funktionieren, da nicht definiert ist, wie es überhaupt funktioniert. Es kann auf dem Compiler in der Version die du verwendest genau das tun, was du gerne möchtest. Es kann auf jedem anderen Compiler in jeder anderen Version etwas völlig anderes tun. Und genau das ist schlecht an fflush(stdin). Du machst die unnötig abhängig von einem konkreten Compiler in einer konkreten Version. Du vertraust auf ein Ergebnis, dass dir niemand garantiert.
es geht doch eigentlich darum das das ergebnis richtig ist oder ?
Darum geht es und genau das kannst du mit fflush(stdin) nicht portabel erreichen. Noch einmal: der Standard definiert kein Ergebnis für fflush(stdin). Er sagt explizit, dass das Ergebnis undefiniert ist. Jedes Ergebnis ist damit ein "richtiges". Wenn beim Aufruf von fflush(stdin) dein Programm abstürzt und dabei deine gesamte digitale Briefmarkensammlung zerstört wird, dann ist das aus Sicht des Standards ein "richtiges" Ergebnis. Aus deiner Sicht aber wahrscheinlich nicht.
der weg ist ja eigentlich irrelevant...
Aber nicht, wenn du an einem bestimmten Ziel ankommen willst.
-
ok das bedeutet dann wohl das ich stat
fflush(stdin);(cin.ignore(numeric_limits<size_t>::max());benutzen soll ? hm.. das muss ich mir noch etwas kürzer stutzen weil bissher mache ich das immer wie im Buch erklärt vor befehlen wie getchar ();
ansonsten wirkt es genauso ? komisch was in so Büchern lernt ...
-
Turmfalke schrieb:
ansonsten wirkt es genauso ?
Nein (und wenn doch, hast du Glück).
fflush(stdin);ist undefiniert (das heißt, der Compiler darf dort machen, was er will) - allerdings haben einige Compiler-Hersteller entschieden, daß sie es so implementieren, daß es den Eingabepuffer leer räumt.cin.ignore(n);ist Teil des Standards - und liest und verwirft solange Eingabezeichen, bis es entweder n Zeichen gelesen hat oder auf ein '\n' stößt (numeric_limits<size_t>::max() ist der größtmögliche Wert, den du dort übergeben kannst). Die beste Entsprechung in C dazu wärewhile(fgetc(stdin)!='\n');.PS: Falls dir der Bandwurm zu viel Schreibarbeit macht, kannst du ihn in eine Funktion auslagern:
void lignore(istream& is,char delim='\n') { is.ignore(numeric_limits<size_t>::max(),delim); } ... lignore(cin); char input = cin.get(); ...