Sie sind auf Seite 1von 6

void schreiben(void)

FILE *fhd:
char sIIIAXZEILENLAENGE];

File-Handling

f h d - f o p e n ( D A T N A M "Ew, " ) ;
if(!fhd)

Kommen wir nun zu einem weiteren Aspekt der Ein- und Ausgabe, dem ,,File Handling". Unter File Handling versteht man das Speichern von Daten in und das Laden
von Daten aus Dateim. Fangen wir mit den gnrndlegenden Funktionen an.

printf('Datei
I
el se

fopen und fdose

Die Funktionen, die eine Datei ffnen und sdrlieen, heien fopen und fclose. Ihre
Prototypen sowie die Prototypen der anderen File-.Handling-Funktioneru
die wir in
diesem Kapitel kennenlemen werden, stehen in der Headerdatei stdio.h.

p r i n t f ( " B i t t e m a x i m a lX i Z e i c h e n p r o Z e i l e e i n g e b e n . \ n , ,
MAXZEILENLAENGE):
printf("Eingabe wird mit
beendet.\n\n');
do
I
printf(')");
gets( s );
i f ( s t r c m p s( , " . ' ) )

fopen und fcbse haben das folgende Format


f i 1e p t r - f o p e n ( d a t e i n a m e . m o d u s ;)

:
fclose(fileptr^);

fputs ( s, fhd);
fputs("\n',fhd);

fleptr ist ein Zeiger auf eine FILE-Struktur. ,,File" heit auf deutsch ,,Datei". Er wird
wie folgt definiert:
F I L E* f i l e p t r ;

"
l w h i l e ( s t r c m D ( s , ' .) ) :

Die File'Stnrktur wird durch den Aufruf von fopen erzeugt und mit /close wieder ge.
lscht. Sie enthlt alle charakteristischen Informationen ber die geffnete Datei und
ist eindeutig, Sie knnen daher mit mehreren/opcz-Aufrufen
mehrere FllE-Strukturen
erzeuterL und damit mehrere Dateien ffnen. H.at flqtr
nach dem AuJruf von fopen
den Wert Q konnte die Datei nicht geffnet werden. Die Prototypen von fopen vnd fclose,sowie die Deklaration von FILE stehen in der Headerdatei stilio.h.Der Name der Datei wird mit einer Stringkorstante dateineme angegeben. Die Regeln der Dateinamenvergalre hngen von Ihrem Computersystem ab. modus ist ebenfalls eine Stringkonnte und gibt den Modus der zu ffnenden Datei an. Die Modi entscheiden ber das
\'ormat der Datei (Iextdatei oder Binrdatei) und darbeq ob gelesen oder geschrieben
werden kann oder soll.

f c l o s e (f h d ) :
p r i n t f ( " \ n E i n g a b e b e e n d e t! \ n ' ) ;
I
l
void lesen(void)
I
F IL E * f h d ;
c h ar s ' I A X Z ELIE N L A E N G; E I
i nt x-l;

en
Beschftigen wir uns zuerst mit den Tixtdateien
zur Verfgung:
Modus
r

f h d - f o p e n ( D A T N A M E . ' r)";
if( !fhd)

fopen stellt uns dafLr folgende Modi

{
pnintf('Datei konntenicht geoeffnet werdent\n\n'):
I
el se

aschreibung-::11:..{.::it,
ffnet eine Textdatei

zum Lesen.

erstellt eine Textdatei zum Schreiben. Der Inhalt einer bereits


unter diesem Namm existierenden Datei wird gelscht.
a

"a+"

konnte nicht erzeugt werden!\n\n');

erstellt eine Textdatei zum Lesen und Sdueiben. Der lnhalt einer
Datei wird gelscht.
bereits unter diesem Nasren existierenden

printf("Die Datei hat folgendenInhalt:\n"):


f s e t s ( s , M A X ZI EL E N L A E N Gf hEd, ) :
oo
I
p r i n t f ( ' X i : 1 s ' . x + . r , s) ;
f g e t s ( s . M A X Z ELIE N L A E N Gf hEd, ) ;
l while(!feof(fhd)):

erstellt oder ftret eine bereits existierende Textdatei zum Lesen


und Schreiben. Der Dateipositionszeiger steht am Ende der
Datel dadurch werdm neue Daten hinten angehngt.

fclose(fhd);
p r i n t f ( " \ n E n d e d e n D a t e i! \ n ' ) ;

erstellt oder ffnet eine bereits existierende Textdatei zum


Schreiben. Der Dateipositionszeiger steht am Ende der Datei,
dadurch werden neue Datm hinten angehn6.

I
Tabelle23.7:Die Dateimodifr Textdateien

Wollen wir z.B. eine Textdatei narnens ,,test.t(t" zum Schr,eibenffneru gehen wir folgendermaen vor:

void main(void)

f i I e p t r - f o p e n( ' t e s t . t x t ' . ' w " ) ;

i nt i nput:

aie Datei wird ins aktuelle Verzeiduris geschrieben. Welches Verzeidrnis das aktuelle ist
ngt von lhrcm Compiler und von dem Pfad ab, in dem sich der Compiler befindet.

printf('Soll
die Datei l-gelesen oder Z'beschriebenwerden?.):
scanf("Zi',&input);

fputs, ftets und feof

i f( i nout:-l )

Schauen wA uns riun die einfasten Funktionen zum Lesen und Schreiben von Text in
Dateien aru nmlich fputs und fgetc. Diese Funktionm sind mit pufs und gefs fr die normale Ein- und Ausgabe identisdu auer da zustzlidr noch ein 7*iger aul die FILEStruktur des zu lesenderr oder beschreibenden Files und ber fgets noch die Anzahl der
maximal einzulesenden Zeichen mit angegeben werden mssen. Des weiteren wind im
folgenden Beispiel die Funktion feof benutzt. feof "trr.d folgerrdermaen aufgenrfen:

lesenO:
I
else
l
if(input*2)
I

wert-feof( fi l eptr ) ;

s c h p e i b e n )( :

Abhlingig davorl ob das Ende der Datei erreicht ist oder nichg ist zrert entweder
,,Wahr" oder,,Falsch". Und hier das Beispiel:
/linclude (stdio.h)
/li ncl ude <stri ng. h>

I
else

/ * P R G 2 3 - 0 1 .*C/

'test.
txt"
lldefi ne DATNAME
l l d e f i n e M A X Z E I L E N L A E N1G6E0

p r i n t f ( " \ n F al s c h e E i n g a b e \! n \ n . ) ;

I
I
I
ln der raain-Funktion liest die scanl-Anweisung eine Zalrt ein. Der Benutzer beendet
die Eingabe duch Drcken der Retum-Taste. Es kann auf manchen Rechnem vorkommeru da die Bettigung der Return-Tste im Tastaturpuffer bteibt. Bemerkbar macht
sich dies, wenn nach dem start des obigen Programms in der ersten Zeile zwei Eingabeaufforderungen stehen und bei der Textausgabe Ihr Text einer ersten Leerzeite folgt.
Wenn dies der Fall ist, fgen Sie hinter scazlbitte folgende Anweisung einl:
I

Dies fiegt an der Eigensdtaft bestimmter Systeme, ei^ caftiage-return und ein line-feed zu senden.

g e t c h a r () ;

"
f s c a n ( f h d , ' X s X s l s % s X s % s X s l i s, s 1 , s 2 , s 3 , s 4 , s 5 , s 6 , s 7 , & x , s B ) ;

auf die Eingabe eines Zeichens. Da wir aber wissery da an dieser Stelle
gglg$wartet
im Programm noch ein CR (carriage return) im Tstaturpuffer gespeichert ist, wird die'
ses eingelesen
Zu Anfang wurden zwei Makros definiert, einmal fr die maximale Zeilenllinge
Ein- und Ausgabe des Textes und einmal fr derr Dateinamen. Der Vorteil dieser
kros ist de4 da man bei einer Anderung des Dateinamens oder der Zeilenlnge
eine Stelle im Programm verndern mu, nmlich das Makro, und das ganze
grarnm pat sich dieser Anderung an.

der
Manur
Pro-

Die main-Funktion brauchen wir nicht zu besprechen, denn Sie ist ziemlich trivial. Gehen wir daher direkt zur Funktion schreiben ber.
Zuerst werden ein 7*iger auf eine FILE-Struktur namens llrd und ein String namens s
definiert, der die Eingabe aufnehmen soll. Dann wird die Datei zum fthreiben geffnet- Sollte sie schon existiereo wird ihr Inhatt gelscht. Es wird berprft, obld falsch
ist (!fhd). lhd ist dann falsdr" wenn er den Wert 0 hat, und das bedeutet, da die Datei
nicht geffnet werden konnte. Fr diesen Fall wird eine entsprecJrende Meldung ausgegeberu Sollteld wah4, also ungleich null sein, ist die Datei ordnungsgem geffnet
und zum Schreiben bereit.
Innerhalb der do-Schleife luft die eigentliche Eingabe ber Tstatur und Ausgabe in
die Datei ab. Die Vereinbarung im Programm lautet, da die Eingabe abgebrochen
wird, wenn h einer Zeile nichts weiter steht als ein Punkt in der ersten Spdte. Zuerst
wird das eigene Prompt ausgegeben und mit gefs ein Strint eingelesery der in s tesPeichert wird. Dann wird berprft, ob die Zeile nur aus einem Punkt besteht. Wenn ia,
wird sie niclt in die Datei geschriebery denn der Punkt ist unsere Endekennunt. Ansonsten wird die eingegebene 7*ile mit fuuts in die Datei geschrieben und durch ein
zweites fVuts mit CR ergnzt. Dies ist notwendig, weil gets das Drcken der Returntaste als Abschlu der Eingabe nicht im String gespeichert hat. Dann wird die do'Schleife
gesdrlossery wobei sie so lange wiederholt wird, wie s nicht nur aus einem Punkt besteht. Sollte unsere Abbruchbedingung erfllt sein, ist die Eingabe kompleft beendet
und die Schleife wird verlassen. Zum ftttlu wird mitfctose die Datei geschlossen und
eine entsprechende Meldung ausgegeben.
Und nun die Funktion lesen.Sie definiert die gleichen Variablen wie schreiben und zustzlich aber noch eine inFVariable r, die fr das Zhlen der Zeilen benutzt wird. Danach wird eine Datei zum Lesen geffnet und anschlieend berprft, ob dies auch
ordnungsgem geschah. Fr die Eingabedatei wird der gleiche Name benutzt wie fr
die Ausgabedatei. Gehen wir nun zur dc'Sclleife. Der Aufbau sieht etwas umstndlich
Das Dateiende'Flag wird nicht
aus, wenn man nicht die Besonderheit vonfolkennt.
g*tz!
wenn das Dateiende erreicht ist, sondern erst danrL wenn versucht wird, wei-

Sie sind vielleicht berrascht, aber wenn Sie sidr an das Kapitel 4 ber scanlerinnern,
wissen Sie, da fr die scary'-Funktion zwei Eingaben duldr ein Leerzeichen tetrennt
werden. Deswegen mssen alle Wrter in einzelne Strings eingelesen werden. Es lieg
dann an lhnen, die Wrter links von der Zahl wieder zu einem String zusammenzufaswelches die
sen. Schreiben Sie einmal aus dem Handgelenk ein Progranmfragment,
Strings sl bis sZ zu einem String narnens sf zusammenfat. Erst denkeru dann weiterlesen!
strcpy(st,sl):
strcat(st,sZ):
s t r c a t ( s t , s 3) ;
s t r c a t ( s t , s 4) ;
strcat(st.s5);
strcat(st,s6);
s t r c a t ( s t . s 7) .
Der erste String wd mit strqy in den String sf kopiert, weil dies einer lnitialisierung
gleichkommt. Htten wir den ersten String mit sfrcat an sf angehngt, wre ein eventuell vorhandender alter Inhdt des String sf nicht berschrieben worderl sondem bliebe
erhalten. Das soll aber nicht sein.
f8etc und fputc
So wie die Funktionen gefs und/puts Strings lesen und schreibe4 gibt es auch Funktioneru die ein einzelnes Zeichen aus einer Datei lesen oder in eine Datei schreiben. Die
Funktionen heien fgetc und fputc. Mit
fputc(zei.fhd);
wd das in der Variablen zei gespeicherte Zeichen in die Datei die der FILE-Struktur
fttil zugeordnet ist, geschrieben. fputc liefert den Wert von za' zurch wenn alles in
Ordnung ist, ansonsten wird der Wert EOF zurckgegeben. EOF ist ein in der Headerdatei stdio.h definiertes Mako. Sie knnen es folgendermaen benutzen:
wert:foutc(zei . fhd);
i f(wert--EOF)
p r i n t f ( " F e h l e r b e i m S c h r e i b e n! \ n ' ) :
Das ksen eines Zeichens funktioniert

Danach enthlt die Variable zai das gelesene Zeichen.

tere Daten zu leseru obwohl das Dateiende erreicht ist. Dies bedeutet, da ein Lrseversuch fehlsdrlagen mu, bevor/eo/einen wahren Wert liefert.

Es mu erwhnt werdery da die da'Schleife nur dann einwandfiei luft, wenn die Datei mindestens eine Zeile enthlt. Um den Fall einer leeren Datei abzufangerl mte
die do-sdrleife noch in eine if-I+bfrage gepackt werden:
f g e t s ( s , M A X Z ELIE N L A E N Gf hEd, ) ;
i f( !feof( fhd))
t
clo

{
Printf('ti :Xs",x+,s );
f hTd. ) ;
f g e t s ( s , M A X ZITL E N L A E N G
l'while(lfeof(fhd));

.2

- -..

und fscan

ffnet eine Binrdatei

"wb"

auf den Bildschirm bringt, sdueibt


" D a s } { o r t h e i t 1 s u n d b e s t e h t a u s Z i E u c h s t a b e n " ,w o '
fpnintf(fhd,
s t r ' l e n ( w o )) ;
in die Datei die der FILE-Struktur ftd zugeordnet ist. Analog dazu funktioniert die
ltcan-Funktion. Anstatt die Eingaben von der Tastatur zu holen, holt sie sich die Daten
aus einer Datei:

. l,',''

zum Lesen

erstellt eine Binrdatei zum Schreiben. Der Inhalt einer bereits


unter diesem Namen existierenden Datei wird gelsdrt.
erstellt oder ffrret eine bereits existierende Binrdatei zum
Schreiben. Der Dateipositionszeiger steht am Ende der Datei,
dadurch werden neue Daten hinten angehngt.

"rb+"

ffnet eine Binrdatei

zum l"esen und Sreiben

"wbt"

erstellt eine Binrdatei zum l.esen und Schreiben. Der Inhalt


einer bereits unter diesem Namen o<istierenden Datei wird
gelst.

"ab+"

erstellt oder ffnet eine bereits existierende Binrdatei zurn


ksen und Sch,eiben. Der Dateipositionszeiger steht am Ende
der Datei, dadurch werden neue Daten hinten angehing.

Es gibt noc-h weitere Funktion zur Bearbeitung von Textdateien. Die komfortabelsten
heien fptirr und fscan. Ihre Funktioruweise ist identisch mit prinf und scanf.Detr
Texg den zuur Beispiel
p r i n t f ( ' D a s l l o r t h e i t X s u n d b e s t e h t a u s 1 i B u c h s t a b e n " ,w o ,
strlen(wo)):

:'.i.t.-.

-l'+il .,J jli:Ia ,' ,'$i

"rb'

"ab"

fprintf

tei

Die Dateiforrn, die wir bisher behandelt haben, war die Textdatei. Textdateien knnen
ohne Probleme in einen Texteditor geladen und dort betrachtet werdm. Die CQuellprogtamrne, die Sie gespeichert haberu sind im allgemeinen auch Textdateien. Nun ist
es aber oft vorteilhafteq, den lnhalt einer Variablen nicht als geschdebene ZahL sondern
direkt den Inhalt der Bytes, die ese Variable reprsentiere4 zu speichern. Erstens kostet dies meist weniger Speicherplatz und das umstndlicle Zurckwandeln des Textes in Zahlvariablen mittelsf can enIlt. fopez bietet uns verschiedene Mglichkeitery
eine Binrdatei zu ffnen:

tciose(fhd):
Wie Sie am vorherigen Beispiel sehen knnen, positionieren die Funktionery die in einer Datei teseru den Dateipositionszeiger immer hinter das zuletzt gelesene ZeicherV
wohingegen die Ftrnktioneru die in eine Datei sdueiben den Dateipositionszeiger immer hinter das zulebt geschriebene Zeichen setzn.

hnlich:

zei:fgetc(fhd):

Tabelle23.2: Dic Datcimodifr Binrilateicn


Fr die letzten drei Modi gibt es noch eine andere Sclu,eibweise, die hier aber nidrt erwhnt zu werden braucht. Die Tbelle der Dateimodi im Anhang ist iedoch vollstndig.
fwrite

und fread

Es gibt zwei Hauptfunktionen fr Binrdateien Die eine heit fwrite, und schreibt in
eine Binrdatei, whrend die andere aus einer Binrdatei liest und fread heit. ftun'te
wird folgendermaen aufgerufen:

fscan(fhd."ti Xs",x,s);

a n z - f w r i t e ( a d n e s s e .g r o e s s e ,a n z a h l. f h d ) ;

fprintf und lscan haben auch sehr viel Almlichkeiten mit den Funktionen sprinfl und
sscanf, die in Strings schrciben und aus ihnen lesen. Versuchen Sie einmal fr den obe'
zu entwerferl der die Zeile wieder
den entsprechendenl$ccn-Aufruf
renfpintf-Aufruf
einliest.

adresserst die Adresse, an der die zu speichemde Variable oder das zu speiernde
Feld steht. groesseist die Gre der Variablen oder eines Feldelemmts in Bytes. anzalrt
ist die Anzahl der Feldelemente. anzahl ist bei der Speichenrng einer normalen Variablen gleich l.fldist der Zeiger auf die FILE-Struktu4 mit der die zu besclueibende Datei verknpft ist. fwrite gibt die Anzahl der komplett geschriebenen Elemente zurck.
lihntich sieht der Aufruf von-fead aus:
a n z - f r e a d (a d r e s s e ,g r o e s s e .a n z a h l , f h d ) ;
Wobei adressedie Adlesse ist an der die aus der Datei gelesenen Daten gespeichert
werden. Die anderen Parameter entspreen denen von/zrrite. l,;.tchfrean gibt die AnzaN der komplett gelesenen Elemente wieder. Tritt z.B. beim Lesen des vierten Ele'
mentes ein Fehler auf, dann gibtfread den Wert 3 zur&

sizeof
Die Funktionen bergen jedoch'im Augenblick ftir uns noch ein Problem: AngenommerL wir wollen eine inFVariable speichern. Woher wissen wiq wieviel Bytes ein infWert gro ist, denn die Werte knnen sich von System zu System unterscheiden. ln C
wurde daher ein GrenbestimmungsoPerator implementiert, der die Gre eines ie'
den Variablentyps und einer ieden Variablen bestimmen kann. Der Grenbestimmungsoperator heit in C sizeof, was von den englischen Wrtern .size of" kommt
und auf Deutsch ,,Gre von" heit. Der Operator wird folgendermaen benutzt:
si zeof x
Hier wird die Gre der Variablen r in Bytes bestimmt. Man sollte sich angewhnery
die Variable, auf die sich sizzolbezieht, immer zu klammern, denn das erhht die l-Ibersitlichkeit. PassenSie aber auf:
char s[80]:
s t r c p y (s . ' T e s t ' ) ;
p l i n t f ( " D ie G r B ev o n s i s t Z i \ n ' , s i z e o f ( s ) ) ;
Was, glauben Sie wfud fr die Gre von s ausgegeben? Es wird 80 ausgegeberg weil
sich sizaof nicht um den lnhdt einer Variablen oder eines Feldes kmmert, sondern um
deren oder dessen Definition. Da s als ein Feld mit 80 char-Elementen definiert wurde
und ein char-Element ein Byte gro ist, kommt als Ergebnis 80 heraus. Wie oben schon
erwhnq kann sizeol nicht nur die Gre einer Variablery sondem auch eines Variablentyps bestinunen:
printf("Der Variablentypint ist ti

Bytes groB'\n',s'izeof(int));

Diese Zeile gibt die Gre des Variablentyps inf aus. Nachdem wir dies nun wissen,
schauen wir uns ein Beispiel an:
/linclude (stdi o. h)
/fincl ude (str^i ng.h)

l*

"test. txt'
/ f d e fi n e D A T N A M E
2 5E
lldefine MAXV0RNAM
l l d e f i n e M A X N A C H N A2M0E
v o i d s c h r e i b e n (v o i d )
I

FILE*fhd:
, eIMAXNACHNAME]:
c h a r v n a m e I M A X V O R N A nMnEa]m
u n s ' i g n e di n t a l t e r . g r o e s s e :

pri ntf('Datei

k o n n t e n i c h t e r z e u g t w e r d e n! \ n \ n " ) ;

I
el se

printf('Vorname (Max. Xi Zeichen) :"'MAXV0RNAME-1):


scanf('Us",vname):
printf('Nachname(Max'XiZeichen):"MAXNACHNAME-1):
scanf('Xs",nname);
:'):
printf("Alter in Jahren
scanf("gu"&alter);
printf("Groesse'in Zentimetern
scanf("3u"&groesse);

:");

fclose(fhd);
" \ n E i n g a b e b e e n d e t !\ n ' ) ;
Pri ntf (
l
I
void lesen(void)
I
FILE *fhd:
v n a m e I M A X V 0 R N A M E ]n' n a m e I M A X N A C H N A M E I ;

unsigned int

alter'groesse:

f h d - f o p e n ( D A T N A H E , 'r b ' ) :
if( !fhd)
I
printf("Datei

konnte

) ,1,fhd);
f w r i t e ( n n a m es. i z e o f ( n n a m e
Wenn jemand das Programm spter liest, kann er daran aber erkennet! ob der Programmierer einen String, wie im ersten Fall, oder ein Feld von char-Elementery wie im
zweiten Fal| abspeichert. Denn es kann manchmal ntzlich seiru ein Feld von clrar-Elementen nicht als String zu betrad'rten. Derienige, der das Programm verstehen mu,
erkerurt dann aber, was der Programmierer vorhatte. Deswegen sollten Sie sich genau
berlegen" welche Bedeutung Sie einer Variablen geben wollen.
Die vierte Anweisung be'
Die dritte Ttorife-Anweistrnt ist nicht erklrungsbedrftig.
nutzt fr den siz-eofoperator nicht den Variablennamery sondern den Typ der Variablen. Dies ist mglidr" aber nicht elegant. Denn sollten Sie in der Definition der Variablen eine Typnderung vornehmerL mssen Sie dies auch in derfnrite-Anweisung machen. Lassen Sie aber die Lnge ber den Variablennamen bestimmeru wie in der dritten Anweisung, dannbleibt Ihnen die Anderung der fwrtte-Anweisung erspart.
Konstanten als Makros zu
sie sollten sich angewhnen alle im Programm benutzten
ndern wollerL ndem sie
definiereru wenn sie eine Konstante irgendwann einmal
wirksam' Haben Sie je'
nur das Makro, und die Anderung ist im ganzen Programm
ganze Programm durchforstery
doch die Konstante direkt angegeben, mssen sie das
langen Programmen sehr
um alle Vorkommnisse det K-oist"nt t zu finderu was bei
mhsam sein kann.
mte ohne weiteres verDie Funktion lescz mu nicht besProchen werder\ denn sie
stndlich sein.

nicht

erzeugt

die ein Feld mit lfi)fi)O infst"tt"n ri" sich folgendes Problem vor: sie haben eine Datei,
nadrdem sie die
werten enthlt. wenn sie jetzt den 8)c[. wert brauchm, milssen sie,
um an die PositiDatei geffnet haben, zuerst die 7999rerte, die davor stehery lese&
Dies liee sictr vermeiden, wenn es die Mglidrkeit gbe, nach dem
or, "rrt*"n.
Element zu setzen und
ffrren der Datei den Dateipositionszeiger direkt auf das 80000.
fr Binrdateien'
nur dieses dann zu lesen. nd diese Mglichkeit gibt es, zumindest
fsetpos
die dem Dateipositionszeiger
6-ie F-tior!
Sie wird folgendermaen aufgerufen:

werden!\n\n");

e lse

{
f r e a d ( v n a m e s. i z e o f ( v n a m e) . 1 . f h d ) ;
f r e a d ( n n a m es, i z e o f ( n n a m )e ' 1 ' f h d ) ;
f r e a d ( & a1t e r , s i z e o f ( a l t e r ) ' 1 ' f h d ) I
f r e a d ( & g r o e s s e , szi e o f ( g r o e s s e ) ' 1 ' f h d ) ;

fpos-t Position;

erfolgDie Variable a enthlt den Wert Q wenn das Setzm des Dateipositionszeigers
position nicht vern."i.h *"r. Bitte beachten Sie, da, obwohl der Wert der Variablen
au da an dieser
dert wird, deren Adresse bergeben werden mu. Dies bedeutet
ist ein selbstde'
Stelle keine Konstante benutzt-werden kann. Der Variablentyp ircs-t
von C' Wie man
klarierter Variablentyp und zhlt nicht zu den Grundvariablentypen
deklarieren kanru temen wir in einem spteren KaPitel. fsetpos
eigene Variabl""typ"
an' Die GrundlOlcht auch das Dateiende-Flag. Doch schauen wir uns nun ein Beispiel
i"t" a* folgenden Funktion iit ale Eunttionlesen aus dem Programm,,PRG2342..".
gepeidrerten Daten
Di-e Funktio:n wurde so umgendert, da von den mit sdreiban
setzen sie diese am
nur noch die Gre eingelesen wird. um die Funktion auszutesterL
bestm ftir die Funktion lesez aus dem vorherigen Beispiel ein'
/ * P R G 2 3 - 0 3 ' *C/
void lesen2(void)
t
FILE *fhd;
I M A X N A C H N A;M E ]
' nEn a m e
c h ar v n a m eI M A x V O R N A] M
u n si g n e d i n t a l t e r , g r o e s s e ;
fpos-t skiP:
f h d - f o o e n ( D A T N A M Er,b' ' ) ;
i f( !fhd)

{
ori ntf('Datei
I
el se

fclose(fhd):
"Vorname

pri ntf(
printf('Nachname
orintf ('Alteli n Jahren
printf('Groesse in cm

:
:
:
:

einen neuen Wert zuweist, heit fsetpos.

a - f s e t p o s ( f h d ' & P o s it i o n )

' ' fhd);


f w r i t e ( v n a m e , si z e o f ( v n a m e ) 1
hE
d )' :
f w r i t e ( n n a m e s. i z e o f ( c h ar ) ' M A X N A C H N Af M
f w r i t e ( & al t e r , s i z e o f ( a l t e r ) ' 1 ' f h d ) ;
f w r i t e ( & g r o e s s e , s i z e o( fu n s ig n e d i n t ) ' 1 ' f h d ) ;

char

h dE ), ;
f w r i t e ( n n a m e s, i z e o f ( c h a r ) , M A X N A C H N AfM

23.g Verndern des Dateipositionszeigers

f h d - f o P e n( D A T N A M E , ' w )b;'
if(!fhd)

Fangen wir mit der Funktio^ sehreibenan. Das ffnen der Datei unterscheidet sich - bis
auf den anderen Modus - nicht vom vorherigen Beispiel. Das Einlesen der Daten ist
auch nichts Neues. Beim Einlesen der Strings wird die maximale AnzaN der mglichen Eingabezeichen mit FeWgrp-l angegeben. Das liegt daran, da ein Feldeintrag
ftir die Endekennung frei bleiben mu. Der ersten fwrite'Anweisung werden die
Adresse des Strings oname, die Gnie des Feldes, die Anzahl der Elemente und der
Name der Datei, in die geschrieben werden soll, bergeben. Die Anzahl der Elemente
ist 1, weil ein einziges Feld abgespeichert wird. Bei der zwerten fwrite-Anweisung ist
die Betradrtungsweise anders. Dort wird nicht ein Sking sondern ein Array von cftarElementen abgespeichert. Dasist natrlich das gleiche, aber es wd nun einmal anders
angegeben. Zuerst wird die Adrcsse des char-Feldes nnarnebergeben. Dann folgt die
Gre eines char-Elements und danach die Anzahl der im Feld vorhandenen cftar-Elemente. Sie sollten sic-h darber klar sein, da die folgenden Zeilen identisch sind:

);
% s \ n ", v n a m e
%s\n",nname);
1u\n',alten);
[u\n".groesse);

l
l
Die dazugehrige zain-Funktion wurde nicht mit abgedruckt, weil sie identisch mit
der aus F-gt"o,,,PRG23-01.C- ist. Werur Sie diese Funktionen abtippen woller!
bernehmen Sie bitte diese main-Funktion.

k o n n t e n i c h t e r z e u g t w e r d e n! \ n \ n ' ) ;

(
s k i p - s ' i z e o f ( v n a m e) + s i z e o f ( n n a m e) + s i z e o f a I t e r ) ;
fsetpos(fhd,&skiP);
f r e a d ( & g r o e s s e s, i z e o f ( g r o e s s e) ' I ' f h d ) ;
f c ' lo s e ( f h d ) ;
printf('Groesse in cm

: 1u\n'.groesse);

Es wd eine variable namens shp vom


\p fpos_t definiert. In ihr wird die summe der
Ingm der zu berspringendm Datm gespeichert. Nach dem ffnm
der Datei wirrd
der Dateipositionszeiger an die Stelle vor den gespeicherten Daten der
GrYtfutp*
e gesetzt. Die restlichen Anweisungen mtsprechen d"" a", ursprnglichen
Funktion lesez- Die Variablen onamc, nname und alter wurden definiert, obiohl"sie
nur zur Beslmmung der zu berspringendm Daten benutzt wurden. Es kann
sein, da der compiler eine Warnung ausgibt, da diese drei Variablen nicht benutzt wurden.
Sollte dies
der Fall seir\ brauchen sie sich in diesem speziellen Fall nicht daran
zu stren.

remove und renaure


Zwei Funktioneru die dirckt mit dem Dateinamen operiere4 sind remove und rename.
a - r e m o v e ( n a m e) :
renrooelscht eine Datei namens name und dbt bei Erfolg den Wert 0 zurck. name isl
die Adresse eines Strings.
a - r e n a m e ( atl e r n a m e . n e u e r n a m e; )

fgetpos

renamebenelnl.lteine Datei namens alfsrname inneuername run. Bei Erfolg wird der Wert
0 zurckgegeben. altername rund neuernamesind Skingadressen. Zum Beispiel lscht

Als C'egenst&.atfxtpos
gibt es die Funktion fgetpos, die den aktuellen wert des Dateipositionszeigers in einer Variablen speichert.

r e m o v e ( ' t e s t .t x t " ) :

fpos_t position;

n e n a m e ( ' t e s tt.x t " , n a m e );

a - f g e t p o s ( f h d , & p o s .tii o n )
Der Aufnrf stinmt exakt mit dem vonfefpos berein, nur dasfgeeosietzt,
anstatt den
Wert der Variblen position in den Dateipositionszeiger zu schrei-beo
den Wert des Da_
teipositionszeiters in die Variable position schleibt. Sollte die Funktion
ihre Aufgabe
ordnungsgem erfllt habe& grbt sie den Wert 0 zurck.
fseek
Es grbt eine weitere Funktiory mit der sich der Dateipositionszeiger
verndern I!
und die ist gleidrzeitig auch die komJortabelste. Sie heiit feeek unjkann
mit verschiedenen Modi aufgenrfen werrdm:
a - f s e e k ( f h d , d i s t a n z , m o d u s) I
Es stehen folgende Modi zur Verfgung:
SEEK-SE'T

die Datei namens,,test.b(t". Der Funktionsaufruf

benennt die Datei namens ,,test.txt" in den Namen um, den die Stringvariable
enthlt.

name

tmpnam und tnpfile


Wenn man aufgrund bestimmter Umstnde eine Datei erzeugen mu, die aber vor Beendigung des Programrns wieder gelscht wird, also eine sogenannte temporre Datei, dann steht man vor dem Problem, einen Namen ftir die Datei zu whlen, der einzigarhgist. Dies ist wichtig, damit nicht eine andere Datei berschrieben wird, weil sie
zufllig den gleichm Namen hat. Um dieses Problem zu umgeherL wurde in C eine
Funktion namens tmpnam implementiert, die einen einzigartigen Namen erzeugt.
tmpnam wird folgendermaen aufgerufen:
char a[80];

Der Dateipositionszeiger wird auf den Dateianfang gesetzt und


bekorrmt den Wert von dislanz hinzuaddiert. Bei diesem Modus
mam nur positive Werte fr distanz einen Sinn. Der Aufnrf mit
diesem Modus kommt in der Wirkung dem Aufruf vonl9etpos(ftd,Eposition) gleidl wenn posifion und iltanz den gleichen
Wert haben.

SEEK-END

Der Dateipositionszeiger
wird auf das Dateiende gesetzt, und
bekommt den Wert von disfanz hinzuaddiert.
Bei diesem Modus
machen nur negative Werte fr dislazz Sinn.

SEEK-CUR

Zum Dateipositionszeiger
wird der Wert vonilistanz
hinzuaddiert. Dies ist der einzige Modus, bei dem positive und negative
Werte fr drsfanz sinnvoll sind. Der Aufruf entspricht der
Anweisungsfolge:

t m p n a ma( ) l
tmpnam schreibt dieserr Namen in die Stringvariable a. Aber tmpnam ist nodr komfortable4 denn sie kann auch so aufgerulen werden:
char *a;
a : t m D n a mN( U L L ) ;
eines Ttigers, der den Wert 0 hat, also auf Adresse 0
NULL ist die Makrodefnition
zeigt. Ein 7*igea der auf die Adresse 0 zeigt, steht nun aber in C fr einen 7*iget" det
auf nits zeigt. Deswegen geben viele Funktioneru zum Beispiel/opcn, bei Erfolg einen Zeiger auf die FILE-Struktur und bei Mierfolg den Wert 0 zurclq weil danach
det Taiger auf Adresse O zr:ig!., was bedeutet, da er auf nichts zeigt. Man htte auch
folgendes schreiben knnen:
a - t m p n a m((v o i d * ) 0 ) ;

Thbelle23.3: Die Motli aon eek


f g e t p o s ( f h d , & p o s it i o n ) ;
P o si t i o n + - d i s t a n z ;
f s e t p o s (f h d , & p o s it i o n ) ;
wollen sie zum Beispiel den Dateipositionszeiger
machen Sie dies so:

um zwei Bytes nach vorne beweger\

f s e e k (f h d , 2 , S E E K _ C U;R )
Die fr fseek zw verfgung stehenden Modi sind Makros, die in der Headerdatei
sfdio.ft definiert sind..yteekliefert 0 zurck, wenn das Verndem des Dateipositionszeigers fehlerfiei vonstatten Sln'rg.fs"eklscht auerdem noch das Dateiende-Flag.

Aber es ist viel elegante4 die Makrodefinition zu benutzen. Doch kommenwb zu tmpncn zur& Rufen wir die Funktion so wie oben beschrieben auf, bergeben wir ihr
den Wert 0 oder einen Nullzeiger. Das heit fr die Funktiorv da wir keinen Zeiger
bergeben. Sie reserviert darauflrin selbst Speicher und schreibt den von ihr erzeugtm
Namen in diesen Speicher. Der Rckgabewert ist dann die Adresse des Speichers, indem der Name steht. Der Speicher wird automatisch bei Programmbeendigung fteigegeben. Er kan+ falls ein neuer Name gebraucht wird, wieder andie tmptum-Funktion
bergeben werderl so da der alte Name berschrieberr wird und kein neuer Speicher
reserviert werden mu.
Eine weitere Funktioru die einem noch mehr Arbeit als tmpnam abnimmt, ist tmpfile.
Sie wird folgendermaen aufgerufen:
f h d - t m p f i 1e ( ) ;

r.*i"d
Die letzte Funktion heit rewind und setzt den Dateipositionszeiger auf den Anfang
der Datei. Weiterhin lcischt sie das Fehlerflag. Ihr Aufruf sieht so aus:
r e w i n d( f h d ) :
Die Funktionen f*tpw, fsetpos vnd fseek spezifizieren einen eventuell aufgetr,etenen
Fehler im Makro errno.

23.4 Alleemeines zu Dateien


Es werden jetzt noch einige Funktionen besprochen, die das Arbeiten mit Dateien untersttzen und damit auch vereinfachen.

AIs erstes wre da die Funktion freopen. Sie sdrliet eine Datei und ffnet eine andere.
Der Aufnrf sieht folgendermaen aus:
n e u f h d - f r e o p e n ( n a m em
. odus,al tfhd) ;
Die Datei" die ber die FILE-Suukhr angesprochen wird, auf die altfrd zeigt, wird ge
sdrlossen- Dann wird eine Datei nanrens name mit dem Modus modns geffrret. Die
A&esse der zugehrigen FILE-Stmktur wd in natftd gsperchert. Sollte ein Fehler auftreteq errth:ilt neuftil denWert 0. Der Aufruf errtspridrt folgender Anweisungsfolge:
fclose(altfhd):
, o d u s) ;
n e u f h d - f o p e n( n a m e m

f h d - f r e o p e n ( n a m e . m o d u s, f h d ) ;

a - t m D n a mN( U L L ):
fhd-fopen(a,'wb+');
Wobei a ein Zeiger auf einen String ist. tmpflehat jdoch den Vorteil, da der Speiche4,
der den Namen aufnimmt, nur fr das ffnen der Datei reserviert und danach wieder
freigegeben wird.
fenor
a-ferror( fhd ) :
Sollte ein Fehler im Zusammenhang mit der Dateild
ungleich Null.

fteoPen

kann gut dazu benutzt werder1 einem Zeiger auf eine FILE-Struktur
frry^
Datei zuzuweisen:

Die Funktion ffnet eine binre Datei zur Ein- und Ausgabe und liefert die Adresse der
FILE-Stnrktur zurck, ber die die Datei verwaltet wird. Der Aufruf von tmpfle
kommt folgender Anweisungsfolge gleich:

eine neue

aufgetr,eten seir\ hat a einen Wert

23.5 Gepufferte Dateien


ien zu puffem' Das bedeutet.da nicht ie'
C
Zeichen in diebatei geschrieben wird, dies auch tatschlich auf der
desmal *"*
Puffer voll
Festplatte oder Diskette gespeichert wird. Vielmehr wird gewartet, bisdet
die Verarist, und dann werden mit einem Zugnlf. alle Daten gespeichert. Dies erhht
weil es schneller geht, einen groen Datenblock einmal zu
beitungsgeschwindigkei!
ab kleinJmehrmals. Dies macht sich besonders bei Disketten bemerkbal
r.h*i,
verdie sich ia im Normalfall nidrt drehen, sondem lediglich beim Zugnfr. in Rotation
setzt werden.
setvbuf
mit der ein Puffer fr eine Datei angelegt werden kann, heit setvbuf.
ffiltioru
Sie wird wie folgt aufgerufen:
a-setvbuf(fhd, adresse, modus.groesse)
Fiir die Datel die mit der FILE-Stnrktur verbunden isq aut dteN znigt, wird ein Puffer
mu
angelegt, det groesseBytes gro ist und an der Adresse aitresx toeg! Die Adresse
die Startadresse eines char-ieldes sein. xtobuf gpbt den Wert 0 zurck, wenn alles ordnungsgem ausgefhrt werden konnte. Fur setobuf glbt es drei Modi:
-IOFBF

Die Ausgabe wird voltstndig gepuffert.

-IOLBF

Die Ausgabe wird zeitenweise gepuffert.

-IONBF

Die Ausgabe wird nicht gePuffert.


Tabellc23.4: Die Moili oon setobuf

in der Headerdatei stdio'h


_I)FBF, -IOLBF und -IoNBF sind Makrodefinitionen und
enthalten.

ungen
Kommerr wir nun wieder zu ein paar bugerv

um das bisher Gelemte zu festigen.

Tbxtdatei fuagt.
Schniben Sie ein Programru welches Sie nach dem Dateinamen einer
Sie, da Sie nicht
Geben Sie diese Datei dann auf dem Bildschirm aus. Bercksichtigen
wissen knnen, wie lang die lngste Zeile der Datei ist'

gnd einer
Scheiben Sie ein Prograrnrl welches Sie nach dem Namen einer Quelldatei
werumgedreht
zeilenweise
soll
steht,
der
in
d"r
Tett
Der
Quelldatei
fragt.
eldatei
Ange
den und in der Zieldatei abgespeichert werden. Benutzen Sie hierfr Textdateien'
noruner1 die Datei hat folgenden Inhalt:
Es ist warm
Johann
Otto
Willi klettert
Dann soll die Zieldatei so aussehen:
mraw tsi sE
nnahoJ
ottO
trettelk illiW
keine Zeile
Der Einfachheit halber sollten Sie davon ausgeheru da in der Textdatei
lnger als 300 bchcn'rst.

lin Beispiel fiit das Einrichten eines Puffers wre folgendes:


char at100l;
FI L E * f h d ;
i nt ok:
"w"
):
fhd-fopen('test.txt',
ok-setvbuf(fhd. a. -l0FBF. sizeof(a));
flcose(fhd):
xtobufhataber auch eine hnliche Eigenschaft wie tmpnam: Soute als Adresse des Puffers der wert 0, also ein Nu[zeite4 beryeben werder! reserviert die Funktion eigenstndig Pufferspeicher der angegebenen Gxie und gibt ihn auch automatisch beim
Schlieen der Datei wieder frei. Um dies zu bewerkstelligery mtiten w im obigen
Beispiel delrt xtobuf-Aufmf folgendersraen gestalten:
o k : s e t v b u f ( f h d , N U L L ,_ I 0 F B F , 1 0 0 ) ;
Folgende Schreibweise wrc allerdings die korrektere:
o k - s e t v b u f ( f h d , N U L L ,_ l 0 F B F , ( s i z e - t ) ( 1 0 0 ) ) ;
Die Grcie mu nmlich als ein Variablentyp namens sr'ze-t angegeben werden. fedoch
sollte man diese explizite Tlrpumwandlung nur vornehmerL wenn der Compiler sie
verlangt. Ansonsten frdert sie nur die Unbersichtlidrkeit.
setbuf
Die Funktion xtbuf dient zum einfacheren Aufruf von setobuf. Schauen wir uns einmal
den Aufnrf an:
-setbuf( fhd, adresse)
-

ftd ist ein Zeiger auf die entspredrende FILE-Struktur. adrax isl 7*iger auf. den Typ
cftar. Sollte die bergebene Adrcsse ungleich Null sein, wird sefobu/automatisch so aufgerufen:

fragt. Dasclneiben sie ein Programrrr' welches sie nach dem Namen einer Tbxtilatei
soll
nach soll man die Mglichkeit zur Eingabe eines Strings haben' Das Programm
entdann pr(en ob der eingegebene String in der Datei enthalten ist oder nicht. Ist er
halten, soll die qste stelle,der der string gefunden wurde in Form von Zeilennumsie einen
mer und Position des strings innerhalb der Zeile ausgegeben werden. wenn
da er
suchstring angeben, der aus mehreren wrtem besteht, kann es vorkommerl
des
sich ber lweioder mehrere Zeilen erstr,eckt- Sie sollen aber nur die Vorkommnisse
aus, da
Suclrstrings bercksichtigen, dieineiner Zeile stehen. C'ehen Sie wieder davon
keine Zeile lnger als 30o Zeien ist-

Schreiben Sie ein Programm mit der gleichen Funktionalitt wie in Aufgabe 3, nur sollen Sie hier binre Dateien beaeiten knnen. Bitte bedenken Sie da Sie bei dieser
Aufgabe nicht mehr zeilenweise vorgehen knnen. Die gefundene Position mu daher
ab Fosition, gemessen vom Anfang der Datei, angegeben werden Diese Aufgabe
kfiryt im """t Moo,"trt einfacher als sie ist. Aber Sie mssen bercksichtigen da,
werur Sie die Datei mitlread blockrveise einlesen, das gesute Wort oder der gesuchte
String teilweise im einen und teilweise im anderen Block enthaltqr sein knnte. Es gibt
versiedene Lsungswege. [.assen Sie sich einen einfallen. Das gleiche Problem tritt
brigens bei allen Aufgaben auf, die sidr auf diese hier beziehen'

VorkomAndern Sie die Programme aus 24.3 und 24.4 so um, da nicht mehr das erste
men des Strings in der Datei sondem d.as lehte Vorkommen ausgegeben wird' Sucht
das Programm zum Beispiel das Wort ,,die" in einem Text, soll die Position des letzten
-die" im Text ausgegeben werden-

Sie die Programme aus 24.3 und 24.4 so um, da nur gezhlt und ausgegeben
Ana"wird, wie olt der entsprechende String in der Datei vorkommt'

setvbuf(fhd, adresse, _l0FBF, BUFSIZ);


Wobei BUFSIZ ein in stdio.h vordefiniertes Makro ist. Hat adrcsx aber den Wert 0, wird
x tobuf tolgendermaen auf geruferu
s e t v b u f ( f h d , N U L L ,_ l 0 N B F , B U F S I Z ) :
NULL steht hier wieder ftir den vordefinierten

Nullzeiger.

fflush
ffi,
Si" gepufferte Dateien benutzrru kann es vorkommen, da Sie den Puffer geme
abspeichern wtirderu obwohl der Puffer noch niciht voll genug ist, um von C automatisch abgespeichert zu werdm. Um dies zu bewerkstelligen, hnutzt man fflush.
w e r t - f f l u s h (f h d ) :
Der Puffer der ^rf1d gehrenden Datei wird abgespeichert. War die Abspeidrerung erfolgeich, hefertfflush den Wert 0 zunick, ansonsten EOF.
Man kann zur Sicherheit fflush aufttfie4 bevor die Datei mit/close geschlossen wird,
um einem Verlust des Puffers vorzubeugen. Unbedingt notwendig ist es aber nicht.

Andem Sie das Programm fr Textdateien aus 24.6 so um, da jedesmaf wenn der
String gefgnden wird" die Zeile und die Position des Strings innerhalb der Zeile in eine
t poi Textdatei gescluieben werden. Am Ende der Datei sollen Sie die Anzahl der
Vrkommnisse ond d"r, String selber ebenfalls noch vermerken. Das Programm soll
erstellten Datei
nadr dem Namm der zu erstellenden Textdatei fragen. Der Inhalt der "fubeit"):
sollte dann ungefhr so aussehen (bei dli Vorkommnissen des Strings
Zeile 3 an Position 23
Z e i ' l e 1 9 a n P o s it i o n 3
Zeile 129 an Position 17
V o n k o m m sn si e i n s g e s a m t : 3
'Arbeit'
G e s u c h t e rS t r i n g :

@
Tndem

Sie das Programm aus 24.3 so urn" da eine neue Datei erzeugt wir4 in der alle
vorkommnisse des suchstrings in der Datei gelscht sind' Angenommen' es sei folgende
Datei gegeberu
D a s l l e t t e r u n d d i e B ' l u m e ns i n d s c h n . A b e r d i e s t r a B e i s t d r e c k i g Ist der eingegebene String ,,die", dann sieht die neue Datei so aus:

23.6 Kontrollfragen

Das lletter und

1. AuI welche Besondereit mu bei der Benutzung vonffofi) geachtet werden?


2. Was sind die Vor- und Nachteile gepu-fferter Dateien?
3. WorauJ mu man bei der Wahl von Dateinanen

achten?

B l u m e ns i n d s c h n . A b e r

StraEe ist

dreckig.

schreibensie ein Programnq weldres sie nach dem Namen einer Textdatei fragt. Anschlieend soll das Programn das Vorkommen aller Buchstaben und Zaftlen zhlen
und in eine Thxtdatei schreiben" deren Namen der Benutzer voher eingeben kann. Der
lnhalt der Textdatei sollte ungefhr so ausseherq wenn die bearbeitet Datei "text.bxt"
heit:
Zhlung der Datei "text.kt"
A=23
B-18
cd
'3-2
Et4

9=2
Unterseiden Sie nicht zwischen Gro- und Kleinschr,eibung. Groe und kleine Buchstaben sollen zusammengefat angegeben werden.

Andem sie das Programm avs24.9 so unu da nicht mehr die Anzahl der Zeichen numerisch sondern grafisch dargestellt wird. Das Beispiel as 249 knnte zum Beispiel
so aussehen:

Zhlung der Datei "text.b(t"


AAAAA
BBBB

cc

44

g
Einheit : 5 Zeichen aufgerundet.
Dies hnelt einer Art Balkendiagramm und erleichert den Vergleich der Hufigkeiten.
wie oben im Beispiel sollten sie fr jede angefangene 5er4ruppe ein neues Zeichen
hinzufgen.

@
Andern Sie das Programm aus 24.10 so uru da die starre 5er4ruppe vom Prograu n
variabel gehalten wird. Eine G-pF
sollte mindestens aus einem Zeichen bestehsu
Der Balken des hu-figsten Zeichens sollte aber nicht grer als 40 Zeichm sein. Das
Programm mu deshalb die Anzalrl der Zeicheo die zu einer Einheit zusamrnerrgefat
werderL selbst bestimmen-

Das könnte Ihnen auch gefallen