kennen:include:iostream
no way to compare when less than two revisions
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
— | kennen:include:iostream [2017-03-24 10:11] (aktuell) – angelegt - Externe Bearbeitung 127.0.0.1 | ||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
+ | ====== < | ||
+ | > Die Verwendung von Flags zur Kontrolle eines Stromzustands | ||
+ | > ist jedenfalls eher eine Studie über Implementierungstechniken | ||
+ | > als über Schnittstellen-Design. | ||
+ | >> --- Bjarne Stroustrup [C++ 3rd edn, 21.4.1]</ | ||
+ | |||
+ | ===== Ein- und Ausgabeströme ===== | ||
+ | C++ bietet eine einheitliche Schnittstelle für [[# | ||
+ | und [[# | ||
+ | Dabei ist es gleichgültig, | ||
+ | oder wohin sie gehen ('' | ||
+ | [[fstream|Dateien]] oder [[sstream|Zeichenketten]]. | ||
+ | Die Kontrolle des [[# | ||
+ | [[# | ||
+ | bei wahlfreiem Zugriff und | ||
+ | [[# | ||
+ | werden einheitlich gehandhabt. | ||
+ | |||
+ | | | Eingabe | ||
+ | | allgemein | '' | ||
+ | | [[fstream|Dateien]] | ||
+ | | [[sstream|Zeichenketten]] | '' | ||
+ | Stromtypen für '' | ||
+ | |||
+ | Standardkanäle sind während der Programmlaufzeit mit Stromvariablen verbunden: | ||
+ | |||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | ==== Ausgabe ==== | ||
+ | Ausgabeströme '' | ||
+ | für die der Ausgabeoperator ''<<'' | ||
+ | [[..: | ||
+ | und formatieren deren Ausgabe als Folge von Zeichen. | ||
+ | Sie schreiben unformatierte Zeichen und Rohspeicher, | ||
+ | besonders für Binärdateien. | ||
+ | |||
+ | <code cpp> | ||
+ | void ausgabe(std:: | ||
+ | { | ||
+ | out << d; // formatierte Ausgabe | ||
+ | out.put(' | ||
+ | out.write( (char*) &d, sizeof(d) ); // Rohspeicher | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Eingabe ==== | ||
+ | Eingabeströme '' | ||
+ | in Werte jener Typen, für die der Eingabeoperator ''>>'' | ||
+ | [[..: | ||
+ | Führende Leerzeichen werden vom Eingabeoperator ''>>'' | ||
+ | Darüber hinaus lassen sich Einzelzeichen | ||
+ | und Rohspeicher, | ||
+ | |||
+ | <code cpp> | ||
+ | void eingabe(std:: | ||
+ | { | ||
+ | in >> d; // formatierte Eingabe | ||
+ | char c = in.get(); | ||
+ | in.get(c); | ||
+ | in.putback(c); | ||
+ | c = cin.peek(); | ||
+ | in.read( (char*) &d, sizeof(d) ); // Rohspeicher | ||
+ | } | ||
+ | </ | ||
+ | Das Einlesen von Zeichenketten verlangt besondere Sorgfalt. | ||
+ | Führende Leerzeichen werden übergangen, | ||
+ | das Einlesen endet beim ersten whitespace danach. | ||
+ | |||
+ | <code cpp> | ||
+ | char str[10]; // lang genug? | ||
+ | cin >> str; // kann und wird schief gehen | ||
+ | </ | ||
+ | Die Methoden '' | ||
+ | lesen auch führende whitespaces in die Zeichenkette ein, | ||
+ | begrenzen deren Länge auf maximal '' | ||
+ | und hängen stets eine ''' | ||
+ | Werden keine oder '' | ||
+ | des '' | ||
+ | wird das '' | ||
+ | |||
+ | <code cpp> | ||
+ | int zeichenketteneingabe(std:: | ||
+ | { | ||
+ | in.getline(s, | ||
+ | in.getline(s, | ||
+ | in.get(s, n, ende); | ||
+ | in.get(s, n); // geht schief, wenn schon bei ' | ||
+ | return in.gcount(); | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Stromzustand ==== | ||
+ | Der Stromzustand von Ein- und Ausgabeströmen ist erfragbar. | ||
+ | Er wird intern durch Flags '' | ||
+ | '' | ||
+ | aus der Basisklasse '' | ||
+ | Er kann mit '' | ||
+ | Während '' | ||
+ | setzt '' | ||
+ | |||
+ | <code cpp> | ||
+ | std:: | ||
+ | { | ||
+ | if (s) cout << "ok "; | ||
+ | if (s.good()) cout << "gut "; | ||
+ | if (s.eof() ) cout << "noch gut, aber am Dateiende "; | ||
+ | if (s.fail()) cout << " | ||
+ | "Strom noch verwendbar "; | ||
+ | if (s.bad() ) cout << "Strom total durcheinander "; | ||
+ | return s.rdstate(); | ||
+ | } | ||
+ | </ | ||
+ | Ein guter Stromzustand ist Voraussetzung, | ||
+ | für den Erfolg weiterer Aktionen mit dem Strom. | ||
+ | Bei nicht gutem Zustand haben Ein- und Ausgaben keine Wirkung. | ||
+ | |||
+ | In der Voreinstellung werfen die Ströme keine [[..: | ||
+ | bei Fehlern eine von [[.: | ||
+ | <code cpp> | ||
+ | void lass_es_krachen(std:: | ||
+ | { | ||
+ | std:: | ||
+ | try | ||
+ | { | ||
+ | in.exception(std:: | ||
+ | int x; | ||
+ | in >> x; // wirft Ausnahme, wenn keine Zahl im Strom ist | ||
+ | } | ||
+ | catch(std:: | ||
+ | { | ||
+ | std::cerr << " | ||
+ | } | ||
+ | in.exceptions(old); | ||
+ | } | ||
+ | </ | ||
+ | Ein- und Ausgabe selbstdefinierter Typen sollten so | ||
+ | [[..: | ||
+ | dass Variablen beim Einlesen nicht in einen undefinierten Zustand geraten können | ||
+ | und der einzulesende Wert erst dann geändert wird, wenn die Eingabe erfolgreich war. | ||
+ | |||
+ | <code cpp> | ||
+ | struct Punkt { int x, y; }; | ||
+ | |||
+ | std:: | ||
+ | { | ||
+ | int x, y; | ||
+ | if (is >> x >> y) | ||
+ | { | ||
+ | p.x = x; | ||
+ | p.y = y; | ||
+ | } | ||
+ | return is; | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | ==== Positionierung und wahlfreier Zugriff ==== | ||
+ | Ströme mit wahlfreiem Zugriff können die Lage der | ||
+ | aktuellen Lese- und Schreibposition im Strom erfragen und ändern. | ||
+ | Das ist vor allem für Binärdateien wichtig. | ||
+ | Die Position kann absolut oder | ||
+ | relativ zu Anfang '' | ||
+ | aktueller Position '' | ||
+ | oder Ende der Datei '' | ||
+ | |||
+ | <code cpp> | ||
+ | long filesize(std:: | ||
+ | { | ||
+ | long pos = is.tellg(); | ||
+ | is.seekg(0, std:: | ||
+ | |||
+ | long beg = is.tellg(); | ||
+ | is.seekg(0, std:: | ||
+ | |||
+ | long end = is.tellg(); | ||
+ | is.seekg(pos); | ||
+ | |||
+ | return end-beg; | ||
+ | } | ||
+ | </ | ||
+ | Bei Ausgabeströmen arbeiten '' | ||
+ | |||
+ | ==== Formatierung ==== | ||
+ | Das Verhalten der Eingabeströme und das Aussehen der Ausgaben (Formatierung) | ||
+ | wird durch Schalter (Flags) in der Basisklasse '' | ||
+ | |||
+ | <code cpp> | ||
+ | void formatierung(std:: | ||
+ | { | ||
+ | long alt = in.flags(); | ||
+ | long neu = ios_base:: | ||
+ | in.flags(alt | neu); // Schalter setzen | ||
+ | in.setf(neu); | ||
+ | in.unsetf(neu); | ||
+ | } | ||
+ | </ | ||
+ | Ganzzahlen sind in drei Positionssystemen (Basis, 8, 10, 16) darstellbar. | ||
+ | Programmierer verwechseln immer Weihnachten mit Helloween, weil OCT 31 = DEC 25: | ||
+ | |||
+ | <code cpp> | ||
+ | void ganzzahlbasis(std:: | ||
+ | { | ||
+ | int i = 25; | ||
+ | out.setf(std:: | ||
+ | out << i << ' '; | ||
+ | out.setf(std:: | ||
+ | out << i << ' '; | ||
+ | out.setf(std:: | ||
+ | out << i << endl; // Ausgabe: 19 31 25 | ||
+ | } | ||
+ | </ | ||
+ | Die Methode '' | ||
+ | '' | ||
+ | Dadurch werden alle Flags in '' | ||
+ | und '' | ||
+ | Dies verhindert, dass zwei einander widersprechende Schalter gleichzeitig gesetzt werden. | ||
+ | |||
+ | Folgende Schalterkonstanten aus '' | ||
+ | |||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Gleitkommazahlen zeigen den Dezimalpunkt und folgende Nullen nur, | ||
+ | wenn '' | ||
+ | |||
+ | Die Ausgabegenauigkeit kann mit der Methode '' | ||
+ | Mit der Standardeinstellung 0 werden bis zu 6 Stellen angezeigt. | ||
+ | Im '' | ||
+ | im '' | ||
+ | |||
+ | <code cpp> | ||
+ | void genauer(std:: | ||
+ | { | ||
+ | int n = out.precision(); | ||
+ | out.precision(2*n); | ||
+ | } | ||
+ | </ | ||
+ | Die Ausgabe eines Wertes nimmt immer mindestens soviele Zeichen ein, | ||
+ | wie zur exakten Ausgabe notwendig sind. | ||
+ | Die Ausgabeweite kann für die unmittelbar nächste Ausgabe vergrößert werden. | ||
+ | |||
+ | <code cpp> | ||
+ | out.width(8); | ||
+ | </ | ||
+ | Ist die befohlene Breite größer als notwendig, | ||
+ | wird die Ausgabezeichenfolge an den Rändern ausgerichtet | ||
+ | und mit Füllzeichen (Standardwert ''' | ||
+ | Nach jeder Ausgabe wird die Weite auf den Standardwert 0 zurückgesetzt, | ||
+ | alle anderen Einstellungen sind bleibend. | ||
+ | |||
+ | <code cpp> | ||
+ | -1.23___ | ||
+ | -___1.23 | ||
+ | ___-1.23 | ||
+ | </ | ||
+ | Das Füllzeichen lässt sich abfragen und ändern: | ||
+ | |||
+ | <code cpp> | ||
+ | char c = out.fill(); | ||
+ | out.fill(' | ||
+ | </ | ||
+ | |||
+ | ==== Formatierung mit Manipulatoren ==== | ||
+ | Manipulatoren bieten elegantere Schreibweisen zur Formatsteuerung: | ||
+ | |||
+ | <code cpp> | ||
+ | int manipuliere(std:: | ||
+ | { | ||
+ | int i = 123; | ||
+ | double d = 123.456789; | ||
+ | std::cout << std::hex << i << ' ' | ||
+ | << std::dec << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | std::cout << std:: | ||
+ | } | ||
+ | </ | ||
+ | Es gibt folgende parameterlose Manipulatoren: | ||
+ | |||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | |||
+ | Manipulatoren mit Parametern sind in [[iomanip]] definiert: | ||
+ | |||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
+ | | '' | ||
kennen/include/iostream.txt · Zuletzt geändert: 2017-03-24 10:11 von 127.0.0.1