I-PROGR2-HOME

  1. Einführung

  2. Stream-Klassen und Objekte

    1. Allgemeine Eigenschaften

    2. Spezielle Eigenschaften für File I/O

  3. Standard-Ein-/Ausgabefunktionen

  4. Manipulatoren

  5. Stream-Zustände

  6. Formate

  7. Dateien

  8. Testfragen und Aufgaben


I-PROGR2 SS03 - PROGRAMMIEREN2 - Vorlesung mit Übung
Input-Output in C++ - Grundlagen

 Achtung : Skript gibt den mündlichen Vortrag nicht vollständig wieder !
                         

AUTHOR: Gerd Döben-Henisch
DATE OF FIRST GENERATION: May-5, 2003
DATE OF LAST CHANGE: May-12, 2003, 19:50h
EMAIL: Gerd Döben-Henisch



1. Einführung


In der heutigen VL sollen die Grundzüge der Input-Output-Funktionen von C++ erläutert werden. Gegenüber der Sprache C wurden diese vollständig überarbeitet. Das gesamte Material ist so umfangreich, dass es nicht in einer VL vollständig behandelt werden kann. Als primäre Quellen für diese VL dienen [JOSUTTIS 1999] UND [JOSUTTIS 2001].


START



2. Stream-Klassen und Objekte


Gegenüber der Sprache C wurden die I/OFunktionen von C++ u.a. internationalisiert, die stringbezogenen Operationen wurden ganz auf C++-Strings umgestellt, eine Ausnahmebehandlung wurde implementiert und alle Symbole gehören nun zum std-Namensbereich ('namespace').

Sämtliche input-Output-Prozesse werden in C++ als Streams behandelt, d.h. als 'Strom von Daten', wobei ein Stream als ein Objekt konstruiert ist, das bestimmte Eigenschaften hat und mittels bestimmter Streamfunktionen manipuliert werden kann.

Die grossen Unterscheidungen sind Input und Output. Diese werden zusätzlich unterschieden nach 'normalem' I/O, Datei-I/O und Stream-I/O.Zusätzlich gibt es für diese verschiedenen Streams auch noch Buffer, die mit den Streams verknüpft werden können. Eine allgemeine Übersicht gibt das nächste Schaubild:



iosklassen

I/O-Basisklassen/Templates



Man kann in dem Schaubild u.a. erkennen, dass eine allgemeine Input-Output-Klasse ios_base mit einem Template basic_ios<> aufgespalten wird in zwei Templates für input-stream und output-stream. Der input-stream ist zum Lesen von Daten und der output-stream zum Schreiben von Daten. Ein kombinierter input-output-stream ist auch verfügbar. Diese Basisklassen sind dann nochmals zusätzlich spezifiziert für Dateioperationen und Stringoperationen.


START



2.1 Allgemeine Eigenschaften


Entsprechend der Struktur von Klassen kann man bei einer Klasse neben den Attributen auch Elementfunktionen unterscheiden. Die öffentlich zugänglichen Elementfunktionen der wichtigen I/O-Klassen zeigt das nächste Schaubild:

iofunctions

I/O-Basisklassen-Funktionen



Schon die Basisklasse ios_base stellt einige Funktionen zur Verfügung:

Zusätzlich haben die speziellen Klassen für Input bzw. Output spezielle Elementfunktionen:

Elementfunktionen für Input:

Elementfunktionen für Output:

Auf der Basis der zuvor definierten Klassen und Templates kann man Objekte generieren. Einige Objekte werden standardmässig generiert. Für den Inputstrema sind dies cin und wcin; für den output-stream sind dies cout, cerr und clog sowie die w-Versionen.


START



2.2 Spezielle Eigenschaften für File I/O


Für die Dateioperationen gibt es einige zusätzliche Operationen:



filefunctions

I/O-Basisklassen-Funktionen für Dateioperationen



Elementfunktionen für Input und Output:

Elementfunktionen für Input:

Elementfunktionen für Output:

Elementfunktionen für Buffer-Klasse:


START



3. Standard-Ein-/Ausgabefunktionen


Betrachten wir ein erstes Beispiel (aus [JOSUTTIS 1999]).




/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference"
 * by Nicolai M. Josuttis, Addison-Wesley, 1999
 *
 * (C) Copyright Nicolai M. Josuttis 1999.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include <cstdlib>
#include <iostream>
using namespace std;

int main()
{
    double x, y;        // operands

    // print header string
    cout << "Multiplication of two floating point values" << endl;

    // read first operand
    cout << "first operand:  ";
    if (! (cin >> x)) {
        /* input error
         *  => error message and exit program with error status
         */
        cerr << "error while reading the first floating value"
             << endl;
        return EXIT_FAILURE;
    }

    // read second operand
    cout << "second operand: ";
    if (! (cin >> y)) {
        /* input error
         *  => error message and exit program with error status
         */
        cerr << "error while reading the second floating value"
             << endl;
        return EXIT_FAILURE;
    }

    // print operands and result
    cout << x << " times " << y << " equals " << x * y << endl;
}



Include-Datei 'iostream' wird für Input- und Output mit Standardobjekten benutzt. Als solche werden 'cin', 'cout' und 'cerr' benutzt werden. Include-Datei 'cstdlib' wird für Fehlermeldungen benötigt wie dem Makro 'EXIT_FAILURE'.

In der Zeile

 cout << "Multiplication of two floating point values" << endl;
 

wird mit cout ein String auf den Bildschirm ausgegeben und mittels 'endl' mit newline und flush beendet (für 'endl' siehe weiter unten ---> Manipulatoren).

Die folgende Zeile fragt indirekt den Zustand des Strems ab. Der Operator '! ()' wird wahr, wenn im Stream ein Fehler aufgetreten ist (für Fehlerzustände siehe unten ---> Stream-Zustände).

   if (! (cin >> x)) {

Im folgenden wird dann eine Fehlerausgabe auf den Fehlerkanal gegeben.

   cerr << "error while reading the first floating value" <<  endl;

Aufrufe des Programms auf der Kommandozeile erzeugen folgenden Output:

gerd@goedel:~/WEB-MATERIAL/fh/I-PROGR2/I-PROGR2-EX/EX8> ./io1
Multiplication of two floating point values
first operand:  12
second operand: 5
12 times 5 equals 60


gerd@goedel:~/WEB-MATERIAL/fh/I-PROGR2/I-PROGR2-EX/EX8> ./io1
Multiplication of two floating point values
first operand:  -1.2
second operand: 5
-1.2 times 5 equals -6



gerd@goedel:~/WEB-MATERIAL/fh/I-PROGR2/I-PROGR2-EX/EX8> ./io1
Multiplication of two floating point values
first operand:

a
error while reading the first floating value
gerd@goedel:~/WEB-MATERIAL/fh/I-PROGR2/I-PROGR2-EX/EX8>

Was man 'nebenbei' an diesem Output sehen kann, ist, dass die Standardobjekte 'cin' und 'cout' mehrfach überladen sind. Sie sind für alle gängigen Datenformate 'voreingestellt'. Wie man eigene Datenformate zusätzlich einführen kann, das wird in einer Nachfolge-VL gezeigt werden.


START



4. Manipulatoren


Manipulatoren sind spezielle Objekte, um Streams zu manipulieren, so das bekannte 'endl', das schon mehrfach benutzt wurde:

std::cout << std::endl;

'endl' fügt bekanntlich ein '\n' ein. Zusätzlich wird der Output-Puffer geleert. Hier die Liste der Manipulatoren (noch nicht vollständig):

MANIPULATOR

KLASSE

BEDEUTUNG

endl

ostream

Gibt '\n' aus und flushed den output-Puffer

ends

ostream

Gibt '\0' aus

flush

ostream

flushed den output-Puffer

ws

istream

Liest whitespace und wirft es weg

setiosflags(flags)

ios_base

Setzt flags als format-Flags (ruft setf(flags) für den Stream); benötigt Inklude-Datei <iomanip> (s.u. bei ---> Formatierung)

setiosflags(mask)

ios_base

Klärt alle flags die durch mask identifiziert werden (Ruft setf(0,mask) für den Stream); benötigt Inklude-Datei <iomanip> (s.u. bei ---> Formatierung)

boolalpha

ios_base

erzwingt alphanumerische Representation(s.u. bei ---> Formatierung)

noboolalpha

ios_base

erzwingt numerische Representation(s.u. bei ---> Formatierung)

setw(val)

ios_base

setzt die Feldbreite für input und output auf val (s.u. bei ---> Formatierung)

setfill(c)

ios_base

definiert c als Füllzeichen (s.u. bei ---> Formatierung)

left

ios_base

adjustiert den Wert links (s.u. bei ---> Formatierung)

right

ios_base

adjustiert den Wert rechts (s.u. bei ---> Formatierung)

internal

ios_base

adjustiert das Zeichen links und den Wert rechts (s.u. bei ---> Formatierung)

oct

ios_base

schreibt und liest Oktalzahlen (s.u. bei ---> Formatierung)

hex

ios_base

schreibt und liest Hexzahlen (s.u. bei ---> Formatierung)

dec

ios_base

schreibt und liest Dezimalzahlen (s.u. bei ---> Formatierung)

...

ios_base

...


START



5. Stream-Zustände


Im Rahmen der Klasse ios_base sind mehrere Zustandsbits definiert, anhand denen man den Zustand eines Streams ablesen kann. Sie stehen allen Objekten vom Typ basic_istream und basic_outstream zur Verfügung. Stream-Puffer haben allerdings keine Zustandsbits.

KONSTANTE

BEDEUTUNG

goodbit

Alles ist OK; kein anderes Bit ist gesetzt

eofbit

Ende der Datei wurde erreicht

failbit

Fehler; eine I/O-Funktion war nicht erfolgreich

badbit;

Schlimmer Fehler; ein undefinierter Zustand wurde erreicht

Diese Zustandsbits können mittels Funktionen der Klasse ios_base manipuliert werden.

Aufgrund der Mängel der Ausnahmebehandlung in C++ wird im allgemeinen empfohlen, diese möglichst nicht zu benutzen


START



6. Formate


C++ bietet auch zahlreiche Möglichkeiten die Formate der ein- und Ausgaben zu beeinflussen. Um dies tun zu können, gibt es mehrere Möglichkeiten:

Einige der Format-Element-Funktionen sind hier aufgelistet.

FUNKTION

BEDEUTUNG

setf(flags)

Setzt flags als zusätzliche format-flags und gibt die bisherigen Zustand aller Flags zurück.

setf(flags, mask)

Setzt flags als zusätzliche format-flags für die durch mask identifizierte Gruppe und gibt die bisherigen Flags zurück.

unsetf(flags, mask)

Klärt flags.

flags()

Gibt alle aktuell gesetzten Format-flags zurück.

flags(flags)

Setzt flags als die neuen Format-flags und gibt die bisherigen Flags zurück.

copyfmt(stream)

Kopiert alle Format-Definitionen von stream.

copyfmt(stream)

Kopiert alle Format-Definitionen von stream.


START



7. Dateien


Dateien können im Rahmen spezieller Datei-Streams bearbeitet werden. Neben den Standardfunktionen für Streams:

Elementfunktionen für Output:

stehen im Falle von Dateien auch noch spezielle Elementfunktionen für Input und Output zur Verfügung:

Elementfunktionen für Input:

Elementfunktionen für Output:

Eng zusammenhängend mit Operationen mit Dateien sind die Elementfunktionen für die Buffer-Klasse:

Im Folgenden ein erstes einfaches Beispiel, das später weiter ausgebaut werden soll.


/* The following code example is taken from the book
 * "The C++ Standard Library - A Tutorial and Reference"
 * by Nicolai M. Josuttis, Addison-Wesley, 1999
 *
 * (C) Copyright Nicolai M. Josuttis 1999.
 * Permission to copy, use, modify, sell and distribute this software
 * is granted provided this copyright notice appears in all copies.
 * This software is provided "as is" without express or implied
 * warranty, and with no claim as to its suitability for any purpose.
 */
#include <string>       // for strings
#include <iostream>     // for I/O
#include <fstream>      // for file I/O
#include <iomanip>      // for setw()
#include <cstdlib>      // for exit()
using namespace std;

// forward declarations
void writeCharsetToFile (const string& filename);
void outputFile (const string& filename);

int main ()
{
    writeCharsetToFile("charset.out");
    outputFile("charset.out");
}

void writeCharsetToFile (const string& filename)
{
    // open output file
    ofstream file(filename.c_str());

    // file opened?
    if (! file) {
        // NO, abort program
        cerr << "can't open output file \"" << filename << "\""
             << endl;
        exit(EXIT_FAILURE);
    }

    // write character set
    for (int i=32; i<256; i++) {
        file << "value: " << setw(3) << i << "   "
             << "char:  " << static_cast<char>(i) << endl;
    }

}   // closes file automatically

void outputFile (const string& filename)
{
    // open input file
    ifstream file(filename.c_str());

    // file opened?
    if (! file) {
        // NO, abort program
        cerr << "can't open input file \"" << filename << "\""
             << endl;
        exit(EXIT_FAILURE);
    }

    // copy file contents to cout
    char c;
    while (file.get(c)) {
        cout.put(c);
    }

}   // closes file automatically



Es wird ein Objekt mit Namen file vom Typ output-stream angelegt. Der Dateiname wird als ein C++-String übergeben, der mit der elementfunktion c_str() in einen C-String umgewandelt wird.

  ofstream file(filename.c_str());

In der nachfolgenden Zeile wird wieder geprüft, ob ein Fehlerstatus bei Objekt file vorliegt.

  if (! file) {
 

In der folgenden Zeile wird die Feldbreite der Ausgabe mit dem Manipulator setw(3) auf den Wert 3 gesetzt; zugleich wird der Eingabewert, der vom Typ int ist, explizit in einen Typ char 'gecastet':

  file << "value: " << setw(3) << i << "   "  << "char:  " << static_cast(i) << endl;

Ist ein File-Stream zum Lesen geöffnet, kann man ihn mittels einer Standardfunktion get() auslesen und zugleich auf den Bildschirm ausgeben. 'file.get(c)' liest das nächste item aus der Datei in die Variable c undcout.put(c) gibt es auf dem Bildschirm aus.

   while (file.get(c)) {
        cout.put(c);
    }

Der Aufruf des Programms auf der Kommandozeile ergibt folgende Ausgabe:

gerd@goedel:~/WEB-MATERIAL/fh/I-PROGR2/I-PROGR2-EX/EX8> ./charset
value:  32   char:
value:  33   char:  !
value:  34   char:  "
value:  35   char:  #
value:  36   char:  $
value:  37   char:  %
value:  38   char:  &
value:  39   char:  '
value:  40   char:  (
value:  41   char:  )
value:  42   char:  *
value:  43   char:  +
value:  44   char:  ,
value:  45   char:  -
value:  46   char:  .
value:  47   char:  /
value:  48   char:  0
value:  49   char:  1
value:  50   char:  2
value:  51   char:  3
value:  52   char:  4
value:  53   char:  5
value:  54   char:  6
value:  55   char:  7
value:  56   char:  8
value:  57   char:  9
value:  58   char:  :
value:  59   char:  ;
value:  60   char:  <
value:  61   char:  =
value:  62   char:  >
value:  63   char:  ?
value:  64   char:  @
value:  65   char:  A
value:  66   char:  B
value:  67   char:  C
value:  68   char:  D
value:  69   char:  E
value:  70   char:  F
value:  71   char:  G
value:  72   char:  H
value:  73   char:  I
value:  74   char:  J
value:  75   char:  K
value:  76   char:  L
value:  77   char:  M
value:  78   char:  N
value:  79   char:  O
value:  80   char:  P
value:  81   char:  Q
value:  82   char:  R
value:  83   char:  S
value:  84   char:  T
value:  85   char:  U
value:  86   char:  V
value:  87   char:  W
value:  88   char:  X
value:  89   char:  Y
value:  90   char:  Z
value:  91   char:  [
value:  92   char:  \
value:  93   char:  ]
value:  94   char:  ^
value:  95   char:  _
value:  96   char:  `
value:  97   char:  a
value:  98   char:  b
value:  99   char:  c
value: 100   char:  d
value: 101   char:  e
value: 102   char:  f
value: 103   char:  g
value: 104   char:  h
value: 105   char:  i
value: 106   char:  j
value: 107   char:  k
value: 108   char:  l
value: 109   char:  m
value: 110   char:  n
value: 111   char:  o
value: 112   char:  p
value: 113   char:  q
value: 114   char:  r
value: 115   char:  s
value: 116   char:  t
value: 117   char:  u
value: 118   char:  v
value: 119   char:  w
value: 120   char:  x
value: 121   char:  y
value: 122   char:  z
value: 123   char:  {
value: 124   char:  |
value: 125   char:  }
value: 126   char:  ~
value: 127   char:
value: 128   char:
value: 129   char:
value: 130   char:
value: 131   char:
value: 132   char:
value: 133   char:
value: 134   char:
value: 135   char:
value: 136   char:
value: 137   char:
value: 138   char:
value: 139   char:
value: 140   char:
value: 141   char:
value: 142   char:
value: 143   char:
value: 144   char:
value: 145   char:
value: 146   char:
value: 147   char:
value: 148   char:
value: 149   char:
value: 150   char:
value: 151   char:
value: 152   char:
value: 153   char:
value: 154   char:
value: 155   char:
value: 156   char:
value: 157   char:
value: 158   char:
value: 159   char:
value: 160   char:
value: 161   char:  ¡
value: 162   char:  ¢
value: 163   char:  £
value: 164   char:  ¤
value: 165   char:  ¥
value: 166   char:  ¦
value: 167   char:  §
value: 168   char:  ¨
value: 169   char:  ©
value: 170   char:  ª
value: 171   char:  «
value: 172   char:  ¬
value: 173   char:  ­
value: 174   char:  ®
value: 175   char:  ¯
value: 176   char:  °
value: 177   char:  ±
value: 178   char:  ²
value: 179   char:  ³
value: 180   char:  ´
value: 181   char:  µ
value: 182   char:  ¶
value: 183   char:  ·
value: 184   char:  ¸
value: 185   char:  ¹
value: 186   char:  º
value: 187   char:  »
value: 188   char:  ¼
value: 189   char:  ½
value: 190   char:  ¾
value: 191   char:  ¿
value: 192   char:  À
value: 193   char:  Á
value: 194   char:  Â
value: 195   char:  Ã
value: 196   char:  Ä
value: 197   char:  Å
value: 198   char:  Æ
value: 199   char:  Ç
value: 200   char:  È
value: 201   char:  É
value: 202   char:  Ê
value: 203   char:  Ë
value: 204   char:  Ì
value: 205   char:  Í
value: 206   char:  Î
value: 207   char:  Ï
value: 208   char:  Ð
value: 209   char:  Ñ
value: 210   char:  Ò
value: 211   char:  Ó
value: 212   char:  Ô
value: 213   char:  Õ
value: 214   char:  Ö
value: 215   char:  ×
value: 216   char:  Ø
value: 217   char:  Ù
value: 218   char:  Ú
value: 219   char:  Û
value: 220   char:  Ü
value: 221   char:  Ý
value: 222   char:  Þ
value: 223   char:  ß
value: 224   char:  à
value: 225   char:  á
value: 226   char:  â
value: 227   char:  ã
value: 228   char:  ä
value: 229   char:  å
value: 230   char:  æ
value: 231   char:  ç
value: 232   char:  è
value: 233   char:  é
value: 234   char:  ê
value: 235   char:  ë
value: 236   char:  ì
value: 237   char:  í
value: 238   char:  î
value: 239   char:  ï
value: 240   char:  ð
value: 241   char:  ñ
value: 242   char:  ò
value: 243   char:  ó
value: 244   char:  ô
value: 245   char:  õ
value: 246   char:  ö
value: 247   char:  ÷
value: 248   char:  ø
value: 249   char:  ù
value: 250   char:  ú
value: 251   char:  û
value: 252   char:  ü
value: 253   char:  ý
value: 254   char:  þ
value: 255   char:  ÿ

 

Zugleich wurde eine Datei 'charset.out' angelegt.


START



7. Aufgaben


  1. Schreiben Sie eine Funktion, mittels der ein Anwender einen beliebig langen Text über die Tastatur eingeben kann, der in einem String gespeichert wird.


  2. Schreiben sie eine Funktion, die den Inhalt eines (Text-)Strings in eine Datei abspeichert. Der Dateiname kann vom Benutzer frei gewählt werden.


  3. Schreiben sie eine Funktion, die eine Textdatei öffnet und den Inhalt der Datei in einen String einliest.


  4. Schreiben Sie eine Funktion, mittels der ein Anwender einen beliebig langen Text über die Tastatur eingeben kann, der in einem String gespeichert wird. Besonderheit: der Text ist in Felder strukturiert, die aus Zeichenketten bestehen und aus Zahlen vom Typ double.


  5. Schreiben sie eine Funktion, die eine Datei öffnet, die in Feldern strukturiert ist, die auch Zahlen vom Typ double enthalten können und die den Inhalt der Datei in Strings bzw. Zahlen abspeichert.


  6. Schreiben sie eine Funktion, die den Inhalt eines (Text-)Strings an eine schon existierende Datei anhängt.


  7. Öffne Sie eine Datei und suchen Sie in dieser Datei nach einem Muster M; wenn das Muster gefunden wird, geben sie die Position in der Datei an, ab der das Muster in der Datei auftritt.


  8. Öffne Sie eine Datei und suchen Sie in dieser Datei nach einem Muster M; ersetzen Sie das Muster M in der Datei durch ein anderes Muster M'.



START