Die Ein- und Ausgabefunktionen, Typen und Makros, die in <stdio.h> vereinbart sind, machen nahezu ein Drittel der Bibliothek aus. Ein Datenstrom (stream) ist Quelle oder Ziel von Daten und wird mit einer Platte oder einem anderen Peripheriegerät verknüpft. Die
Bibliothek unterstützt zwei Arten von Datenströmen, für Text und binäre Information, die allerdings bei manchen Systemen und insbesondere bei UNIX identisch sind. Ein Textstrom ist eine Folge von Zeilen; jede Zeile enthält null oder mehr Zeichen und ist mit '\n' abgeschlossen. Eine Umgebung muß möglicherweise zwischen einem Textstrom und einer anderen Repräsentierung umwandeln (also zum Beispiel '\n' als Wagenrücklauf und Zeilenvorschub abbilden). Wird ein Binärstrom geschrieben
und auf dem gleichen System wieder eingelesen, so entsteht die gleiche Information. Ein Strom wird durch Eröffnen (open) mit einer Datei oder einem Gerät verbunden; die Verbindung wird durch Abschließen (close) wieder aufgehoben. Eröffnet man eine Datei, so erhält man einen Zeiger auf ein Objekt vom Typ FILE, wo alle Information hinterlegt ist, die zur Kontrolle des Stroms nötig ist. Wenn die Bedeutung eindeutig ist, werden wir die Begriffe FILE-Zeiger und
Datenstrom gleichberechtigt verwenden. Wenn die Ausführung eines Programms beginnt, sind die drei Ströme stdin, stdout und stderr bereits eröffnet. Die Format-Zeichenkette enthält zwei Arten von Objekten: gewöhnliche Zeichen, die in die Ausgabe kopiert werden, und Umwandlungsangaben, die jeweils die Umwandlung und Ausgabe des nächstfolgenden Arguments von fprintf veranlassen. Jede Umwandlungsangabe beginnt mit dem Zeichen % und endet mit einem Umwandlungszeichen. Zwischen %
und dem Umwandlungszeichen kann, der Reihenfolge nach, folgendes angegeben werden:
Als Feldbreite oder Genauigkeit kann jeweils * angegeben werden; dann wird der Wert durch Umwandlung von dem nächsten oder den zwei nächsten Argumenten festgelegt, die den Typ int besitzen müssen. Die Umwandlungszeichen und ihre Bedeutung erklärt Tabelle 1. Wenn das Zeichen nach % kein Umwandlungszeichen ist, ist der Verlauf undefiniert. int printf(const char *format, ...) printf(...) ist äquivalent zu fprintf(stdout,...). int sprintf(char *s, const char *format, ...) sprintf funktioniert wie printf, nur wird die Ausgabe in den Zeichenvektor s geschrieben und mit '\0' abgeschlossen. s muß groß genug für das Resultat sein. Im Resultatwert wird '\0' nicht mitgezählt. vprintf(const char *format, va_list arg) vfprintf(FILE *stream, const char *format, va_list arg) vsprintf(char *s, const char *format, va_list arg) Die Funktionen vprintf, vfprintf und vsprintf sind äquivalent zu den entsprechenden printf-Funktionen, jedoch wird die variable Argumentliste durch arg ersetzt. Dieser Wert wird mit dem Makro va_startund vielleicht mit Aufrufen von va_arg initialisiert. Siehe dazu die Beschreibung von <stdarg.h> im Abschnitt Variable Argumentenliste. Tabelle 1: printf Umwandlungen
Formatierte EingabeDie scanf-Funktionen behandeln Eingabe-Umwandlungen unter Formatkontrolle. int fscanf(FILE *stream, const char *format, ...) fscanf liest von stream unter Kontrolle von format und legt umgewandelte Werte mit Hilfe von nachfolgenden Argumenten ab, die alle Zeiger sein müssen. Die Funktion wird beendet, wenn format abgearbeitet ist. fscanf liefert EOF, wenn vor der ersten Umwandlung das Dateiende erreicht wird oder ein Fehler passiert; andernfalls liefert die Funktion die Anzahl der umgewandelten und abgelegten Eingaben.Die Format-Zeichenkette enthält normalerweise Umwandlungsangaben, die zur Interpretation der Eingabe verwendet werden. Die Format-Zeichenkette kann folgendes enthalten:
Eine Umwandlungsangabe bestimmt die Umwandlung des nächsten Eingabefelds. Normalerweise wird das Resultat in der Variablen abgelegt, auf die das zugehörige Argument zeigt. Wenn jedoch * die Zuweisung verhindern soll, wie bei %*s, dann wird das Eingabefeld einfach übergangen und eine Zuweisung findet nicht statt. Ein Eingabefeld ist als Folge von Zeichen definiert, die keine Zwischenraumzeichen sind; es reicht entweder bis zum nächsten Zwischenraumzeichen, oder bis eine explizit angegebene Feldbreite erreicht ist. Daraus folgt, daß scanf über Zeilengrenzen hinweg liest, um seine Eingabe zu finden, denn Zeilentrenner sind Zwischenraumzeichen. (Zwischenraumzeichen sind Leerzeichen, Tabulatorzeichen \t, Zeilentrenner \n, Wagenrücklauf \r, Vertikaltabulator \v und Seitenvorschub \f). Das Umwandlungszeichen gibt die Interpretation des Eingabefelds an. Das zugehörige Argument muß ein Zeiger sein. Die erlaubten Umwandlungszeichen zeigt Tabelle 2. Den Umwandlungszeichen d, i, n, o, u und x kann h vorausgehen, wenn das Argument ein Zeiger auf short statt int ist, oder der Buchstabe l, wenn das Argument ein Zeiger auf long ist. Vor den Umwandlungszeichen e, f und g kann der Buchstabe l stehen, wenn ein Zeiger auf double und nicht auf float in der Argumentliste steht, und L, wenn es sich um einen Zeiger auf long double handelt. int scanf(const char *format, ...)scanf(...) ist äquivalent zu fscanf(stdin,...). int sscanf(const char *s, const char *format, ...)sscanf(s, ...) ist äquivalent zu scanf(...), mit dem Unterschied, daß die Eingabezeichen aus der Zeichenkette s stammen. Tabelle 2: scanf Umwandlungen
Ein- und Ausgabe von Zeichenint fgetc(FILE *stream)fgetc liefert das nächste Zeichen aus stream als unsigned char (umgewandelt in int) oder EOF bei Dateiende oder bei einem Fehler. char *fgets(char *s, int n, FILE *stream)fgets liest höchstens die nächsten n-1 Zeichen in s ein und hört vorher auf, wenn Zeilentrenner gefunden wird. Der Zeilentrenner wird im Vektor abgelegt. Der Vektor wird mit '\0' abgeschlossen. fgets liefert s oder NULL bei Dateiende oder bei einem Fehler. int fputc(int c, FILE *stream)fputc schreibt das Zeichen c (umgewandelt in unsigned char) in stream. Die Funktion liefert das ausgegebene Zeichen oder EOF bei Fehler. int fputs(const char *s, FILE *stream) fputs schreibt die Zeichenkette s (die '\n' nicht zu enthalten braucht) in stream. Die Funktion liefert einen nicht-negativen Wert oder EOF bei einem Fehler. int getc(FILE *stream)getc ist äquivalent zu fgetc, kann aber ein Makro sein und dann das Argument für stream mehr als einmal bewerten. int getchar(void) getchar ist äquivalent zu getc(stdin). char *gets(char *s) gets liest die nächste Zeile von stdin in den Vektor s und ersetzt dabei den abschließenden Zeilentrenner durch '\0'. Die Funktion liefert s oder NULL bei Dateiende oder bei einem Fehler. int putc(int c, FILE *stream)putc ist äquivalent zu fputc, kann aber ein Makro sein und dann das Argument für stream mehr als einmal bewerten. int putchar(int c)putchar(c) ist äquivalent zu putc(c, stdout). int puts(const char *s)puts schreibt die Zeichenkette s und einen Zeilentrenner in stdout. Die Funktion liefert EOF, wenn ein Fehler passiert, andernfalls einen nicht-negativen Wert. int ungetc(int c, FILE *stream)ungetc stellt c (umgewandelt in unsigned char) in stream zurück, von wo das Zeichen beim nächsten Lesevorgang wieder geholt wird. Man kann sich nur darauf verlassen, daß pro Datenstrom ein Zeichen zurückgestellt werden kann. EOF darf nicht zurückgestellt werden. ungetc liefert das zurückgestellte Zeichen oder EOF bei einem Fehler. Direkte Ein- und Ausgabesize_t fread(void *ptr, size_t size, size_t nobj, FILE *stream)fread liest aus stream in den Vektor ptr höchstens nobj Objekte der Größe size ein. fread liefert die Anzahl der eingelesenen Objekte; das kann weniger als die geforderte Zahl sein. Der Zustand des Datenstroms muß mit feof und ferror untersucht werden. size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *stream)fwrite schreibt nobj Objekte der Größe size aus dem Vektor ptr in stream. Die Funktion liefert die Anzahl der ausgegebenen Objekte; bei Fehler ist das weniger als nobj. Positionieren in Dateienint fseek(FILE *stream, long offset, int origin) fseek setzt die Dateiposition für stream; eine nachfolgende Lese- oder Schreiboperation wird auf Daten von der neuen Position ab zugreifen. Für eine binäre Datei wird die Position auf offset Zeichen relativ zu origin eingestellt; dabei können die Werte SEEK_SET (Dateianfang) SEEK_CUR (aktuelle Position) oder SEEK_END (Dateiende) angegeben werden. Für einen Textstrom muß offset Null sein oder ein Wert, der von ftell stammt (dafür muß dann origin den Wert SEEK_SET erhalten). fseek liefert einen von Null verschiedenen Wert bei Fehler. long ftell(FILE *stream) ftell liefert die aktuelle Dateiposition für stream oder -1L bei Fehler. void rewind(FILE *stream) rewind(fp) ist äquivalent zu fseek(fp, OL, SEEK_SET); clearerr(fp); int fgetpos(FILE *stream, fpos_t *ptr)fgetpos speichert die aktuelle Position für stream bei *ptr. Der Wert kann später mit fsetpos verwendet werden. Der Datentyp fpos_t eignet sich zum Speichern von solchen Werten. Bei Fehler liefert fgetpos einen von Null verschiedenen Wert. int fsetpos(FILE *stream, const fpos_t *ptr) fsetpos positioniert stream auf die Position, die von fgetpos in *ptr abgelegt wurde. Bei Fehler liefert fsetpos einen von Null verschiedenen Wert.FehlerbehandlungViele der Bibliotheksfunktionen notieren Zustandsangaben, wenn ein Dateiende oder ein Fehler gefunden wird. Diese Angaben können explizit gesetzt und getestet werden. Außerdem kann der Integer-Ausdruck errno (der in <errno.h> deklariert ist) eine Fehlernummer enthalten, die mehr Information über den zuletzt aufgetretenen Fehler liefert. void clearerr(FILE *stream) clearerr löscht die Dateiende- und Fehlernotizen für stream. int feof(FILE *stream) feof liefert einen von Null verschiedenen Wert, wenn für stream ein Dateiende notiert ist. int ferror(FILE *stream) ferror liefert einen von Null verschiedenen Wert, wenn für stream ein Fehler notiert ist. void perror(const char *s) perror(s) gibt s und eine von der Implementierung definierte Fehlermeldung aus, die sich auf die Fehlernummer in errno bezieht. Die Ausgabe erfolgt im Stil von fprintf(stderr, "%s: %s\n", s, "Fehlermeldung") Siehe strerror im Abschnitt <string.h>.[ Anfang der Seite | Inhaltsverzeichnis | Funktions-Register Header-Register ] |