C Standard-Bibliothek

Ein- und Ausgabe: <stdio.h>


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.


Dateioperationen

Die folgenden Funktionen beschäftigen sich mit Dateioperationen. Der Typ size_t ist der vorzeichenlose, ganzzahlige Resultattyp des sizeof-Operators.

  FILE *fopen(const char *filename, const char *mode)
fopen eröffnet die angegebene Datei und liefert einen Datenstrom oder NULL bei Mißerfolg. Zu den erlaubten Werten von mode gehören
"r"Textdatei zum lesen und eröffnen
"w"Textdatei zum Schreiben erzeugen; gegebenenfalls alten Inhalt wegwerfen
"a"anfügen; Textdatei zum Schreiben am Dateiende eröffnen oder erzeugen
"r+"Textdatei zum Ändern eröffnen (Lesen und Schreiben)
"w+"Textdatei zum Ändern erzeugen; gegebenenfalls alten Inhalt wegwerfen
"a+"anfügen; Textdatei zum Ändern eröffnen oder erzeugen, Schreiben am Ende
Ändern bedeutet, daß die gleiche Datei gelesen und geschrieben werden darf; fflush oder eine Funktion zum Positionieren in Dateien muß zwischen einer Lese- und einer Schreiboperation oder umgekehrt aufgerufen werden. Enthält mode nach dem ersten Zeichen noch b, also etwa "rb" oder "w+b", dann wird auf eine binäre Datei zugegriffen. Dateinamen sind auf FILENAME_MAX Zeichen begrenzt. Höchstens FOPEN_MAX Dateien können gleichzeitig offen sein.

  FILE *freopen(const char *filename, const char *mode, FILE *stream)
freopen eröffnet die Datei für den angegebenen Zugriff mode und verknüpft stream damit. Das Resultat ist stream oder Null bei einem Fehler. Mit freopen ändert man normalerweise die Dateien, die mit stdin, stdout oder stderr verknüpft sind.

  int fflush(FILE *stream)
Bei einem Ausgabestrom sorgt fflush dafür, daß gepufferte, aber noch nicht geschriebene Daten geschrieben werden; bei einem Eingabestrom ist der Effekt undefiniert. Die Funktion liefert EOF bei einem Schreibfehler und sonst Null. fflush(NULL) bezieht sich auf alle offenen Dateien.

  int fclose(FILE *stream)
fclose schreibt noch nicht geschriebene Daten für stream, wirft noch nicht gelesene, gepufferte Eingaben weg, gibt automatisch angelegte Puffer frei und schließt den Datenstrom. Die Funktion liefert EOF bei Fehlern und sonst Null.

  int remove(const char *filename)
remove entfernt die angegebene Datei, so daß ein anschließender Versuch, sie zu eröffnen, fehlschlagen wird. Die Funktion liefert bei Fehlern einen von Null verschiedenen Wert.

  int rename(const char *oldname, const char *newname)
rename ändert den Namen einer Datei und liefert nicht Null, wenn der Versuch fehlschlägt.

  FILE *tmpfile(void)
tmpfile erzeugt eine temporäre Datei mit Zugriff "wb+", die automatisch gelöscht wird, wenn der Zugriff abgeschlossen wird, oder wenn das Programm normal zu Ende geht. tmpfile liefert einen Datenstrom oder NULL, wenn die Datei nicht erzeugt werden konnte.

  char *tmpnam(char s[L_tmpnam])
tmpnam(NULL) erzeugt eine Zeichenkette, die nicht der Name einer existenten Datei ist, und liefert einen Zeiger auf einen internen Vektor im statischen Speicherbereich. tmpnam(s) speichert die Zeichenkette in s und liefert auch s als Resultat; in s müssen wenigstens L_tmpnam Zeichen abgelegt werden können. tmpnam erzeugt bei jedem Aufruf einen anderen Namen; man kann höchstens von TMP_MAX verschiedenen Namen während der Ausführung des Programms ausgehen. Zu beachten ist, daß tmpnam einen Namen und keine Datei erzeugt.

  int setvbuf(FILE *stream, char *buf, int mode, size_t size)
setvbuf kontrolliert die Pufferung bei einem Datenstrom; die Funktion muß aufgerufen werden, bevor gelesen oder geschrieben wird, und vor allen anderen Operationen. Hat mode den Wert_IOFBF, so wird vollständig gepuffert, _IOLBF sorgt für zeilenweise Pufferung bei Textdateien und _IONBF verhindert Puffern. Wenn buf nicht NULL ist, wird buf als Puffer verwendet; andernfalls wird ein Puffer angelegt. size legt die Puffergröße fest. Bei einem Fehler liefert setvbuf nicht Null.

  void setbuf(FILE *stream, char *buf)
Wenn buf den Wert NULL hat, wird der Datenstrom nicht gepuffert. Andernfalls ist setbuf äquivalent zu (void) setvbuf(stream, buf, _IOFBF, BUFSIZ).


Formatierte Ausgabe

Die printf-Funktionen ermöglichen Ausgabe-Umwandlungen unter Formatkontrolle.

  int fprintf(FILE *stream, const char *format, ...)
fprintf wandelt Ausgaben um und schreibt sie in stream unter Kontrolle von format. Der Resultatwert ist die Anzahl der geschriebenen Zeichen; er ist negativ, wenn ein Fehler passiert ist.

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:

  • Steuerzeichen (flags) (in beliebiger Reihenfolge), die die Umwandlung modifizieren:
  • -veranlaßt Ausrichtung des umgewandelten Arguments in seinem Feld nach links.
    +bestimmt, daß die Zahl immer mit Vorzeichen ausgegeben wird.
    Leerzeichen wenn das erste Zeichen kein Vorzeichen ist, wird ein Leerzeichen vorangestellt.
    0legt bei numerischen Umwandlungen fest, daß bis zur Feldbreite mit führenden Nullen aufgefüllt wird.
    #verlangt eine alternative Form der Ausgabe. Bei o ist die erste Ziffer eine Null. Bei x oder X werden 0x oder 0X einem von Null verschiedenen Resultat vorangestellt. Bei e, E, f, g und G enthält die Ausgabe immer einen Dezimalpunkt; bei g und G werden Nullen am Schluß nicht unterdrückt.
  • eine Zahl, die eine minimale Feldbreite festlegt. Das umgewandelte Argument wird in einem Feld ausgegeben, das mindestens so breit ist und bei Bedarf auch breiter. Hat das umgewandelte Argument weniger Zeichen als die Feldbreite verlangt, wird links (oder rechts, wenn Ausrichtung nach links verlangt wurde) auf die Feldbreite aufgefüllt. Normalerweise wird mit Leerzeichen aufgefüllt, aber auch mit Nullen, wenn das entsprechende Steuerzeichen angegeben wurde.
  • Ein Punkt, der die Feldbreite von der Genauigkeit (precision) trennt.
  • Eine Zahl, die Genauigkeit, die die maximale Anzahl von Zeichen festlegt, die von einer Zeichenkette ausgegeben werden, oder die Anzahl Ziffern, die nach dem Dezimalpunkt bei e, E, oder f Umwandlungen ausgegeben werden, oder die Anzahl signifikanter Ziffern bei g oder G Umwandlung oder die minimale Anzahl von Ziffern, die bei einem ganzzahligen Wert ausgegeben werden sollen (führende Nullen werden dann bis zur gewünschten Breite hinzugefügt).
  • Ein Buchstabe als Längenangabe: h, l oder L."h" bedeutet, daß das zugehörige Argument als short oder unsigned short ausgegeben wird; "l" bedeutet, daß das Argument long oder unsigned long ist: "L" bedeutet, daß das Argument long double ist.

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
ZeichenArgument; Umwandlung in
d,iint; dezimal mit Vorzeichen.
oint; oktal ohne Vorzeichen (ohne führende Null).
x,Xint; hexadezimal ohne Vorzeichen (ohne führendes 0x oder 0X) mit abcdef bei 0x oder ABCDEF bei 0X.
uint; dezimal ohne Vorzeichen.
cint; int einzelnes Zeichen, nach Umwandlung in unsigned char.
schar*; aus einer Zeichenkette werden Zeichen ausgegeben bis vor '\0' oder so viele Zeichen, wie die Genauigkeit verlangt.
fdouble; dezimal als [-]mmm.ddd, wobei die Genauigkeit die Anzahl der d festlegt. Voreinstellung ist 6; bei 0 entfällt der Dezimalpunkt.
e,Edouble; dezimal als [-]m.dddddde±xx oder [-]m.ddddddE±xx, wobei die Genauigkeit die Anzahl der d festlegt. Voreinstellung ist 6; bei 0 entfällt der Dezimalpunkt.
g,Gdouble; %e oder %E wird verwendet, wenn der Exponent kleiner als -4 oder nicht kleiner als die Genauigkeit ist; sonst wird %f benutzt. Null und Dezimalpunkt am Schluß werden nicht ausgegeben.
pvoid*; als Zeiger (Darstellung hängt von Implementierung ab).
nint*;die Anzahl der bisher von diesem Aufruf von printf ausgegebenen Zeichen wird im Argument abgelegt. Ein Argument wird nicht umgewandelt.
%kein Argument wird umgewandelt; ein % wird ausgegeben.


Formatierte Eingabe

Die 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:

  • Leerzeichen oder Tabulatorzeichen, die ignoriert werden.
  • Gewöhnliche Zeichen (nicht aber %), die dem nächsten Zeichen nach Zwischenraum im Eingabestrom entsprechen müssen.
  • Umwandlungsangaben, bestehend aus %; einem optionalen Zeichen *, das die Zuweisung an ein Argument verhindert; einer optionalen Zahl, die die maximale Feldbreite festlegt; einem optionalen Buchstaben h, l, oder L, der die Länge des Ziels beschreibt; und einem Umwandlungszeichen.

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
ZeichenEingabedaten; Argumenttyp
ddezimal, ganzzahlig; int *.
iganzzahlig; int *. Der Wert kann oktal (mit 0 am Anfang) oder hexadezimal (mit 0x oder 0X am Anfang) angegeben sein.
ooktal ganzzahlig (mit oder ohne 0 am Anfang); int *.
udezimal ohne Vorzeichen; unsigned int *.
xhexadezimal ganzzahlig (mit oder ohne 0x oder 0X am Anfang); int *.
cein oder mehrere Zeichen; char *. Die nachfolgenden Eingabezeichen werden im angegebenen Vektor abgelegt, bis die Feldbreite erreicht ist; Voreinstellung ist 1. '\0' wird nicht angefügt. In diesem Fall wird Zwischenraum nicht überlesen; das nächste Zeichen nach Zwischenraum liest man mit %ls.
sFolge von Nicht-Zwischenraum-Zeichen (ohne Anführungszeichen); char *, der auf einen Vektor zeigen muß, der die Zeichenkette und das abschließende '\0' aufnehmen kann, das dazukommt.
e, f, gGleitpunkt; float *. Das Eingabeformat erlaubt für float ein optionales Vorzeichen, eine Ziffernfolge, die auch einen Dezimalpunkt enthalten kann, und einen optionalen Exponenten, bestehend aus E oder e und einer ganzen Zahl, optional mit Vorzeichen.
pZeiger, wie ihn printf("%p") ausgibt; void *
nlegt im Argument die Anzahl Zeichen ab, die bei diesem Aufruf bisher gelesen wurden; int *. Vom Eingabestrom wird nicht gelesen, die Zählung der Umwandlungen bleibt unbeeinflußt.
[...]erkennt die längste nicht-leere Zeichenkette aus den Eingabezeichen in der angegebenen Klasse; char *. Dazu kommt '\0'. Die Klasse []...] enthält auch].
[^...]erkennt die längste nicht-leere Zeichenkette aus den Eingabezeichen nicht in der angegebenen Klasse; char*. Dazu kommt '\0'. Die Klasse [^]...] enthält auch ].
%erkennt %; eine Zuweisung findet nicht statt.


Ein- und Ausgabe von Zeichen

  int 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 Ausgabe

  size_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 Dateien

  int 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.


Fehlerbehandlung

Viele 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 ]

 

15. November 1999, Peter Klingebiel, DVZ