Menu

Ein- und Ausgabe in C++: cin, cout, getline und Streams

Wie Konsolen-E/A in C++ funktioniert: Ausgabe mit cout, Einlesen mit cin, der klassische Zeilenumbruch-Bug bei getline nach cin und wie man sich erholt, wenn die Eingabe fehlschlägt.

Diese Seite enthält ausführbare Editoren - bearbeiten, ausführen und Ausgabe sofort sehen.

Wie C++ mit der Konsole spricht

C++ erledigt Konsolen-E/A über Streams aus dem Header <iostream>. Du schreibst mit cout (Zeichenausgabe) nach außen und liest mit cin (Zeicheneingabe) vom Benutzer. Sie verwenden zwei Operatoren, die du schon als Bit-Verschiebungen gesehen hast, hier mit neuem Zweck:

  • << ist der Einfüge-Operator: Er schickt Daten in cout hinein.
  • >> ist der Extraktions-Operator: Er zieht Daten aus cin in eine Variable.

Ein praktischer Merksatz für die Richtung: Die Pfeile zeigen in die Richtung, in die die Daten fließen. Jetzt, da du Text in Strings halten kannst, bewegen wir diesen Text in dein Programm hinein und wieder heraus.

Ausgeben mit cout

cout schickt alles, was du einfügst, an die Standardausgabe. Du kannst mehrere << in einer Anweisung verketten und dabei Text, Zahlen und Variablen frei mischen.

Jedes << hängt an dieselbe Zeile an, bis du einen Zeilenumbruch einfügst. Dafür gibt es zwei Wege: '\n' fügt ein Zeilenumbruch-Zeichen ein, während endl einen Zeilenumbruch einfügt und den Puffer auf den Bildschirm leert. Das Leeren hat echte Kosten, also bevorzuge in einer Schleife, die Tausende Zeilen ausgibt, '\n' – der Stream leert sich bei Bedarf von selbst (und immer beim Programmende).

// In Ordnung für eine einmalige Meldung:
cout << "Done" << endl;

// In einer heißen Schleife lieber so - kein erzwungenes Leeren pro Iteration:
for (int i = 0; i < 1000000; ++i)
    cout << i << '\n';

Einlesen mit cin und >>

cin >> variable liest ein durch Leerzeichen getrenntes Token und wandelt es in den Typ der Variablen um. Es überspringt führende Leerzeichen oder Zeilenumbrüche und stoppt dann beim nächsten Leerzeichen.

Weil >> beim Leerzeichen stoppt, eignet es sich hervorragend für einzelne Zahlen und einzelne Wörter, aber gar nicht für einen ganzen Satz: cin >> word bei der Eingabe hello world liest nur hello und lässt world für die nächste Leseoperation im Puffer.

Eine ganze Zeile mit getline einlesen

Um eine ganze Zeile – samt Leerzeichen – zu erfassen, nutze getline(cin, line), das alles bis zur Enter-Taste in einen std::string einliest.

Das ist das richtige Werkzeug, wann immer die Eingabe Leerzeichen enthalten kann – Namen, Adressen, Sätze. Es gibt nur eine Falle, die in dem Moment auf dich wartet, in dem du getline mit >> mischst.

Die Zeilenumbruch-Falle bei cin + getline

Das ist der mit Abstand häufigste E/A-Bug in C++. Wenn du cin >> n machst, liest die Extraktion die Zahl, lässt aber den Zeilenumbruch (die Enter-Taste, die du gedrückt hast) im Eingabepuffer liegen. Das nächste getline sieht diesen übrig gebliebenen Zeilenumbruch sofort, behandelt die Zeile als bereits abgeschlossen und gibt dir einen leeren String – ohne jemals auf Eingabe zu warten.

int age;
string city;

cin >> age;            // du tippst 30 und drückst Enter; '\n' bleibt im Puffer
getline(cin, city);    // liest den übrigen '\n' -> city ist "" (leer!)

Die Lösung besteht darin, diesen übrig gebliebenen Zeilenumbruch mit cin.ignore nach dem >> und vor dem getline zu verwerfen:

cin.ignore(numeric_limits<streamsize>::max(), '\n') überspringt Zeichen, bis es einen Zeilenumbruch verschluckt hat (oder das Eingabeende erreicht). Das ist die robuste Variante – das kürzere cin.ignore() verwirft nur ein einziges Zeichen, was kaputtgeht, wenn der Benutzer nach der Zahl zusätzliche Leerzeichen getippt hat. Greife aus Gewohnheit zur vollständigen Form.

Wenn die Eingabe fehlschlägt

Wenn der Benutzer Buchstaben tippt, wo du eine Zahl erwartet hast, schlägt die Extraktion fehl: cin geht in einen Fehlerzustand über und die Zielvariable bleibt unverändert (seit C++11 auf 0 gesetzt). Schlimmer noch: Sobald cin im Fehlerzustand ist, wird auch jede spätere Leseoperation stillschweigend übersprungen, sodass du in einer Endlosschleife landen kannst.

Die Erholung hat immer zwei Schritte: cin.clear() setzt die Fehler-Flags zurück, sodass der Stream wieder nutzbar ist, und cin.ignore(...) wirft die störenden Zeichen weg, die noch im Puffer feststecken. Lässt du das ignore weg, bleibt die fehlerhafte Eingabe liegen, also schlägt das nächste >> erneut fehl – die klassische Endlosschleife. cin >> n direkt in der Bedingung zu prüfen funktioniert, weil sich der Stream im Fehlerzustand in false umwandelt.

Häufige Fehler, die du vermeiden solltest

  • cin >> s für einen Satz verwenden. Es stoppt beim ersten Leerzeichen. Nutze getline für alles mit Leerzeichen.
  • cin.ignore zwischen >> und getline vergessen. Der übrig gebliebene Zeilenumbruch gibt dir eine leere Zeile. Leere zuerst den Puffer.
  • Überall zu endl greifen. Jedes davon erzwingt ein Leeren. Nimm standardmäßig '\n' und spare dir endl für Fälle auf, in denen die Ausgabe wirklich jetzt erscheinen muss.
  • Ein fehlgeschlagenes cin ignorieren. Buchstaben in einer numerischen Leseoperation machen cin kaputt; mach immer clear() und dann ignore(), bevor du erneut liest.

Weiter: String-Streams

Konsolen-E/A und String-Verarbeitung treffen sich in String-Streams. Ein stringstream gibt dir dieselben Operatoren << und >>, aber auf einen String im Speicher statt auf die Konsole gerichtet – perfekt, um eine Zeile in Zahlen zu zerlegen, formatierten Text aufzubauen und zwischen Strings und anderen Typen umzuwandeln, ohne jemals die Tastatur zu berühren.

Häufig gestellte Fragen

Warum überspringt getline die Eingabe direkt nach der Verwendung von cin in C++?

cin >> x liest die Zahl, lässt aber den Zeilenumbruch, den du gedrückt hast, im Puffer liegen. Das nächste getline liest bis zu diesem übrig gebliebenen Zeilenumbruch und gibt sofort einen leeren String zurück. Räume ihn zuerst mit cin.ignore(numeric_limits<streamsize>::max(), '\n'); nach dem >> und vor dem getline weg.

Was ist der Unterschied zwischen endl und \n in C++?

Beide beenden die Zeile, aber endl leert zusätzlich (flush) den Ausgabepuffer auf den Bildschirm, während '\n' nur einen Zeilenumbruch einfügt. Das Leeren hat einen Preis: In einer engen Schleife bevorzuge '\n' und lass den Stream von selbst leeren. Nutze endl nur, wenn du wirklich willst, dass die Ausgabe genau jetzt erscheint.

Wie lese ich in C++ eine ganze Textzeile einschließlich Leerzeichen ein?

Nutze getline(cin, line), nicht cin >> line. Der Operator >> stoppt beim ersten Leerzeichen, schnappt sich also nur ein Wort. getline liest alles bis zur Enter-Taste in einen std::string ein, Leerzeichen inklusive.

Coddy programming languages illustration

Lerne mit Coddy zu programmieren

LOS GEHT'S