Mit <stdio.h> arbeitest du über einen FILE * (Dateizeiger) mit Dateien.
| Funktion | Zweck |
|---|---|
fopen(pfad, modus) | Datei öffnen (NULL bei Fehler) |
fclose(f) | schließen |
fprintf, fputs, fputc, fwrite | schreiben |
fscanf, fgets, fgetc, fread | lesen |
feof, ferror | Ende/Fehler abfragen |
fseek, ftell, rewind | Position |
remove, rename | Datei löschen/umbenennen |
Modi: "r" lesen, "w" schreiben (löscht Inhalt), "a" anhängen, "r+" lesen und schreiben, "b" zusätzlich für Binärdateien ("rb", "wb").
#include <stdio.h>
#include <string.h>
int main(void) {
const char *pfad = "notiz.txt";
FILE *f = fopen(pfad, "w");
if (f == NULL) { perror("fopen"); return 1; }
fprintf(f, "Zeile %d\n", 1);
fputs("Zeile 2\n", f);
fclose(f);
f = fopen(pfad, "a"); // anhängen
if (f) { fputs("Zeile 3\n", f); fclose(f); }
f = fopen(pfad, "r");
if (f == NULL) { perror("fopen"); return 1; }
char zeile[64];
int nr = 0;
while (fgets(zeile, sizeof zeile, f) != NULL) { // zeilenweise lesen
zeile[strcspn(zeile, "\n")] = '\0';
printf("%d: %s\n", ++nr, zeile);
}
fclose(f);
FILE *fehlt = fopen("gibt-es-nicht.txt", "r");
if (!fehlt) perror("Fehler"); // gibt eine lesbare Meldung aus
remove(pfad);
return 0;
}1: Zeile 1 2: Zeile 2 3: Zeile 3
Immer prüfen, ob fopen NULL liefert, und jede geöffnete Datei mit fclose schließen.
Zahlen aus einer Datei
#include <stdio.h>
int main(void) {
FILE *f = fopen("zahlen.txt", "w");
if (!f) return 1;
for (int i = 1; i <= 5; i++) fprintf(f, "%d %.1f\n", i, i * 1.5);
fclose(f);
f = fopen("zahlen.txt", "r");
if (!f) return 1;
int n; double x, summe = 0;
while (fscanf(f, "%d %lf", &n, &x) == 2) summe += x;
fclose(f);
printf("Summe: %.1f\n", summe);
remove("zahlen.txt");
return 0;
}Summe: 22.5
Binärdateien
fwrite und fread schreiben und lesen Speicherblöcke direkt:
#include <stdio.h>
typedef struct { int id; double wert; char name[16]; } Eintrag;
int main(void) {
Eintrag e[3] = { {1, 1.5, "eins"}, {2, 2.5, "zwei"}, {3, 3.5, "drei"} };
FILE *f = fopen("daten.bin", "wb");
if (!f) return 1;
size_t geschrieben = fwrite(e, sizeof e[0], 3, f);
fclose(f);
Eintrag neu[3];
f = fopen("daten.bin", "rb");
if (!f) return 1;
size_t gelesen = fread(neu, sizeof neu[0], 3, f);
fseek(f, 0, SEEK_END);
long groesse = ftell(f); // Dateigröße in Bytes
fclose(f);
printf("%zu geschrieben, %zu gelesen, %ld Bytes\n", geschrieben, gelesen, groesse);
printf("%d %.1f %s\n", neu[2].id, neu[2].wert, neu[2].name);
remove("daten.bin");
return 0;
}3 geschrieben, 3 gelesen, 96 Bytes 3 3.5 drei
Fehlerbehandlung
- Rückgabewerte aller Datei-Funktionen prüfen
perror("text")oderstrerror(errno)(<errno.h>,<string.h>) liefern die Ursache- Zum Schreiben prüfen:
fclosekann einen verzögerten Schreibfehler melden - Beim Beenden bei Fehlern alle Dateien schließen (siehe goto-Muster)
Standardkanäle
Jedes Programm hat drei Dateizeiger: stdin (Eingabe), stdout (Ausgabe), stderr (Fehler). fprintf(stderr, ...) und fgets(zeile, n, stdin) sind dieselben Funktionen mit anderem Ziel.
Merke
fopenliefertNULLbei Fehlern: immer prüfen;fclosenicht vergessen- Text:
fprintf,fgets,fscanf; Binärdaten:fwrite,freadmit Modus"rb"/"wb" - Zeilenweise lesen mit
fgetsund Puffergröße perrorzeigt den Grund eines Fehlers- Dateien sind nur Ströme von Bytes; Formate bestimmst du selbst
Aufgabe
Schreibe ein Programm, das eine Textdatei zeilenweise liest, die Zeilen nummeriert in eine zweite Datei schreibt und die Wörter zählt.