C++-Programmierung: Einfache Ein- und Ausgabe

Alte Seite
Diese Seite gehört zum alten Teil des Buches und wird nicht mehr gewartet. Die Inhalte sollen in das neue Buch einfließen: C++-Programmierung/ Inhaltsverzeichnis.
Eine aktuelle Seite zum gleichen Thema ist unter C++-Programmierung/ Einführung in C++/ Einfache Ein- und Ausgabe verfügbar.

Ein- und Ausgaberoutinen geben Ihnen die Möglichkeit, mit einem Programm zu interagieren. Dieses Kapitel beschäftigt sich mit der Eingabe über die Tastatur und der Ausgabe auf der Konsole in C++-typischer Form. Die C-Variante werden Sie später noch Kennenlernen.

Ströme oder Streams Bearbeiten

Mit Hilfe der neuen Möglichkeiten von C++ gegenüber C wurde die Art der Ein- und Ausgabe nicht nur grundlegend geändert, sondern auch deutlich vereinfacht. Das Prinzip der Ströme (englisch Streams) wurde in C++ versinnbildlicht. Es gibt ein Objekt, über das die auszugebenden Daten auf den Bildschirm "fließen", bzw. von der Tastatur zum Programm.

Ausgabe Bearbeiten

Ausgabeoperator Bearbeiten

Mit dem Ausgabeoperator << ist es möglich, beliebig viele Teile der Ausgabe aneinanderzuhängen, die sich auch auf mehrere Zeilen verteilen dürfen:

cout << "Hallo, " << "Ihr" 
     << " " << 2 
     << "!" << endl;

bewirkt die Ausgabe

Hallo, Ihr 2!

Ob die Ausgabeoperatoren am Ende der ersten oder am Anfang der zweiten Zeile stehen, ist dabei Geschmackssache.

Escape-Sequenzen Bearbeiten

Eine Escape-Sequenz wird durch einen Backslash ('\') eingeleitet.

\n Zeilenumbruch (newline)
\t horizontaler Tabulator (tab)
\v vertikaler Tabulator (vertical tab)
\b Zurücksetzen (backspace)
\r Wagenrücklauf (carriage return)
\f Seitenvorschub (formfeed)
\a Tonsignal (alert)
\', \", \\ zur Darstellung von ', ", \, da diese sonst andere Bedeutungen haben
\ooo das Zeichen mit der dreistelligen Oktalziffer ooo
\0 Spezialfall Nullzeichen, bezeichnet das Ende einer Zeichenkette (string)
\xhh[hhh...] das Zeichen mit der hexadezimalen Nummer hh (je 2 Hexadezimalziffern ein Zeichen, das Ende wird durch ein Zeichen gekennzeichnet, das keine Hexadezimalziffer ist)

Ausgabeströme Bearbeiten

Moderne Betriebssysteme stellen gewöhnlich zwei Ausgabeströme (Kanäle, output streams) bereit: stdout (kurz für standard out) und stderr (standard error). Beide werden normalerweise auf die Kommandozeile des Bildschirms gelenkt. stdout ist für normale Bildschirmausgaben wie Resultate oder Benutzerinformationen zuständig, während stderr Fehlermeldungen und Warnungen liefern soll. Weil zwei getrennte Kanäle vorhanden sind, können Resultate und Fehlermeldungen in verschiedene Dateien geschrieben werden. Diese Möglichkeit sinnvoll zu nutzen, liegt im Verantwortungsbereich des Programmierers, also in Ihrer Verantwortung. Wenn Sie in Ihrem Programm Fehler abfragen, und das sollten Sie tun, dann geben Sie entsprechende Meldungen auf dem Fehlerstream aus.

Die Standardausgabe wird über std::cout vorgenommen, die Fehlerausgabe über std::cerr. cout steht dabei für console out, ein Hinweis auf die gewöhnliche Verwendung dieser Ausgabe. Diese beiden und andere Objekte werden in der Bibliothek iostream (=in-out-stream) zur Verfügung gestellt.

Ein Minimalprogramm, das die Funktionsweise der Ausgabe zeigt, ist dieses erweiterte "Hallo-Welt-Programm":

#include <iostream>

using namespace std;

int main()
{
   cout << "Hallo, Du!" << endl;        //das ist eine Standard-Ausgabe
   cerr << "KRITISCHER FEHLER" << endl; //das ist eine Fehlermeldung
   return 0;
}

Nachdem das Programm Sie begrüßt hat, erblickt es Ihr Antlitz und erschrickt (auf Grund einer Verwechslung) dermaßen, dass es sofort einen kritischen Fehler auf dem Fehlerstream cerr ausgibt. Nun aber mal Scherz bei Seite, wie Sie die Umleitung eines Datenstroms bewerkstelligen, können Sie unter Linux-Shellprogrammierung beziehungsweise Dos/Windows-Batch-Programmierung nachlesen. Wenn Sie die Ausgabe in eine Datei umleiten, bekommen Sie in der Konsole nur noch die Fehlermeldung angezeigt, während in der Datei jene Daten die auf cout ausgegeben wurden stehen.

Die meisten Befehle sind Ihnen schon aus dem Kapitel Das erste Programm bekannt. Neu hinzugekommen ist die Zeile: using namespace std;. Damit wird festgelegt, dass wir den Namensraum std benutzen. Die gesamte Standardbibliothek von C++ benutzt diesen Namensraum, was jetzt aber nicht von Bedeutung sein soll. Für den Moment sollten Sie sich einfach merken, dass Sie cout, cerr, cin usw. ohne ein vorangestelltes std:: benutzen können, wenn Sie diese Zeile darüber verwendet haben. Was Namensräume sind und wie bzw. wieso man sie verwendet, werden Sie im Kapitel „Namensräume“ erfahren.

Ausgabe-Manipulatoren Bearbeiten

Manipulatoren können wie Text und Variablen auf einem Stream ausgegeben werden. Zwei Standard-Manipulatoren für Ausgabestreams haben Sie bereits kennengelernt: endl und flush.

endl fügt genau wie das Newline-Zeichen (\n) einen Zeilenumbruch ein. Allerdings hat er noch eine weitere Eigenschaft, er leert den Ausgabespeicher. Je nach Optimierung beim Kompilieren wird eine Ausgabe vielleicht nicht sofort auf den Bildschirm geschrieben, sondern in einem Puffer zwischengespeichert, um erst andere Programmteile abzuarbeiten und an späterer Stelle mehrere Ausgaben gesammelt auszugeben. Das kann unter Umständen Zeit sparen.

Der Manipulator flush leert ebenfalls den Puffer, so dass alle Ausgaben sofort erscheinen. Die folgenden 2 Zeilen haben also die gleiche Wirkung: sie fügen einen Zeilenumbruch ein und geben dann, den im Ausgabepuffer stehenden Text auf dem Bildschirm aus. Bei heutigen Rechnern werden Sie vermutlich keinen sichtbaren Unterschied bemerken, wenn Sie den Ausgabepuffer automatisch leeren lassen, aber der Vollständigkeit halber soll es hier stehen.

cout << "Hallo, ich bin ein Text!" << endl; 
cout << "Hallo, ich bin ein Text!\n" << flush;
cout << "Hallo, ich bin ein Text!\n"; // Puffer wird nicht geleert

Es gibt außer diesen Beiden noch eine ganze Reihe weiterer Manipulatoren, für einige davon muss zusätzlich die Headerdatei iomanip eingebunden werden. Die Manipulatoren stehen natürlich auch im Namespace std.

setw(5) Breite der Ausgabe, hier: 5 Zeichen
setfill('*') Platzfüllzeichen
left, right Ausrichtung
showpos, noshowpos Positives Vorzeichen ein- oder ausblenden (Minus wird immer ausgegeben)
internal Vorzeichen linksbündig, Werte rechtsbündig ausrichten
hex, oct, dec verschiedene Zahlensysteme
showbase, noshowbase Zahlensystem in der für C/C++ typischen Art anzeigen (oktal mit Präfix 0, hexadezimal mit Präfix 0x) oder nicht
uppercase, nouppercase Ausgabe in Großbuchstaben oder normal darstellen (beeinflusst nicht den Text innerhalb von Anführungszeichen)
scientific Ausgabe in wissenschaftlicher Darstellung
fixed Ausgabe als standard Kommazahl
boolalpha, noboolalpha boolescher Wert als Text (true,false) oder Zahl (0,1) ausgeben

Um dem Ausgabestrom einen Manipulator mitzuteilen, verwenden Sie immer den Ausgabeoperator <<.

#include <iostream>
#include <iomanip>

using namespace std;

int main()
{
  cout << setfill('*');
  cout << internal << showpos;
  cout << setw(4) << 7   << setw(4) << 6;
  cout << setw(4) << 5   << setw(4) << 23  << endl;
  cout << setw(4) << 120 << setw(4) << -12;
  cout << setw(4) << 11  << setw(4) << 2   << flush;
}

Dieser Code gibt folgende Ausgabe:
+**7+**6+**5+*23
+120-*12+*11+**2

Am besten spielt man mit den Manipulatoren ein bisschen herum, um sie besser kennen zu lernen.

Eingabe Bearbeiten

Für die Eingabe ist der Strom stdin (standard input) zuständig. Er fragt die Tastatur nach einer Eingabe ab und schreibt diese dann zum Beispiel in eine Variable.

Die Standardeingabe wird mit dem Objekt std::cin verwendet, cin steht für console input. cin ist ebenfalls aus der Bibliothek iostream.

Hier ein kleines Beispielprogramm:

#include <iostream>

using namespace std;

int main()
{
    int zahl;
    cout << "Bitte Zahl eingeben!" << endl;
    cin >> zahl;
    cout << "Danke. Sie haben " << zahl << " eingegeben" << endl;
    return 0;
}

Das Programm fragt eine Zahl (genauer: eine Integer-Variable) ab und gibt diese dann aus.