Programmieren in C - www2.inf.h

Werbung
Inhalt
•
•
•
•
•
•
•
•
Dateibehandlung
Soll ein C-Programm eine Datei (lesend oder schreibend) nutzen, so
werden verschiedene Funktionen der stdio.lib benötigt
➔
stdio.h mit include einbinden
Einführung
Elementare Datentypen und Anweisungen
Felder und Zeiger
Funktionen
Strukturen
Deklarationen, Speicherklassen
Zunächst muss die gewünschte Datei geöffnet werden
➔
Funktion fopen aus der stdio.lib
Beim Öffnen der Datei muß angegeben werden, ob sie zum Lesen oder
zum Schreiben geöffnet werden soll
Modus, der der Funktion fopen als Parameter übergeben wird
➔
Ein- und Ausgabe
Sonstiges
Zum Lesen und Schreiben stehen in der stdio.lib verschiedene Funktionen
zur Verfügung
➔
Funktionen fgetc, fputc, fscanf, fprintf, ...
Abschließend muss die Datei wieder geschlossen werden
➔
Funktion fclose aus der stdio.lib
209
210
fopen
Mögliche Angaben zum Modus
FILE *fopen(const char *filename, const char *mode)
"r"
"w"
"a"
"rb"
"wb"
"ab"
Rückgabewert der Funktion ist FILE*, also ein Zeiger auf eine Struktur
namens FILE, die in der stdio.lib definiert ist.
Der Rückgabewert ist NULL, falls die Datei nicht geöffnet werden konnte.
Vom Programm aus kann nur über diesen Pointer auf die Datei
zugegriffen werden!
ASCII-Datei zum Lesen öffnen
ASCII-Datei zum Schreiben öffnen
ASCII-Datei zum Erweitern (Schreiben) öffnen
Binär-Datei zum Lesen öffnen
Binär-Datei zum Schreiben öffnen
Binär-Datei zum Erweitern (Schreiben) öffnen
Achtung!
Beim Schreiben mittels wird der alte Inhalt der Datei überschrieben!
Beim Schreiben mittels wird an das alte Datei-Ende angehängt.
filename ist der Name der zu öffnenden Datei, in der Notation des
jeweiligen Systems
(z.B. Unix: "/tmp/datei.dat", Windows: "C:\tmp\datei.dat")
Beide Modi erzeugen eine neue Datei, wenn es keine Datei des
angegebenen Namens gibt.
mode ist String, der den Modus der Operation bestimmt.
Es gibt weitere Modi.
Wir werden im folgenden nur ASCII-Dateien (Text-files) benutzen.
211
212
Zeichenorientiertes Lesen und Schreiben
fclose
int fgetc(FILE *f);
Liest nächstes Zeichen und liefert es als int-Wert (ASCII-Code!) zurück.
Am Dateiende wird EOF zurückgeliefert.
(EOF ist kein char, deshalb ist der Rückgabetyp der Funktion int)
int fclose(FILE *f);
int fputc(char c, FILE *f);
Schreibt Zeichen. Liefert den ASCII-Code des Zeichens als Rückgabewert
oder EOF bei Fehler.
Der FILE-Pointer f hat anschließend einen undefinierten Wert.
Schließt die Datei.
Liefert 0, falls kein Fehler auftrat.
char *fgets(char *s, int n, FILE *f);
Höchstens n-1 Zeichen werden aus einer Zeile eingelesen und mit
\0 abgeschlossen. Zurückgegeben werden diese Zeichen als String s oder
NULL, wenn das Lesen nicht erfolgreich war.
int fputs(const char *s, FILE *f);
Schreibt s in Datei. Liefert EOF bei Fehler, sonst nichtnegativen Wert.
213
214
Beispiel Datei1.c
Beispiel Datei2.c
// Datei2.c
// Datei1.c
// liest aus der Datei dat1.txt
// schreibt in die Datei dat1.txt
#include <stdio.h>
#include <stdio.h>
int main (int argc, char ** argv) {
int main (int argc, char ** argv) {
FILE *f_in;
int i;
char c;
FILE *f_out;
f_out = fopen("dat1.txt", "w");
// Erfolg von fopen sollte immer abgefragt werden
if (f_out != NULL) {
fputc('a', f_out);
fputs("bc", f_out);
}
f_in = fopen("dat1.txt", "r");
if (f_in != NULL)
do {
i = fgetc(f_in);
c = (char) i;
// Kontrollausgabe des gelesenen Zeichens
printf("i: %d c: %c\n", i, c);
}while(i != EOF);
fclose(f_out);
}
fclose(f_in);
}
215
216
Exkurs: Ausdrücke und Anweisungen
Ausdrücke als Anweisung
In C ist es aber auch erlaubt, einen Ausdruck als Anweisung zu formulieren.
Bisher haben wir deutlich unterschieden zwischen Ausdrücken und
Anweisungen.
Beispiele:
3*(sin(y) + 7);
printf();
Ausdrücke (logische oder arithmetische) werden ausgewertet und liefern
ein Resultat.
Logische Ausdrücke treten z.B. als Bedingungen in if-statements oder
Schleifen auf, arithmetische Ausdrücke z.B. als rechte Seite von
Wertzuweisungen:
if (i < 0) { };
x = 3*(sin(y) + 7);
Ein solcher Ausdruck wird ausgewertet und der Ergebniswert wird ignoriert.
Anweisungen werden ausgeführt und haben eine Wirkung.
Beispiele sind Wertzuweisung, if, Schleifen oder Funktionsaufrufe:
if (i < 0) { };
x = 3*(sin(y) + 7);
drucke(feld, n);
Beide Aufrufe sind sowohl Ausdruck als auch Anweisung, genauer:
Ausdrucksanweisung.
Die von uns definierte Funktion drucke(int[], int) war als Funktion mit
Rückgabetyp void definiert,
printf() ist aber eine Funktion der stdio.lib, die dort mit Rückgabetyp int
definiert ist.
Diesen Rückgabewert der Funktion haben wir bisher immer ignoriert.
Wieso ist printf(); ein Ausdruck?
Wieso haben wir eben drucke(feld, n); als Anweisung bezeichnet?
217
218
Zuweisung als Ausdruck
Anwendung
Die Wertzuweisung hat nicht nur eine Wirkung (belegt einen Speicherplatz
mit einem Wert), sondern liefert selbst einen Wert zurück (nämlich den Wert
des Ausdrucks der rechten Seite).
Dieser Wert kann dann in einem umfassenden Ausdruck verwendet werden:
if ( (i = n/4) > 0 ) {
if ( (i = n/4) > 0 ) {
};
// statt
Achtung!
i = n/4;
if ( i > 0 ) {
oder:
};
if( (iptr = (int*) malloc (8)) != NULL )
{*iptr = ...}
// statt
iptr = (int*) malloc (8);
if (iptr!= NULL)
{*iptr = ...}
};
ist nicht identisch mit
if ( i = (n/4 > 0) ) {
Beispiel:
};
Die Variable i wird mit dem Wert n/4 belegt, dieser Wert wird dann auf > 0
geprüft.
if ( (i = n/4) > 0 ) {
Durch diese doppelte Interpretation kann
die Zuweisung eines Funktionswertes an eine Variable und
die Abfrage dieses Wertes in einem Schritt zusammengefasst werden:
};
219
220
Ende des Exkurses
Beispiel Datei1a.c
// Datei1a.c
Viele Funktionen in C liefern einen Fehlercode als int-Ergebnis zurück und
verstecken die eigentliche Berechnung als „Nebeneffekt“.
// schreibt in die Datei dat1.txt
#include <stdio.h>
Beispiele: printf, scanf, fclose, fgetc, fputc, ...
Für solche Funktionen ist es üblich, den Aufruf mit der Fehlercodeabfrage
zu verknüpfen.
int main (int argc, char ** argv) {
FILE *f_out;
if ( (f_out = fopen("dat1.txt", "w")) != NULL) {
fputc('a', f_out);
fputs("bc", f_out);
}
-> folgende Beispiele
fclose(f_out);
}
221
Beispiel Datei2a.c
222
formatierte Ein- und Ausgabe
int fprintf(FILE *f, char *format, ...);
int fscanf(FILE *f, char *format, ...);
// Datei2a.c
// liest aus der Datei dat1.txt
werden genau wie printf und scanf benutzt, mit dem Unterschied, dass
der erste Parameter jeweils ein FILE-Pointer ist, der auf die Datei zeigt, in
die geschrieben, bzw. von der gelesen werden soll.
#include <stdio.h>
int main (int argc, char ** argv) {
FILE *f_in;
int i;
char c;
Rückgabewert ist bei fscanf und scanf die Anzahl der gelesenen Werte
(nicht Zeichen),
bei fprintf und printf die Anzahl der geschriebenen Zeichen.
if ( (f_in = fopen("dat1.txt", "r"))!= NULL )
while ( (i = fgetc(f_in)) != EOF ) {
c = (char) i;
// Kontrollausgabe des gelesenen Zeichens
printf("i: %d c: %c\n", i, c);
}
Der zweite Parameter ist die Formatangabe.
fclose(f_in);
}
223
Formatbezeichner
%d
%o
%x
%ld
%f
%e
%c
%s
%%
224
Übung
Integer dezimal mit Vorzeichen
Integer oktal ohne Vorzeichen
Integer hexadezimal ohne Vorzeichen
long int mit Vorzeichen
float oder double ohne Benutzung von Zehnerpotenzen
float oder double im Exponentionalformat
einzelnes Zeichen
String
das %-Zeichen
Aufgaben des dreizehnten Übungsblattes.
Auch Breite und Genauigkeit der Ausgabe können angegeben werden,
z.B.:
%6d
mindestens 6 Stellen, rechtsbündig
%12.3f insgesamt mindestens 12 Stellen (incl. Vorzeichen und
Dezimalpunkt), davon 3 Nachkommastellen
225
226
Herunterladen