Eingabestream cin
Eingabe von numerischen Daten und Texten
Einlesen von Zeilen
Fehlerfälle
Beispiel und Übung
Für die Standard-Eingabe wird in C++ Programme vorzugsweise den Eingabestream cin verwendet. Die Standard-Eingabe erfolgt in der Regel über die Tastatur.
Genauso wie der Ausgabestream cout, ist auch der Eingabestream cin eine Instanz einer Streamklasse und liegt im Namensraum std. Wenn Sie diesen Stream einsetzen, müssen Sie die Datei iostream einbinden, die Sie auch schon für den Ausgabestream cout benötigt haben.
Die allgemeine Syntax für die formatierte Eingabe mittels cin lautet:
| std::cin >> var1 [ >> var2 [ >> var3 ...]]; |
Nach dem Eingabestream cin folgt der Operator >> und dann die Namen einzulesende Variable. Mehrere einzulesende Variablen werden einfach durch entsprechende Wiederholungen aneinander gehängt. Die Datentypen der Variablen können dabei beliebig 'gemischt' sein. Sie müssen dann bei der Eingabe 'nur' darauf achten, dass die eingelesenen Werte sich in den dazugehörigen Variablen abspeichern lassen. Was bei fehlerhaften Eingaben passiert, dass erfahren Sie gleich noch.
|
// Datei einbinden #include <iostream> using std::cin; // Variablen definieren short var1; long var2; // main() Funktion int main () { .... // 2 Daten einlesen cin >> var1 >> var2; .... } |
Bei der Eingabe von mehreren Daten werden die einzelnen Daten durch Leerzeichen voneinander getrennt eingegeben. Die Zuordnung Eingabe zur Variable erfolgt von links nach rechts, d.h. die erste Eingabe wird auch der ersten Variable zugewiesen (wenn kein Eingabefehler vorliegt).
|
char myArray[SIZE]; myArray ist der Name des Feldes und SIZE die Feldgröße. In einem so definierten Feld können maximal SIZE-1 Zeichen abgelegt werden. Die -1 rührt daher, dass C-Strings immer mit einer binären 0 abgeschlossen werden, und die muss schließlich auch im Feld abgespeichert werden. |
Standardmäßig werden alle numerischen Eingaben im Dezimalformat erwartet. Sie können jedoch mit den bekannten Manipulatoren dec, hex und oct eine andere Zahlenbasis für die Eingabe einstellen. (siehe nachfolgendes Beispiel). Die eingestellten Zahlenbasen für cout und cin arbeiten unabhängig voneinander.
Beim Einlesen von Texten müssen Sie Obacht geben. Da die Daten durch Leerzeichen getrennt werden, wird jedes einzelne Wort in einem eigenen char-Feld abgelegt, welches, wie bei C-Strings üblich, automatisch mit einer binären Null abgeschlossen wird. Wollen Sie einen Text der aus mehreren Wörtern besteht einlesen, so müssen Sie dies zeilenweise tun (siehe nächsten Abschnitt).
|
// Einlesen eines Hex-Wertes short var; cin >> hex >> var; // Einlesen eines Oktal-Wertes short var; cin >> oct >> var; // Einlesen zweier Wörter (mit je max. 9 Buchstaben!) char array1[10], array2[10]; cin >> array1 >> array2; |
|
|
Da beim Eingabestream cin die einzelnen Eingaben durch Leerzeichen voneinander getrennt werden, können Eingaben die selbst Leerzeichen enthalten nicht direkt eingelesen werden. Soll eine komplette Zeile eingelesen werden, so kann hierfür die cin-Memberfunktion getline(...) verwendet werden. getline(...) besitzt prinzipiell folgende Deklaration:
|
istream& getline (char *pBuffer, int noOfChars); |
getline(...) erhält im ersten Parameter die Adresse des char-Feldes übergeben, in dem die Eingabe abgelegt werden soll. Der zweite Parameter definiert die maximale Anzahl der einzulesenden Zeichen plus 1. Wenn Sie z.B. maximal 10 Zeichen einlesen wollen, so müssen Sie hier den Wert 11 übergeben (und selbstverständlich auch das char-Feld mit mindestens 11 Elementen definieren!). Der Grund für dieses Verhalten ist, dass getline(...) die Eingabe ebenfalls als C-String ablegt, und der wird bekanntermaßen mit einer binären 0 abgeschlossen (was man nicht oft genug wiederholen kann!).
Und zu getline(...) noch ein Beispiel. Zunächst wird ein char-Feld mit der Größe SIZE (gleich 81) definiert, in das eine komplette Zeile eingelesen werden soll. Damit können Sie SIZE-1 Zeichen einlesen, die dann als String im char-Feld abgelegt werden. Werden mehr als SIZE-1 Zeichen eingegeben, so werden SIZE Zeichen im char-Feld abgelegt. Die restlichen eingegebenen Zeichen verbleiben zunächst im Eingabepuffer. Da aber SIZE Zeichen übernommen wurden, fehlt jetzt natürlich die abschließende binäre 0, die ja für den Abschluss eines Strings erforderlich ist. Diese binäre 0 wird im Beispiel zur Sicherheit immer als letzte Zeichen im char-Feld eingetragen, damit der String auf jeden Fall abgeschlossen ist. Anschließend wird die restliche Eingabe im Eingabepuffer mittels cin.ignore(...) übersprungen. Zum Schluss wird das char-Feld dann mittels cout zur Kontrolle ausgegeben.
|
#include <iostream> #include <limits> using namespace std; // Konstante für Feldgrösse definieren const int SIZE = 81; // main() Funktion int main () { // Feld zur Aufnahme der Eingabe definieren char array[SIZE]; // Hinweis ausgeben cout << "Bitte einen Text eingeben: "; // Zeile einlesen, aber max. SIZE Zeichen cin.getline(array, SIZE); // Zur Sicherheit 0 anfuegen array[SIZE-1] = 0; // Restliche Eingabe verwerfen cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Eingabe wieder ausgeben cout << "Eingabe war: " << array << endl; } |
|
Bitte einen Text eingeben: Ein Text mit
Leerzeichen! |
Beachten Sie beim Einlesen mittels getline(...), dass alle Eingaben als ASCII-Zeichen im char-Feld abgelegt werden. Wenn Sie also
12 2<RETURN>
eingeben, so liegen die 'Werte' als String "12 2" vor. Wie Sie diese 'String-Werte' in numerische Werte konvertieren können, das erfahren Sie noch.
|
|
|
Sehen Sie sich einmal das nachfolgende Beispiel an. Dort wird zunächst ein Text (formatiert) in das Feld array eingelesen. Anschließend soll nun eine komplette Zeile (unformatiert) eingelesen werden. Wenn Sie dieses Code-Stückchen laufen lassen würden, so würde das unformatierte Einlesen der Zeile fehlschlagen!
Was passiert hier? Überlegen Sie sich einmal, welche Tasten Sie bei der ersten, formatierten Eingabe gedrückt haben. Nun? Die zuletzt gedrückte Taste war natürlich die <RETURN>-Taste, d.h. im Eingabepuffer liegt der eingegebene Text und das abschließende RETURN. Bei der formatierten Eingabe wird nun nur der Text ohne das RETURN aus dem Eingabepuffer geholt, d.h. das RETURN bleibt noch im Eingabepuffer liegen. Wird dann unformatiert mit getline(...) eingelesen, so findet es zunächst das RETURN und damit ist für getline(...) die Sache erledigt! Deshalb gilt: verwenden Sie in einem Programm sowohl die formatierte wie auch und unformatierte Eingabe, leeren Sie vor einen Wechsel stets den Eingabepuffer mit cin.ignore(...), so wie weiter oben angegeben. |
Soll mittels cin ein numerischer Wert eingelesen werden und es wird stattdessen ein nicht-numerischer Ausdruck eingegeben, so behält die einzulesende Variable ihren ursprünglichen Wert. Die Eingabe wird dann der nächsten cin Anweisung 'zugewiesen', die alphanumerische Eingaben verarbeitet (siehe erste Eingabe im folgenden Beispiel). Diesen Fehlerfall können Sie abfangen, indem Sie nach dem Einlesen die Memberfunktion fail() aufrufen. Liefert die Memberfunktion true zurück, so war die Eingabe fehlerhaft. Beachten Sie aber, dass Sie danach unbedingt den Fehlerstatus des Eingabestreams cin mittels clear() löschen müssen und dass die Eingabe noch im Eingabepuffer steht!
Besteht die Eingabe eines numerischen Wertes am Anfang aus numerischen Zeichen gefolgt von nicht-numerischen Zeichen, so erhält die einzulesende Variable den numerischen Teil der Eingabe zugewiesen. Der Rest der Eingabe wird dann wiederum an die nächste cin Anweisung weitergeleitet die alphanumerische Eingaben verarbeitet (siehe zweite Eingabe im Beispiel). Unglücklicherweise liefert die Memberfunktion fail() hier false zurück, da ja die Eingabe (wenigstens teilweise) erfolgreich war.
|
short var; cin >> var; // Wenn fail() true zurückgibt if (cin.fail()) { // Fehler löschen und Eingabe ueberspringen cin.clear(); cin.ignore(std::numeric_limits<int>::max(),'\n'); } |
|
Eingabe : MaxMaier Eingabe : 12MaxMaier |
Wollen Sie sicher sein, dass nach jeder Eingabe der Eingabepuffer vollständig leer ist, so müssen Sie die im Eingabepuffer noch befindlichen Zeichen wieder mittels der Memberfunktion ignore(...) verwerfen.
|
|
Dieses Programm löst ein Gleichungssystem mit zwei
Unbekannten: |
|
// Beispiel zu cin // Zuerst Dateien iostream und iomanip einbinden #include <iostream> #include <iomanip> using std::cout; using std::cin; using std::endl; // Variablen für 1. Gleichung definieren double a1, b1, c1; // Variablen für 2. Gleichung definieren double a2, b2, c2; // Normierte Koeffizienten double b1Norm, c1Norm; double b2Norm, c2Norm; // Lösung der Gleichung double x, y; // main() Funktion int main () { // Hinweis auf Programmfunktion ausgeben cout << "Dieses Programm löst ein Gleichungssystem mit zwei Unbekannten:\n" << "\tA1x + B1y + C1 = 0\n\tA2x + B2y + C2 = 0\n" << "Alle Koeffizienten müssen ungleich 0 sein!\n"; cout << "Bitte Koeffizienten der Gleichungen als Gleitkommazahlen!\n" << "(A1 B1 C1)? "; // Koeffizienten der 1. Gleichung einlesen cin >> a1 >> b1 >> c1; cout << "(A2 B2 C2)? "; // Koeffizienten der 2. Gleichung einlesen cin >> a2 >> b2 >> c2; // Koeffizienten normieren und Gleichung nach x auflösen // x = -B1Ny - C1N // x = -B2Ny - C2N b1Norm = -b1 / a1; c1Norm = -c1 / a1; b2Norm = -b2 / a2; c2Norm = -c2 / a2; // Durch Gleichsetzen der Gleichungen nun Y ausrechnen // -B1Ny - C1N = -B2N - C2N // y = (C2N-C1N) / (B1N - B2N) y = (c2Norm-c1Norm)/(b1Norm-b2Norm); // X nun ausrechnen durch einsetzen des Y-Wertes in 1. Gleichung x = (-b1*y - c1)/a1; // Und Ergebnis ausgeben cout << "Ergebnis: X = " << x << ", Y = " << y << endl; } |
Und jetzt mal etwas aus dem alltäglichen Leben.
Sie sollen in der Übung den Steueranteil und den Nettobetrag Ihres Einkaufs ausrechnen. Dazu werden der an der Kasse bezahlte Betrag und der darin enthaltene Steuersatz in % eingegeben. Das Programm soll dann berechnen, wie viel Steuer im gezahlten Betrag enthalten ist und wie viel Sie ohne Steuer hätten zahlen müssen.
Hinweis: Bei einem angenommenen Steuersatz von 7% zahlen Sie 107% an der Kasse, nämlich 100% für Ihre Ware und 7% für das Finanzamt.
Die berechneten Beträge sind mit 2 Nachkommastellen auszugeben
|
Wie viel EUR haben Sie bezahlt?
233.45 |