c++ getline() wartet nicht auf Eingaben von der Konsole, wenn es mehrmals aufgerufen wird
Lesezeit: 4 Minuten
Benutzer754852
Ich versuche, ein paar Benutzereingabeparameter von der Konsole zu bekommen, zwei Strings, zwei Ints und ein Double. Der relevante Code, den ich zu verwenden versuche, ist dieser:
Beim Ausführen des Programms wird der Code jedoch nicht bis zum zweiten Aufruf von getline() angehalten, anstatt auf die Eingabe des ersten inputString zu warten. Die Konsolenausgabe sieht also so aus:
Titel: Kategorie:
wobei der Cursor hinter der Kategorie erscheint. Wenn ich jetzt eintippe, springt das Programm zur Jahreseingabe und erlaubt mir nicht, mehr als eine Zeichenfolge einzugeben. Was passiert hier?
Kann nicht reproduzieren; Bitte poste echten, vollständigen Code. Ich wette, dein Problem liegt woanders. Mischen Sie auch keine formatierten Eingaben und getline().
– Kerrek SB
16. Oktober 2011 um 20:18 Uhr
@KerrekSB: Ich stimme zu, dass das Mischen ein Symptom für schlechten Stil ist, aber was ist der objektive Grund dafür, sie nicht zu mischen? Ich denke, es ist vollkommen richtig, sie zu mischen, wirklich.
– sehen
16. Oktober 2011 um 20:21 Uhr
@sehe: Das Problem ist, dass die formatierte Extraktion die Zeilenumbrüche nicht verbraucht, daher ist es sehr einfach, unerwartete Ergebnisse zu erhalten, wenn Sie dies tun getline() nachdem Sie dachten, dass Sie bereits die gesamte vorangegangene Zeile verarbeitet haben. Ich sage nicht, dass es unmöglich ist, aber es macht die Logik oft sehr schwer zu lesen und aufrechtzuerhalten.
– Kerrek SB
16. Oktober 2011 um 20:22 Uhr
Entschuldigung für den unvollständigen Code; Das Programm war lang. Ich denke jetzt, dass das Problem mit einer früheren Verwendung eines Cins zusammenhängt, um ein Int vor diesem Block zu erhalten.
– Benutzer754852
16. Oktober 2011 um 20:30 Uhr
Das Problem ist, dass Sie Aufrufe von getline() mit der Verwendung des Operators >> mischen.
Denken Sie daran, dass der Operator >> führende Leerzeichen ignoriert hat, sodass er korrekt über die Zeilengrenzen hinweg fortgesetzt wird. Hört jedoch auf zu lesen, nachdem die Eingabe erfolgreich abgerufen wurde, und verschluckt daher keine nachgestellten ‘\n’-Zeichen. Wenn Sie also ein getline() nach einem >> verwenden, erhalten Sie normalerweise das Falsche, es sei denn, Sie sind vorsichtig (um zuerst das nicht gelesene Zeichen ‘\n’ zu entfernen).
Der Trick besteht darin, nicht beide Arten von Eingaben zu verwenden. Wählen Sie das Passende aus und bleiben Sie dabei.
Wenn es sich nur um Zahlen handelt (oder um Objekte, die gut mit dem Operator >> spielen), verwenden Sie einfach den Operator >> (Notenzeichenfolge ist der einzige grundlegende Typ, der nicht symmetrisch zur Eingabe / Ausgabe ist (dh nicht gut spielt)).
Wenn die Eingabe Zeichenfolgen oder eine Kombination von Dingen enthält, für die getline() erforderlich ist, verwenden Sie nur getline() und analysieren Sie die Zahl aus der Zeichenfolge.
std::getline(std::cin, line);
std::stringstream linestream(line);
int value;
linestream >> value;
// Or if you have boost:
std::getline(std::cin, line);
int value = boost::lexical_cast<int>(line);
Sie müssen den Eingabepuffer leeren. Es kann damit gemacht werden cin.clear(); cin.sync();.
Seltsamerweise funktioniert es bei mir nicht mit der Kombination von denen. Es funktioniert nur mit std::cin.ignore().
– KeyC0de
7. August 2018 um 1:18 Uhr
Sie können verwenden
cin.ignore();
oder wie von @kernald erwähnt verwenden
cin.clear();
cin.sync();
vor der Verwendung von getline()
Farbod Ahmadian
Wenn der Benutzer ein Leerzeichen vor \n im vorherigen eingibt cin Vor getlinenur ignorieren selbst würde nicht ausreichen, also müssen Sie stattdessen diesen Code verwenden ignorieren() allein. Zum Beispiel 12345 \t \n wird nicht mehr funktionieren. Alle unverarbeiteten Zeichen müssen ignoriert werden.
Danke. Der Code funktioniert nur, wenn sowohl cin.clear() als auch cin.sync() verwendet werden.
– Benutzer754852
16. Oktober 2011 um 20:26 Uhr
Der einfachste Weg, den >>-Operator mit der getline()-Methode zu kombinieren, besteht darin, cin.ignore() vor jedem Aufruf von getline einzugeben, damit der Eingabepuffer von allen übrig gebliebenen Zeilenumbruchzeichen aus der vorherigen Eingabe gelöscht wird.
– Corey Zambonie
24. Juni 2015 um 16:46 Uhr
Funktioniert auch mit ws. Sie können verwenden getline(cin >> ws, inputString)), um die Leerzeichen oder die Zeilenumbrüche nach dem Lesen von Daten zu essen cin Befehl.
Unix-Ninja
Das Mischen von getline() mit Eingabeströmen ist im Allgemeinen eine schlechte Sache. Es ist theoretisch möglich, die schmutzigen Puffer, die durch die Verwendung von Streams übrig bleiben, manuell zu handhaben, aber es ist ein unnötiger Schmerz, der auf jeden Fall vermieden werden sollte.
Sie sind besser dran, eine Konsolenbibliothek zu verwenden, um Ihre Eingaben zu erfassen, auf diese Weise kann die Drecksarbeit für Sie abstrahiert werden.
Schau dir TinyCon an. Sie können einfach die statische Methode tinyConsole::getLine() anstelle Ihrer getline- und stream-Aufrufe verwenden, und Sie können sie so oft verwenden, wie Sie möchten.
Kann nicht reproduzieren; Bitte poste echten, vollständigen Code. Ich wette, dein Problem liegt woanders. Mischen Sie auch keine formatierten Eingaben und
getline()
.– Kerrek SB
16. Oktober 2011 um 20:18 Uhr
@KerrekSB: Ich stimme zu, dass das Mischen ein Symptom für schlechten Stil ist, aber was ist der objektive Grund dafür, sie nicht zu mischen? Ich denke, es ist vollkommen richtig, sie zu mischen, wirklich.
– sehen
16. Oktober 2011 um 20:21 Uhr
@sehe: Das Problem ist, dass die formatierte Extraktion die Zeilenumbrüche nicht verbraucht, daher ist es sehr einfach, unerwartete Ergebnisse zu erhalten, wenn Sie dies tun
getline()
nachdem Sie dachten, dass Sie bereits die gesamte vorangegangene Zeile verarbeitet haben. Ich sage nicht, dass es unmöglich ist, aber es macht die Logik oft sehr schwer zu lesen und aufrechtzuerhalten.– Kerrek SB
16. Oktober 2011 um 20:22 Uhr
Entschuldigung für den unvollständigen Code; Das Programm war lang. Ich denke jetzt, dass das Problem mit einer früheren Verwendung eines Cins zusammenhängt, um ein Int vor diesem Block zu erhalten.
– Benutzer754852
16. Oktober 2011 um 20:30 Uhr