Willkommen beim sechsten Teil des C-Kurses! |
Bisher hatten wir, recht erfolgreich, schon kleinere Programme geschrieben,
die schon recht ansehnlich waren. Doch sie hatten ein Manko: Die eingegebenen
Daten waren nach dem Beenden der Programme im Nirwana gelandet. Dem wollen
wir abhelfen, indem wir uns im 6. Teil mit dem Ein- und Ausgeben der Daten
in Dateien befassen.
Standardkanäle in C |
Kanäle ? Ich kenn nur Canale Grande.... C legt bei jedem Start
eines Programms drei fest definierte Ein- & Ausgabekanäle an.
Sie müssen nicht definiert werden! In der Regel werden diese Ein-,
Ausgabekanäle benutzt, um Datenumlenkungen zu ermöglichen. bsp.
wenn unter Dos die Ausgabe auf ein File umgelenkt
wird, wird das File zur Standardausgabe, bzw. wenn ein File als Eingabe
auf ein Programm gelenkt wird, wird dieses File zur Standardeingabe. Doch
schauen wir uns diese Drei Kanäle einmal genauer an. Die verwendeten
Befehle werden noch erläutert.
stdin |
Der Standardeingabekanal, er ist in der Regel die Tastatur
scanf ( ... ) |
ist also im Normalfall identisch mit
fscanf ( stdin, ... ) |
stdout |
Der Standardausgabekanal ist in der Regel der Bildschirm
printf ( ... ) |
ist also im Normalfall identisch mit
fprintf ( stdout , ... ) |
stderr |
Der Standardfehlerkanal. Hier werden die Fehlermeldungen zu Diagnosezwecken
ausgegeben. Dies geschieht in der Regel auch auf dem Bildschirm. Von praktischem
Nutzen wird das ganze, wenn der Standardausgabekanal nicht mehr der Bildschirm
ist und man trotzdem Feedback haben möchte.
fprintf ( stderr ,"Fehler aufgetreten in der Datei xyz.bat" ) |
Das Öffnen und Schließen einer Datei |
Für C ist eine Datei nichts anderes als eine Ansammlung von Zeichen,
unabhängig, was drin steht. Um mit einer Datei unter C zu arbeiten,
muß man sie "öffnen" und danach natürlich wieder "schließen".
/*
Beispiel zum schreiben eines Files #include <stdio.h> void main ( void )
neuer Variablentyp FILE ! Er enthält Informationen über das zu bearbeitende File! */ FILE *datei; datei = fopen ( "test.dat" , "w+" );
printf ("\nDie Datei konnte nicht geöffnet werden!\n"); else {
fprintf (datei, "Hallo, dies steht nun in der Datei !"); printf ("\nAlles OK!\n");
fclose (datei); |
Nach dem Start erscheint folgendes:
Ziemlich unspektakulär, aber schauen wir uns jetzt das File an. Wie wir sehen haben wir ein File mit Namen test.dat erzeugt, das folgenden Inhalt hat.
Schauen wir uns nun die Befehle an, die wir angewendet haben.
fopen |
Mittels fopen wird eine Datei geöffnet. Als Argument werden die
zu bearbeitende Datei und der Arbeitsmodus übergeben.
r | nur zum lesen öffnen, die Datei muß existieren |
w | nur zum schreiben öffnen, wenn eine Datei existiert wird sie vorher gelöscht |
a | nur zum anhängen öffnen, wenn keine Datei existiert, wird
sie angelegt
( die Fileendmarkierung EOF wird nicht gelöscht ) |
r+ | zum lesen und schreiben öffnen, die Datei muß existieren |
w+ | zum lesen und schreiben öffnen, wenn die Datei nicht existiert, wird sie erzeugt |
a+ | nur zum anhängen öffnen, wenn keine Datei existiert, wird
sie angelegt
( vor dem anhängen wird EOF gelöscht und am Endgeschriebene ) |
Zusätzlich zu diesen Arbeitsmodi kann man noch weitere Angaben
machen.
b | Binärmodus
alle Daten werden ohne Umwandlung in die Datei geschrieben |
t | Textmodus
einige Daten werden umgewandelt, so z.B. \n oder \r\n |
Wird keine Angabe gemacht, ob im Text- oder Binärmodus gearbeitet
wird, so wird defaultmäßig im Textmodus gearbeitet. Das oben
erwähnte EOF ( = End Of File ) dient dazu
das Ende eines Files zu markieren. Will man nun ein File zum lesen und
schreiben öffnen, welches im Binärmodus arbeteitet, so kann man
dies mit
fopen (datei, "w+b"); |
fclose |
Mit fclose können wir die Dateien, die wir mit fopen öffneten
wieder schließen.
fclose (datei); |
Hier werden die Schreibpuffer auf das Medium zurückgeschrieben
und die Verzeichniseinträge aktualisiert. datei ist vom Typ
*FILE und wurde mit fopen initialisiert!
Lesen und schreiben von Daten |
In den folgenden Beispielen ist datei immer eine mittels fopen
erzeugte
Variable vom Typ *FILE! (Zeiger auf den Typ FILE) , daher fangen
sie auch mit einem f an. Es können aber auch die Standardkanäle
zur gezielten Ein- und Ausgabe benutzt werden. Beispiele für den Sinn
und Nutzen der Kanäle wird es bei
putc()
und getc() geben.
fscanf |
Der Befehl verhält sich genau wie scanf
- mit nur einem Unterschied, hier wird angegeben woher die Information
kommen soll. Wo in der allg. Form Punkte stehen, sind die Variablenadressen
aufzulisten.
fscanf ( FILE* , char* , ... ); |
fscanf ( datei , "%c", &zeichen); |
Wenn wir also folgendes schreiben, so wäre dies equivalent zu einem
scanf
(...)
fscanf (stdin , "%c", &zeichen ); |
Der einzige Unterschied: Hier wird von einer Datei gelesen. Die Variable
zeichen
ist vom Typ char.Analog kann man hier auch andere Zeichen einlesen. Wie
an
fprintf |
Und hier kann man ahnen was folgt. Analog zu printf
dient dieser Befel zur Datenausgabe.Hier müssen zwei Argumente Übergeben
werden, einmal die Datei oder der Ausgabekanal in der Form
fprintf ( FILE * datei, char *zeichen, ...); |
Sei wie in unserem vorangegangenem Beispiel datei eine geöffnete
Datei, so kann man in sie mit dem folgenden Befehlen beispielsweise schreiben
fprintf ( datei , "\nHallo - Das File ist geöffnet :-)\n\n"); |
fprintf ( datei , "\nZahl = %d" , zahl); |
Wie sieht, sind die Ausgaberegeln bis auf die zusätzliche Angabe
des Ausgabemediums mit printf identisch. Wenn wir die Standardkanäle
benutzen kann man statt der Bildschirmausgabe auch folgendes schreiben,
was equivalent zu printf("...")ist.
fprintf (stdout, "\nHallo - Das File ist geöffnet :-)\n\n" ); |
getc und putc |
Vielleicht erinnert sich noch jemand an getchar
und putchar ? Mit diesen Funktionen hatte man die Möglichkeit
Zeichen einzeln einzulesen und auszugeben.Wie wir schon sahen, gibt es
analoge Befehle zu printf und scanf, die auf Files, bzw.
Kanäle bezogen sind. Folglich sollte es auch analoge Befehle zu putchar
und getchar geben Voila, hier sind sie.
char putc (char zeichen, FILE *datei ) |
Analog zu putchar
liefert als Rückgabe entweder das übergebene Zeichen oder ein
EOF
zurück und haben die gleiche Bedeutung. Bei einem Fehler beim Ausgeben
des Zeichen wird EOF zurückgeliefert, ansonsten das übergebene
Zeichen selbst.
char getc (FILE * datei ) |
Analog zu getchar
wird hier das Zeichen aus dem File gelesen. Auch hier gilt, das bei einem
aufgetretenen Fehler der Übergabewert EOF ist. Ein Beispiel,
wie man putc und getc anwendet wird nach den
Beispielprogramm zu fprintf |
So, jetzt können wir schon eine ganze Menge anfangen. Das untere
Programm einfach mal ausprobieren und sich das erzeugte File anschauen.
Testen Sie den Unterschied zwischen Text- und Binärmodus!
/*
Beispiel zum schreiben eines Files*/ #include <stdio.h> void main ( void )
datei = fopen ( "test.dat" , "w+" ); if (datei == NULL )
else {
fprintf (datei, "\nUnsere erste Datei :-)\n\n");
printf ("\n...und die Datei ist wieder zu\n"); fclose (datei); |
Beispielsweise erscheint nach dem Start, wenn alles glatt lief
und in der Datei test.dat sollte folgendes stehen
Schauen sie sich nun die Datei einmal an, wenn sie zum öffnen
fopen (datei, "w+b"); |
benutzt haben, dann sieht die Datei gleich anders aus.
Textdatei erstellen mit putchar und getchar |
Wie wir die Daten in einem File abspeichern, haben wir nun geübt.
Wenden wir uns nun einem Minimaleditor zu. Am Anfang werden wir abfragen,
wie die Datei denn überhaupt heißen soll, die wir erstellen
wollen. Der Dateiname darf dabei maximal 24 Buchstaben groß sein.
Das 25te Zeichen ist dabei das \0 , wie wir schon im Kapitel
über Textfelder lernten.
/*
Beispiel eines Minimaleditors*/ #include <stdio.h> void main ( void )
char dateiname[25]; char zeichen; char abbruch = '#'; printf ("\nBitte Dateinamen angeben : ");
datei = fopen ( dateiname , "w+" ); if (datei == NULL )
else {
while (( zeichen = getchar()) != abbruch ) putc (datei,zeichen); printf ("\n\nDanke, das sie mich benutzten\n\n"); fclose (datei); |
Nachdem wir unser Programm starteten, wählen wir als Beispielnamen beispiel.dat und tippen ein bischen darauf los. Nachdem wir die Eingabe mit # beendeten sind wir natürlich auch neugierig, ob alles abgespeichert wurde, wie wir es wollten. Schauen wir nach.
Jetzt benötigen wir noch ein Programm, womit wir Textdateien auf
dem Bildschirm ausgeben können. Dies geht recht fix, wie wir an folgendem
Beispiel sehen werden. Wie zuvor werden wir den Dateinamen der Datei abfragen,
die wir darstellen wollen. Schauen wir uns doch gleich mal das File an,
welches wir mit dem vorigen Programm geschrieben haben.
/*
Beispiel von lesen eines Files und dem Ausgebem*/ #include <stdio.h> void main ( void )
char dateiname[25]; char zeichen; char abbruch = '#'; printf ("\nBitte Dateinamen angeben : ");
datei = fopen ( dateiname , "r" ); if (datei == NULL )
else {
fclose (datei); printf ("\n\nDanke, das sie mich benutzten\n\n"); |
Mit diesem Programm können wir, da wir putc benutzen, die
Ausgabe einfach in ein File umleiten.
Textdatei erstellen mit Standardkanälen |
/*
Beispiel der Ein- und Ausgabe mittels Standardkanälen*/ #include <stdio.h> void main ( void )
char abbruch = '#'; while (( zeichen = getc(stdin)) != abbruch ) putc (zeichen, stdout); |
Starten wir das Programm und probieren aus, auf diesem Weg alles, was wir auf der Tastaur eingeben, in ein File zu schreiben, bis wir # eingeben. Auf diese weise sollte wir, ähnlich den vorigen Programmen, recht einfach eine Textdatei erstellen können. Das Programm wurde in diesem Beispiel kanal.c benannt und der Name der ausführbaren Datei ist kanal.exe . Das zu erzeugende File wurde stdout.txt genannt.
Nachdem ein bischen Text eingegeben wurde, sollte nun der Text in der Datei stdout.txt stehen, da die Ausgabe dorthin umgeleitet wurde. Schauen wir es uns mit einem Editor an. Wie zu sehen ist, machte das Programm was wir uns vorher überlegten. Da das # unsere Abbruchbedingung ist, wurde es nicht mehr abgespeichert.
Üben wir ein bischen, den Umgang mit den Ein- und Ausgabekanälen
ein bischen. In der Einleitung zu den Kanälen wurde erwähnt,
das z.B. durch Umlenkung Files als Ein- und Ausgabekanal gesetzt werden
können. Doch wie sieht dies nun im Detail aus ? Im Prinzip haben wir
das gerade gemacht.
kanal.exe > stdout.txt |
Hier wird beispielsweise das File stdout.txt zur Standardausgabe.
Schreiben wir nun ein Programm, welches die Standardeingabe stdin
nimmt, und sie in Großbuchstaben umwandelt und anschließend
auf der Standardausgabe
stdout ausgibt. Wie wir sehen, zeigt stdin
auf stdout.txt. Die Funktionen toupper
zum umwandeln der Zeichen in Großbuchstaben finden wir in
ctype.h .Zum testen nehmen wir das soeben erzeugte File stdout.txt.
/*
Beispiel der Ein- und Ausgabe mittels Standardkanälen*/ #include <stdio.h> #include <ctype.h> void main ( void )
char abbruch = EOF; while (( zeichen = getc(stdin)) != abbruch ) putc (toupper(zeichen), stdout); |
...das Obligatorische |
Autor: Sebastian Cyris \ PCD Bascht
Dieser C-Kurs dient nur zu Lehrzwecken! Eine Vervielfältigung ist ohne vorherige Absprache mit dem Autor verboten! Die verwendete Software unterliegt der GPL und unterliegt der Software beiliegenden Bestimmungen zu deren Nutzung! Jede weitere Lizenzbestimmung die der benutzten Software beiliegt, ist zu beachten!