Version [22635]
Dies ist eine alte Version von ProzProg4EingabeAusgabe erstellt von RonnyGertler am 2013-03-27 20:49:44.
Prozedurale Programmierung - Kapitel 4 - Eingabe und Ausgabe
Inhalte von Dr. E. Nadobnyh
Grundbegriffe
1. Eine Ausgabe ist die Datenlieferung vom Prozessor bzw. vom Programm zu Peripherie (Bildschirm, Datei).
2. Eine Eingabe ist die Datenlieferung von Peripherie (Tastatur, Datei) zum Prozessor.
3. I/O steht für "Input/Output", E/A -für "Eingabe/ Ausgabe".
4. Bildschirm und Tastatur werden auch als Konsole bezeichnet.
5. Die E/A–Operationen über Konsole werden als interaktive und die E/A–Operationen mit Dateien als nicht-interaktive bezeichnet.
Bibliothekfunktionen für E/A
Für die Eingabe und Ausgabe stehen in C und C++ keine Operatoren zur Verfügung. Die entsprechende Funktionen werden in Standardbibliotheken definiert.
Zwei Standardbibliotheken sind verbreitet:
1) stdio-Bibliothek für C enthält rund 40 Funktionen, darunter printf und scanf als zentrale Funktionen .
2) iostream-Bibliothek für C++ enthält eine ganze Klassenhierarchie und auch Objekte cout und cin.
Überblick
In C++ stehen die C-Funktionen auch zur Verfügung.
C++ hat ihr eigenes Eingabe-Ausgabe-Konzept. Es ist typsicher und ist leicht erweiterbar, z.B. für benutzerdefinierten Datentypen. Standardbibliotheken werden durch die Include-Dateien <stdio.h> und <iostream> eingebunden.
Hier sind einige Beispiele ohne formale Beschreibung:
Bibliothek Aufgabe |
sdtio | iostream |
Bildschirmausgabe | printf | cout<< |
Tastatureingabe | scanf | cin>> |
Dateizugriff | fprintf und fscanf | fstream |
4.1. Bildschirmausgabe
printf
Die formatgesteuerte Ausgabe erfolgt in der stdio-Bibliothek mit der Funktion printf (print formatted). Diese Funktion übersetzt interne Werte in Textzeilen.
Syntax (nicht vollständig): printf (fz , a1, ... ,aN );
1) Argumente a1 bis aN sind Variablen oder andere Daten, die ausgegeben werden müssen.
2) Eine Format-Zeichenkette fz steuert die Formatierung aller Argumente. Sie enthält zwei Arten von Zeichenfolgen:
- gewönliche Zeichen, die in die Ausgabe kopiert werden;
- Formatelemente, die mit dem Zeichen % beginnen und eigentliche Formatierung für die Argumente steuern.
3) Jeder Formatelement bestimmt das Format für ein entsprechendes Argument. Die Format-Zeichenkette bestimmt, wieviele weitere Argumente folgen.
Format-Zeichenkette
Bei der Ausgabe wird jedes Formatelement durch den Wert des nächsten Argumentes ersetzt.
Erklärung:
Format-Zeichenkette: | “2 * %d ergibt %d “ |
Formatelement: | %d |
Argumente: | a, b |
Steuerung: | zwei %d steuern a und b |
Ausgabe: | 2 * 5 ergibt 10 |
printf-Formatelement
Ein Formatelement (Umwandlungsspezifikation) besteht aus 6 Teilen. Linker und rechter Teil sind obligatorisch.
% | - | min | .max | L | UZ |
% | Anfang des Formatelementes |
- | Minus steuert linksbündige Ausgabe |
min | Mindestlänge des Ausgabebereichs |
.max |
1)Anzahl Stellen rechts vom Punkt für Gleitpunkttypen 2)Maximale Länge der auszugebenden Zeichenkette |
L | L - Argument ist long double, l - Argument ist long |
UZ |
Umwandlungszeichen, z.B.: d – Darstellung von Ganzzahlen, f – Darstellung von Gleitpunktzahlen. |
Beispiel:
float a=3.141592; printf(„pi= %7.3f“, a); //pi= 3.142
printf-Umwandlungszeichen
Das Umwandlungszeichen gibt die Interpretation des auszugebenden Wertes.
UZ | Ausgabe als: |
c | Einzelzeichen |
d, i | Ganzzahl (dezimal) |
u | Ganzzahl (dezimal, nur positiv) |
o | Ganzzahl (oktal, nur positiv) |
x, X | Ganzzahl (hexadezimal, nur positiv) |
e, E | Gleitpunktzahl in Exponentendarstellung |
f | Gleitpunktzahl in Dezimalbruchdarstellung |
g, G | kürzeste Darstellung von e oder f |
s | Zeichenkette (C-String) |
p | Pointer (Adresse ) |
⇒ Demos 1, 2, 3.
4.2. Tastatureingabe
scanf
Die formatgesteuerte Eingabe erfolgt in der stdio-Bibliothek mit der Funktion scanf (scan formatted). Diese Funktion übersetzt Eingabefelder in interne Werte. Sie macht praktisch die gleiche Umwandlungen wie printf in der umgekehrten Richtung.
Syntax (nicht vollständig): scanf (fz , a1, ... , aN );
1) Argumente a1 bis aN sind Zeiger auf Variablen oder Adressen. Sie geben an, wo die dazugehörigen umgewandelten Daten gespeichert werden sollen. Die Variablen müssen über den Adress- Operator (&) angesprochen werden.
2) Eine Format-Zeichenkette fz legt die Anzahl der Eingaben und Interpretation (Typ, Format) der einzelnen Eingabefelder fest. Sie kann enthalten:
- Blanks, Tabs und Newlines (werden ignoriert),
- Formatelemente (Umwandlungsspezifikationen).
scanf- Ausführung
1) Die Eingabe wird erst an das Programm gesendet, nachdem die Returntaste betätigt wurde.
2) scanf hört auf, wenn die Format-Zeichenkette abgearbeitet wurde, oder wenn ein Eingabefeld nicht zur Umwandlungsangabe passt.
3) Der nächste scanf-Aufruf beginnt seine Suche nach dem zuletzt umgewandelten Zeichen.
4) Eingabefelder werden durch Zwischenraumzeichen getrennt: Leerzeichen, Tabulatorzeichen, Seitenvorschub, Newline ua. Daraus folgt, daß scanf über Zeilengrenzen hinweg liest,
5) Ein Eingabefeld wird bis zu:
a) dem nächsten Zwischenraumzeichen oder
b) einer angegebenen Feldbreite gelesen.
scanf-Formatelement
Ein Formatelement (Umwandlungsspezifikation) besteht aus 5 Teilen. Linker und rechter Teil sind obligatorisch.
% | * | max | L | UZ |
% | Anfang des Formatelementes |
* | Eingabefeld wird übergangen |
max | Maximale Länge des Eingabefeldes |
L | L - Argument ist long double, l - Argument ist long oder double ua. |
UZ | Umwandlungszeichen: c, u, d, i, o, x, e, f, g, s |
Das Umwandlungszeichen gibt die Interpretation des Eingabefeldes. Achtung: scanf unterscheidet zwischen f für float und lf für double.
Beispiel:
int i1;
scanf("%d", &i1); //Eingabe: 1234
fflush
Ein- und Ausgabeoperationen sind gepuffert Bei Dialoganwendungen, z.B. über Konsole, wird ein gemeinsamer Puffer verwendet.
In manchen Fällen bei abwechselnder Eingabe und Ausgabe ist es erforderlich, den Puffer zu leeren. Für solche Fälle ist die Funktion fflush vorgesehen.
Beispiel: fflush(stdin);
⇒ Demo 4.
4.3. Dateizugriff
Begriffsdefinitionen
Ein Dateizugriff (Dateibearbeitung, Datei-Transfer) ist eine Eingabe/Ausgabe aus/in Dateien.
C/C++ macht keinen Unterschied zwischen Dateien und Geräten (z.B. Konsole, Drucker). Beide Gruppen werden gleich betrachtet und behandelt.
Textdateien bestehen aus einer Folge von Zeilen. Jede Zeile ist mit einem Newline-Zeichen abgeschlossen. Textdateien
werden in der Regel sequentiell verarbeitet.
Funktionen für Dateizugriff:
1) zum Öffnen und Schließen von Dateien,
2) zum Schreiben und Lesen,
3) zur Fehlerbehandlung,
4) zur Dateiverwaltung, z.B. Funktionen für einen direkten Zugriff (random access) auf Datei.
Einführungsbeispiel
Das Zusammenspiel von Dateioperationen kann im einen kleinen Programm illustriert werden:
#include <stdio.h>
int main()
{ //Zeiger auf die Datei definieren
FILE* fp;
//Datei zum Schreiben erzeugen und oeffnen
fp=fopen("name.txt", "w");
//Text in die Datei schreiben
fprintf(fp, "Dieser Text geht in die Datei");
//Datei schliessen
fclose(fp);
return 0;
}
int main()
{ //Zeiger auf die Datei definieren
FILE* fp;
//Datei zum Schreiben erzeugen und oeffnen
fp=fopen("name.txt", "w");
//Text in die Datei schreiben
fprintf(fp, "Dieser Text geht in die Datei");
//Datei schliessen
fclose(fp);
return 0;
}
Öffnen von Dateien
Dateien müssen vor der Nutzung explizit geöffnet werden. Prototyp: FILE* fopen(char* dateiname, char* modus);
Die Funktion akzeptiert einen Dateinamen, z.B. „etwas.txt“ und liefert einen Zeiger, der beim Lesen oder Schreiben der Datei verwendet wird. Das zweite Argument ist die Zugriffsart. Einige Arten:
modus | Beschreibung |
„r“ | (read) Öffnen zum Lesen. Datei muß existieren. |
„w“ | (write) Öffnen zum Schreiben. Die evtl. existierende Datei wird durch leere ersetzt. |
„a“ | (append) Anfügen an Datei. Die evtl. existierende Datei wird nicht gelöscht |
„w+“ | Öffnen zum Lesen und Schreiben. Die evtl. existierende Datei wird durch leere ersetzt. |
fopen- Ausführung
1) Wenn eine nicht existierende Datei zum Schreiben oder Anfügen eröffnet wird, so wird sie erzeugt, falls das möglich ist.
2) Wird eine existierende Datei zum Schreiben eröffnet, geht der alte Inhalt verloren.
3) Beim Öffnen zum Anfügen bleibt der Inhalt erhalten.
4) Beim Datei-Öffnen wird implizit auch ein Dateipuffer im Arbeitsspeicher definiert. Der Dateipuffer ermöglicht einen effektiver Datentransfer zwischen Speicher und Datei.
Dateipuffer
Fehler beim Öffnen
Nach jedem fopen-Aufruf sollte geprüft werden, ob die Datei auch wirklich geöffnet wurde.
Einige Fehlerursachen sind:
1) Eine Datei soll gelesen werden, jedoch existiert nicht.
2) Eine Eingabedatei kann nicht gelesen werden, z.B. kein Zugriffsrecht.
3) Eine schreibgeschützte Datei soll beschrieben werden.
Bei Fehler liefert die Funktion fopen den Wert NULL:
FILE* fp = fopen( „text.txt", "r");
if(NULL == fp)
{ printf("Fehler beim Datei-Oeffnen");
}
if(NULL == fp)
{ printf("Fehler beim Datei-Oeffnen");
}
Schreiben und Lesen von Dateien
Das Lesen und Schreiben von Datei erfolgt entsprechend dem Lesen von der Tastatur bzw. dem Schreiben auf den Bildschirm.
Die Funktionen fprintf und fscanf werden exakt wie printf und scanf verwendet. Als erstes Argument fp bekommen sie ein FILE-Zeiger auf die Datei.
Syntax (nicht vollständig):
fprintf ( fp, fz, a1, ... , aN );
fscanf ( fp, fz, a1, ... , aN );
Jede Schreib/Lese-Operation bezieht sich auf die aktuelle Position in der Datei.
Lesen von Dateien
1) Man sollte eine Datei nur dann mit fscanf lesen, wenn man ihr Format genau kennt.
2) Die Daten müssen im Wesentlichen das Format von Literalen des entsprechenden Datentyps haben, z.B.:
Operator | Datei-Inhalt | Inhalt x |
float x; fscanf(fp, "%f", &x); |
1.234e-2 | 0.01234 |
3) Bei der Eingabe von mehreren Literalen, müssen sie durch Leerzeichen, Tabulatoren oder Zeilenvorschübe getrennt werden. Sonst sind sie beim Lesen nicht auseinander zu halten.
Operator | Datei-Inhalt | Inhalt x und y |
float x; int y; fscanf(fp, "%f %d", &x, &y); |
1.234e-2 567 |
0.01234 567 |
4) Alle führende und doppelte Trennzeichen werden überlesen.
5) scanf bricht ab, sobald ein Zeichen gelesen wird, das nicht den Formatangaben entspricht.
Nach jedem Datei-Zugriff sollte geprüft werden, ob das Lesen wirklich ausgeführt wurde. Dafür liefert fscanf die Anzahl der tatsächlich eingelesenen Datenfelder zurück.
6) Der Zustand EOF (End Of File) wird gesetzt, wenn man über letztes Zechen der Datei liest. Das Erreichen des Dateiendes ist keine Katastrophe. Es ist üblich. Dieser Zustand kann mit der Funktion feof abgefragt werden.
⇒ Demo 5.
Schließen von Dateien
Schließen der Datei ist eine komplementäre Operation zum Öffnen. Danach werden keine weiteren Zugriffe auf die Datei erlaubt. Zum Schließen gibt es mehrere Möglichkeiten:
1) Wenn sich ein Programm beendet, schließen sich automatisch alle noch offenen Dateien.
2) Das explizite Schließen einer Datei folgt durch den Aufruf der Funktion fclose.
Wenn z.B. eine Datei zuerst beschrieben und danach gelesen werden soll, kann sie für solche Umschaltung explizit geschlossen und wieder geöffnet werden.
Eine zum Schreiben geöffnete Datei ist verletzbar, solange sie nicht wieder geschlossen ist. Wenn eine Datei im Schreibmodus geöffnet wurde, wird diese erst beschrieben, wenn der Puffer voll ist. Die Daten im Puffer sind verloren, wenn das Programm abstürzt oder z.B. ein USB-Stick einfach abgezogen wird.
⇒ Demo 6.
4.4. E/A - mit iostream
Grundbegriffe
1. Beim Start eines C++ -Programms sind die so genannte iostream-Variablen (Objekte) automatisch vordefiniert und können benutzt werden:
- cin ("console input") repräsentiert die Tastatur bei der Standard-Eingabe;
- cout ("console output") repräsentiert den Bildschirm bei der Standard-Ausgabe.
Der innere Aufbau des Datentyps iostream ist kompliziert und bleibt dem Benutzer verborgen.
2. Eingabe und Ausgabe werden über vordefinierte Operatoren << und >> bedient.
Anmerkung: Operatoren << und >> sind überladen, d.h. für iostream redefiniert. Die ursprüngliche Bedeutung von diesen Operatoren ist Bit-Shift.
Der Ausgabeoperator <<
1. Die Funktionsweise kann man mit dem Prinzipbeispiel erläutern:
Quelltext: cout<< „Hallo“ ;
Bedeutung:
2. Mit < können die vordefinierten Standardtypen ohne spezielle Formatierungssymbole ausgegeben werden, z.B.:
cout << "Hallo"; cout << 1.2<
int x=12, y=3; cout << x+y<
3. Der Manipulator endl (end line) gibt das Symbol (Symbole) „Ende der Zeile“ aus. Der Cursor auf dem Bildschirm bewegt sich auf den Anfang der nächsten Zeile.
4. Ausgabeoperatoren sind kaskadierbar bzw. verkettbar.
CategoryProzProg