6
Kommen wir nun zu einem weiteren Aspekt der Ein- und Ausgabe, dem ,,File Hand- ling". Unter File Handling versteht man das Speichern von Daten in und das Laden von Daten aus Dateim. Fangen wir mit den gnrndlegenden Funktionen an. fopen und fdose Die Funktionen, die eine Datei öffnen und sdrließen, heißen 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. fopen und fcbse haben das folgende Format fi 1eptr-fopen(dateiname.modus) ; : fclose(fileptr^); fleptr ist ein Zeiger auf eine FILE-Struktur. ,,File" heißt auf deutsch ,,Datei". Er wird wie folgt definiert: FILE *fileptr; Die File'Stnrktur wird durch den Aufruf von fopen erzeugt und mit /close wieder ge. löscht. Sie enthält alle charakteristischen Informationen über die geöffnete Datei und ist eindeutig, Sie können 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 geöffnet werden. Die Prototypen von fopen vnd fclo- se, sowie die Deklaration von FILE stehen in der Headerdatei stilio.h. Der Name der Da- tei wird mit einer Stringkorstante dateineme angegeben. Die Regeln der Dateinamen- vergalre hängen von Ihrem Computersystem ab. modus ist ebenfalls eine Stringkon- nte und gibt den Modus der zu öffnenden Datei an. Die Modi entscheiden über das \'ormat der Datei (Iextdatei oder Binärdatei) und darübeq ob gelesen oder geschrieben werden kann oder soll. en Beschäftigen wir uns zuerst mit den Tixtdateien fopen stellt uns dafüLr folgende Modi zur Verfügung: Modus aöschreibung-::11:..{.::it, r öffnet eine Textdatei zum Lesen. erstellt eine Textdatei zum Schreiben. Der Inhalt einer bereits unter diesem Namm existierenden Datei wird gelöscht. a erstellt oder öffnet eine bereits existierende Textdatei zum Schreiben. Der Dateipositionszeiger steht am Ende der Datei, dadurch werden neue Datm hinten angehän6. erstellt eine Textdatei zum Lesen und Sdueiben. Der lnhalt einer bereits unter diesem Nasren existierenden Datei wird gelöscht. "a+" erstellt oder öftret eine bereits existierende Textdatei zum Lesen und Schreiben. Der Dateipositionszeiger steht am Ende der Datel dadurch werdm neue Daten hinten angehängt. Tabelle 23.7:Die Dateimodifür Textdateien Wollen wir z.B. eine Textdatei narnens ,,test.t(t" zum Schr,eibenöffneru gehen wir fol- gendermaßen vor: fi I eptr-fopen ('test. txt' .'w" ); 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. fputs, ftets und feof Schauen wA uns riun die einfaösten Funktionen zum Lesen und Schreiben von Text in Dateien aru nämlich fputs und fgetc. Diese Funktionm sind mit pufs und gefs für die nor- male Ein- und Ausgabe identisdu außer daß zusätzlidr noch ein 7*iger aul die FILE- Struktur des zu lesenderr oder beschreibenden Files und ber fgets noch die Anzahl der maximal einzulesenden Zeichen mit angegeben werden müssen. Des weiteren wind im folgenden Beispiel die Funktion feof benutzt. feof "trr.d folgerrdermaßen aufgenrfen: wert-feof( fi l eptr ) ; Abhlingig davorl ob das Ende der Datei erreicht ist oder nichg ist zrert entweder ,,Wahr" oder,,Falsch". Und hier das Beispiel: /linclude (stdio.h) /* PRG23-01.C */ /li nc l ude <stri ng. h> lldefi ne DATNAME 'test. txt" lldefine MAXZEILENLAENGE 160 void schreiben(void) I FILE *fhd: char sIIIAXZEILENLAENGE]; fhd-fopen ( DATNAME, "w" ); if(!fhd) { printf('Datei konnte nicht erzeugt werden!\n\n'); I el se { printf("Bitte maximalXi Zeichen pro Zeile eingeben.\n,, MAXZEILENLAENGE): printf("Eingabe wird mit beendet.\n\n'); do I printf(')"); gets ( s ); i f ( strcmp( s, ".') ) { f p u t s ( s , f h d ); fputs("\n',fhd); I l while(strcmD(s,'. " ) ): fcl ose(fhd ): printf( "\nEingabe beendet ! \n' ); I l void lesen(void) I FI LE *fhd; char sÜ'IAXZEI LENLAENGEI ; i nt x-l; fhd-fopen( DATNAME.'r" ) ; if( !fhd) { pnintf('Datei konnte nicht geoeffnet werdent\n\n'): I el se { printf("Die Datei hat folgenden Inhalt:\n"): f sets ( s , MAXZE I LENLAENGE, f h d ) : oo I p r i ntf ('Xi :1s'.x+.r,s ); f g e t s ( s . MAXZEI LENLAENGE, f h d ); l while(!feof(fhd)): fclose(fhd); printf("\nEnde den Datei !\n'); I I void main(void) ( i nt i nput: printf('Soll die Datei l-gelesen oder Z'beschrieben werden?.): scanf("Zi',&input); i f( i nout:-l ) ( lesenO: I else l if(input*2) I schpeiben( ): I e lse { printf( "\nFa lsche Eingabe! \ n \ n . ); I I I ln der raain-Funktion liest die scanl-Anweisung eine Zalrt ein. Der Benutzer beendet die Eingabe duch Drücken der Retum-Taste. Es kann auf manchen Rechnem vorkom- meru daß die Betätigung der Return-Täste im Tastaturpuffer bteibt. Bemerkbar macht sich dies, wenn nach dem start des obigen Programms in der ersten Zeile zwei Einga- beaufforderungen stehen und bei der Textausgabe Ihr Text einer ersten Leerzeite folgt. Wenn dies der Fall ist, fügen Sie hinter scazlbitte folgende Anweisung einl: File-Handling I Dies fiegt an der Eigensdtaft bestimmter Systeme, ei^ caftiage-return und ein line-feed zu senden.

File Handling

  • Upload
    as-asd

  • View
    240

  • Download
    3

Embed Size (px)

DESCRIPTION

a

Citation preview

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

fopen und fdose

Die Funktionen, die eine Datei öffnen und sdrließen, heißen fopen und fclose. IhrePrototypen sowie die Prototypen der anderen File-.Handling-Funktioneru die wir indiesem Kapitel kennenlemen werden, stehen in der Headerdatei stdio.h.

fopen und fcbse haben das folgende Format

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

:f c l o s e ( f i l e p t r ^ ) ;

fleptr ist ein Zeiger auf eine FILE-Struktur. ,,File" heißt auf deutsch ,,Datei". Er wirdwie folgt definiert:

F I L E * f i l e p t r ;

Die File'Stnrktur wird durch den Aufruf von fopen erzeugt und mit /close wieder ge.löscht. Sie enthält alle charakteristischen Informationen über die geöffnete Datei undist eindeutig, Sie können daher mit mehreren/opcz-Aufrufen mehrere FllE-StrukturenerzeuterL und damit mehrere Dateien öffnen. H.at flqtr nach dem AuJruf von fopenden Wert Q konnte die Datei nicht geöffnet werden. Die Prototypen von fopen vnd fclo-se, sowie die Deklaration von FILE stehen in der Headerdatei stilio.h. Der Name der Da-tei wird mit einer Stringkorstante dateineme angegeben. Die Regeln der Dateinamen-vergalre hängen von Ihrem Computersystem ab. modus ist ebenfalls eine Stringkon-

nte und gibt den Modus der zu öffnenden Datei an. Die Modi entscheiden über das\'ormat der Datei (Iextdatei oder Binärdatei) und darübeq ob gelesen oder geschrieben

werden kann oder soll.

en

Beschäftigen wir uns zuerst mit den Tixtdateien fopen stellt uns dafüLr folgende Modi

zur Verfügung:

Modus aöschreibung-::11:..{.::it,

r öffnet eine Textdatei zum Lesen.

erstellt eine Textdatei zum Schreiben. Der Inhalt einer bereitsunter diesem Namm existierenden Datei wird gelöscht.

a erstellt oder öffnet eine bereits existierende Textdatei zumSchreiben. Der Dateipositionszeiger steht am Ende der Datei,dadurch werden neue Datm hinten angehän6.

erstellt eine Textdatei zum Lesen und Sdueiben. Der lnhalt einer

bereits unter diesem Nasren existierenden Datei wird gelöscht.

"a+" erstellt oder öftret eine bereits existierende Textdatei zum Lesenund Schreiben. Der Dateipositionszeiger steht am Ende derDatel dadurch werdm neue Daten hinten angehängt.

Tabelle 23.7: Die Dateimodifür Textdateien

Wollen wir z.B. eine Textdatei narnens ,,test.t(t" zum Schr,eiben öffneru gehen wir fol-gendermaßen vor:

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

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.

fputs, ftets und feof

Schauen wA uns riun die einfaösten Funktionen zum Lesen und Schreiben von Text in

Dateien aru nämlich fputs und fgetc. Diese Funktionm sind mit pufs und gefs für die nor-male Ein- und Ausgabe identisdu außer daß zusätzlidr noch ein 7*iger aul die FILE-Struktur des zu lesenderr oder beschreibenden Files und ber fgets noch die Anzahl dermaximal einzulesenden Zeichen mit angegeben werden müssen. Des weiteren wind imfolgenden Beispiel die Funktion feof benutzt. feof "trr.d folgerrdermaßen aufgenrfen:

w e r t - f e o f ( f i l e p t r ) ;

Abhlingig davorl ob das Ende der Datei erreicht ist oder nichg ist zrert entweder

,,Wahr" oder,,Falsch". Und hier das Beispiel:

/ l i n c l u d e ( s t d i o . h ) / * P R G 2 3 - 0 1 . C * /

/ l i n c l u d e < s t r i n g . h >

l l d e f i n e D A T N A M E ' t e s t . t x t "l l d e f i n e M A X Z E I L E N L A E N G E 1 6 0

v o i d s c h r e i b e n ( v o i d )I

F I L E * f h d :

c h a r s I I I A X Z E I L E N L A E N G E ] ;

f h d - f o p e n ( D A T N A M E , " w " ) ;i f ( ! f h d )

{p r i n t f ( ' D a t e i 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 ' ) ;

Ie l s e

{p r i n t f ( " B i t t e m a x i m a l X 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 , ,

M A X Z E I L E N L A E N G E ) :p r i n t f ( " E i n g a b e w i r d m i t b e e n d e t . \ n \ n ' ) ;d o

Ip r i n t f ( ' ) " ) ;g e t s ( s ) ;i f ( s t r c m p ( s , " . ' ) )

{f p u t s ( s , f h d ) ;f p u t s ( " \ n ' , f h d ) ;

I

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

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 ' ) ;

Il

v o i d l e s e n ( v o i d )IF I L E * f h d ;

c h a r s Ü ' I A X Z E I L E N L A E N G E I ;i n t x - l ;

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

{p n i n t f ( ' D a t e i k o n n t e n i c h t g e o e f f n e t w e r d e n t \ n \ n ' ) :

Ie l s e

{p r i n t f ( " D i e D a t e i h a t f o l g e n d e n I n h a l t : \ n " ) :f s e t s ( s , M A X Z E I L E N L A E N G E , f h d ) :o o

Ip r i n t f ( ' X i : 1 s ' . x + . r , s ) ;f g e t s ( s . M A X Z E I L E N L A E N G E , f h d ) ;

l w h i l e ( ! f e o f ( f h d ) ) :

f c l o s e ( f h d ) ;p r i n t f ( " \ n E n d e d e n D a t e i ! \ n ' ) ;

II

v o i d m a i n ( v o i d )(i n t i n p u t :

p r i n t f ( ' S o l l d i e D a t e i l - g e l e s e n o d e r Z ' b e s c h r i e b e n w e r d e n ? . ) :s c a n f ( " Z i ' , & i n p u t ) ;

i f ( i n o u t : - l )(

l e s e n O :I

e l s el

i f ( i n p u t * 2 )I

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

e l s e{

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

II

ln der raain-Funktion liest die scanl-Anweisung eine Zalrt ein. Der Benutzer beendetdie Eingabe duch Drücken der Retum-Taste. Es kann auf manchen Rechnem vorkom-meru daß die Betätigung der Return-Täste im Tastaturpuffer bteibt. Bemerkbar machtsich dies, wenn nach dem start des obigen Programms in der ersten Zeile zwei Einga-beaufforderungen stehen und bei der Textausgabe Ihr Text einer ersten Leerzeite folgt.Wenn dies der Fall ist, fügen Sie hinter scazlbitte folgende Anweisung einl:

File-Handling

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

g e t c h a r ( ) ;

gglg$wartet auf die Eingabe eines Zeichens. Da wir aber wissery daß an dieser Stelle

im Programm noch ein CR (carriage return) im Tästaturpuffer gespeichert ist, wird die'

ses eingelesen

Zu Anfang wurden zwei Makros definiert, einmal für die maximale Zeilenllinge der

Ein- und Ausgabe des Textes und einmal für derr Dateinamen. Der Vorteil dieser Ma-

kros ist de4 daß man bei einer Anderung des Dateinamens oder der Zeilenlänge nur

eine Stelle im Programm verändern muß, nämlich das Makro, und das ganze Pro-

grarnm paßt sich dieser Anderung an.

Die main-Funktion brauchen wir nicht zu besprechen, denn Sie ist ziemlich trivial. Ge-

hen 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 geöff-

net- Sollte sie schon existiereo wird ihr Inhatt gelöscht. Es wird überprüft, obld falsch

ist (!fhd). lhd ist dann falsdr" wenn er den Wert 0 hat, und das bedeutet, daß die Datei

nicht geöffnet werden konnte. Für diesen Fall wird eine entsprecJrende Meldung aus-

gegeberu Sollteld wah4, also ungleich null sein, ist die Datei ordnungsgemäß geöffnet

und zum Schreiben bereit.

Innerhalb der do-Schleife läuft die eigentliche Eingabe über Tästatur 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 tesPei-chert wird. Dann wird überprüft, ob die Zeile nur aus einem Punkt besteht. Wenn ia,wird sie niclt in die Datei geschriebery denn der Punkt ist unsere Endekennunt. An-

sonsten wird die eingegebene 7*ile mit fuuts in die Datei geschrieben und durch ein

zweites fVuts mit CR ergänzt. Dies ist notwendig, weil gets das Drücken der Returnta-

ste als Abschluß der Eingabe nicht im String gespeichert hat. Dann wird die do'Schleifegesdrlossery wobei sie so lange wiederholt wird, wie s nicht nur aus einem Punkt be-

steht. Sollte unsere Abbruchbedingung erfüllt 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 zu-

sätzlich aber noch eine inFVariable r, die für das Zählen der Zeilen benutzt wird. Da-

nach wird eine Datei zum Lesen geöffnet und anschließend überprüft, ob dies auch

ordnungsgemäß geschah. Für die Eingabedatei wird der gleiche Name benutzt wie für

die Ausgabedatei. Gehen wir nun zur dc'Sclleife. Der Aufbau sieht etwas umständlichaus, wenn man nicht die Besonderheit vonfolkennt. Das Dateiende'Flag wird nichtg*tz! wenn das Dateiende erreicht ist, sondern erst danrL wenn versucht wird, wei-

tere Daten zu leseru obwohl das Dateiende erreicht ist. Dies bedeutet, daß ein Lrsever-

such fehlsdrlagen muß, bevor/eo/einen wahren Wert liefert.

Es muß erwähnt werdery daß die da'Schleife nur dann einwandfiei läuft, wenn die Da-

tei mindestens eine Zeile enthält. Um den Fall einer leeren Datei abzufangerl müßte

die do-sdrleife noch in eine if-I+bfrage gepackt werden:

f g e t s ( s , M A X Z E I L E N L A E N G E , f h d ) ;i f ( ! f e o f ( f h d ) )

tclo

{P r i n t f ( ' t i : X s " , x + , s ) ;f g e t s ( s , M A X Z T I L E N L A E N G T . f h d ) ;

l ' w h i l e ( l f e o f ( f h d ) ) ;

t c i o s e ( f h d ) :

Wie Sie am vorherigen Beispiel sehen können, positionieren die Funktionery die in ei-

ner Datei teseru den Dateipositionszeiger immer hinter das zuletzt gelesene ZeicherV

wohingegen die Ftrnktioneru die in eine Datei sdueiben den Dateipositionszeiger im-

mer hinter das zulebt geschriebene Zeichen setz€n.

fprintf und fscan

Es gibt noc-h weitere Funktion zur Bearbeitung von Textdateien. Die komfortabelsten

heißen fptirrü und fscan. Ihre Funktioruweise ist identisch mit prinf und scanf.DetrTexg 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 ,

s t r l e n ( w o ) ) :

auf den Bildschirm bringt, sdueibt

f p n i n t f ( f h d , " 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 '

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:

f s c a n ( f h d . " t i X s " , x , s ) ;

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 für den obe'

renfpintf-Aufruf den entsprechendenl$ccn-Aufruf zu entwerferl der die Zeile wieder

einliest.

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 ) ;

Sie sind vielleicht überrascht, aber wenn Sie sidr an das Kapitel 4 über scanlerinnern,

wissen Sie, daß für die scary'-Funktion zwei Eingaben duldr ein Leerzeichen tetrenntwerden. Deswegen müssen alle Wörter in einzelne Strings eingelesen werden. Es lieg

dann an lhnen, die Wörter links von der Zahl wieder zu einem String zusammenzufas-

sen. Schreiben Sie einmal aus dem Handgelenk ein Progranmfragment, welches die

Strings sl bis sZ zu einem String narnens sf zusammenfaßt. Erst denkeru dann weiterle-

sen!

s t r c p y ( s t , s l ) :s t r c a t ( s t , s Z ) :s t r c a t ( s t , s 3 ) ;s t r c a t ( s t , s 4 ) ;s t r c a t ( s t . s 5 ) ;s t r c a t ( s t , s 6 ) ;s t r c a t ( s t . s 7 ) .

Der erste String wüd mit strqy in den String sf kopiert, weil dies einer lnitialisierung

gleichkommt. Hätten wir den ersten String mit sfrcat an sf angehängt, wäre ein eventu-

ell 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 Funktio-

neru die ein einzelnes Zeichen aus einer Datei lesen oder in eine Datei schreiben. Die

Funktionen heißen fgetc und fputc. Mit

f p u t c ( z e i . f h d ) ;

wüd das in der Variablen zei gespeicherte Zeichen in die Datei die der FILE-Struktur

fttil zugeordnet ist, geschrieben. fputc liefert den Wert von za' zurüch wenn alles in

Ordnung ist, ansonsten wird der Wert EOF zurückgegeben. EOF ist ein in der Header-

datei stdio.h definiertes Mako. Sie können es folgendermaßen benutzen:

w e r t : f o u t c ( z e i . f h d ) ;i f ( w e r t - - E O F )

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 ähnlich:

z e i : f g e t c ( f h d ) :

Danach enthält die Variable zai das gelesene Zeichen.

Die Dateiforrn, die wir bisher behandelt haben, war die Textdatei. Textdateien könnenohne Probleme in einen Texteditor geladen und dort betrachtet werdm. Die CQuell-progtamrne, die Sie gespeichert haberu sind im allgemeinen auch Textdateien. Nun istes aber oft vorteilhafteq, den lnhalt einer Variablen nicht als geschdebene ZahL sonderndirekt den Inhalt der Bytes, die öese Variable repräsentiere4 zu speichern. Erstens ko-stet dies meist weniger Speicherplatz und das umständlicle Zurückwandeln des Tex-tes in Zahlvariablen mittelsf can enüäIlt. fopez bietet uns verschiedene Möglichkeiteryeine Binärdatei zu öffnen:

Für die letzten drei Modi gibt es noch eine andere Sclu,eibweise, die hier aber nidrt er-wähnt zu werden braucht. Die Täbelle der Dateimodi im Anhang ist iedoch vollstän-dig.

fwrite und fread

Es gibt zwei Hauptfunktionen für Binärdateien Die eine heißt fwrite, und schreibt ineine Binärdatei, während die andere aus einer Binärdatei liest und fread heißt. ftun'tewird folgendermaßen aufgerufen:

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 ) ;

adresse rst die Adresse, an der die zu speichemde Variable oder das zu speiöerndeFeld steht. groesse ist die Größe der Variablen oder eines Feldelemmts in Bytes. anzalrtist die Anzahl der Feldelemente. anzahl ist bei der Speichenrng einer normalen Varia-blen gleich l.fldist der Zeiger auf die FILE-Struktu4 mit der die zu besclueibende Da-

tei verknüpft ist. fwrite gibt die Anzahl der komplett geschriebenen Elemente zurück.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 adresse die Adlesse ist an der die aus der Datei gelesenen Daten gespeichertwerden. Die anderen Parameter entspreöen denen von/zrrite. l,;.tchfrean gibt die An-zaN der komplett gelesenen Elemente wieder. Tritt z.B. beim Lesen des vierten Ele'mentes ein Fehler auf, dann gibtfread den Wert 3 zurü&

.2 teiI

- - . . : ' . i . t . - . . l , ' , ' '

-l'+il .,J jli:Ia ,' ,'$i"rb' öffnet eine Binärdatei zum Lesen

"wb" erstellt eine Binärdatei zum Schreiben. Der Inhalt einer bereitsunter diesem Namen existierenden Datei wird gelösdrt.

"ab" erstellt oder öffrret eine bereits existierende Binärdatei zumSchreiben. Der Dateipositionszeiger steht am Ende der Datei,dadurch werden neue Daten hinten angehängt.

"rb+"öffnet eine Binärdatei zum l"esen und Söreiben

"wbt" erstellt eine Binärdatei zum l.esen und Schreiben. Der Inhalteiner bereits unter diesem Namen o<istierenden Datei wirdgelösöt.

"ab+" erstellt oder öffnet eine bereits existierende Binärdatei zurnksen und Sch,eiben. Der Dateipositionszeiger steht am Endeder Datei, dadurch werden neue Daten hinten angehing.

Tabelle 23.2: Dic Datcimodi für Binärilateicn

sizeof

Die Funktionen bergen jedoch'im Augenblick ftir uns noch ein Problem: Angenom-

merL wir wollen eine inFVariable speichern. Woher wissen wiq wieviel Bytes ein inf-

Wert groß ist, denn die Werte können sich von System zu System unterscheiden. ln C

wurde daher ein GrößenbestimmungsoPerator implementiert, der die Größe eines ie'den Variablentyps und einer ieden Variablen bestimmen kann. Der Größenbestim-

mungsoperator heißt in C sizeof, was von den englischen Wörtern .size of" kommt

und auf Deutsch ,,Größe von" heißt. Der Operator wird folgendermaßen benutzt:

s i z e o f x

Hier wird die Größe der Variablen r in Bytes bestimmt. Man sollte sich angewöhnery

die Variable, auf die sich sizzolbezieht, immer zu klammern, denn das erhöht die l-Iber-

siötlichkeit. Passen Sie aber auf:

c h a r s [ 8 0 ] :s t r c p y ( s . ' T e s t ' ) ;p l i n t f ( " D i e G r ö B e v o n s i s t Z i \ n ' , s i z e o f ( s ) ) ;

Was, glauben Sie wfud für die Größe von s ausgegeben? Es wird 80 ausgegeberg weil

sich sizaof nicht um den lnhdt einer Variablen oder eines Feldes kümmert, 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

erwähnq kann sizeol nicht nur die Größe einer Variablery sondem auch eines Varia-

blentyps bestinunen:

p r i n t f ( " D e r V a r i a b l e n t y p i n t i s t t i B y t e s g r o B ' \ n ' , s ' i z e o f ( i n t ) ) ;

Diese Zeile gibt die Größe des Variablentyps inf aus. Nachdem wir dies nun wissen,

schauen wir uns ein Beispiel an:

/ l i n c l u d e ( s t d i o . h ) l */ f i n c l u d e ( s t r ^ i n g . h )

/ f d e f i n e D A T N A M E " t e s t . t x t 'l l d e f i n e M A X V 0 R N A M E 2 5l l d e f i n e M A X N A C H N A M E 2 0

v o i d s c h r e i b e n ( v o i d )

I

F I L E * f h d :

c h a r v n a m e I M A X V O R N A M E ] , n n a m e I M A X N A C H N A M E ] :

u n s ' i g n e d i n t a l t e r . g r o e s s e :

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

i f ( ! f h d ){

p r i n t f ( ' D a t e i 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 " ) ;

Ie l s e

tp r i n t f ( ' V o r n a m e ( M a x . X i Z e i c h e n ) : " ' M A X V 0 R N A M E - 1 ) :

s c a n f ( ' U s " , v n a m e ) :p r i n t f ( ' N a c h n a m e ( M a x ' X i Z e i c h e n ) : " M A X N A C H N A M E - 1 ) :s c a n f ( ' X s " , n n a m e ) ;p r i n t f ( " A l t e r i n J a h r e n : ' ) :

s c a n f ( " g u " & a l t e r ) ;p r i n t f ( " G r o e s s e ' i n Z e n t i m e t e r n : " ) ;

s c a n f ( " 3 u " & g r o e s s e ) ;

f w r i t e ( v n a m e , s i z e o f ( v n a m e ) ' 1 ' f h d ) ;

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 A M E ' f h d ) :

f w r i t e ( & a l 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 f ( u n s i g n e d i n t ) ' 1 ' f h d ) ;

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 ' ) ;

lI

v o i d l e s e n ( v o i d )I

F I L E * f h d :

c h a r 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 ;

u n s i g n e d i n t a l t e r ' g r o e s s e :

f h d - f o p e n ( D A T N A H E , ' r b ' ) :

i f ( ! f h d )

I

p r i n t f ( " D a t e i 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 " ) ;

e l s e

{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 e , s i z e o f ( n n a m e ) ' 1 ' f h d ) ;f r e a d ( & a 1 t e r , s i z e o f ( a l t e r ) ' 1 ' f h d ) If r e a d ( & g r o e s s e , s i z e o f ( g r o e s s e ) ' 1 ' f h d ) ;

f c l o s e ( f h d ) :

p r i n t f ( " V o r n a m e : % s \ n " , v n a m e ) ;

p r i n t f ( ' N a c h n a m e : % s \ n " , n n a m e ) ;

o r i n t f ( ' A l t e l i n J a h r e n : 1 u \ n ' , a l t e n ) ;p r i n t f ( ' G r o e s s e i n c m : [ u \ n " . g r o e s s e ) ;

ll

Die dazugehörige 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.

Fangen wir mit der Funktio^ sehreiben an. 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 mögli-

chen Eingabezeichen mit FeWgröp-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 Gniße 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 cftar-

Elementen abgespeichert. Dasist natürlich das gleiche, aber es wüd nun einmal anders

angegeben. Zuerst wird die Adrcsse des char-Feldes nnarne übergeben. Dann folgt die

Größe eines char-Elements und danach die Anzahl der im Feld vorhandenen cftar-Ele-

mente. Sie sollten sic-h darüber klar sein, daß die folgenden Zeilen identisch sind:

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 A M E , f h d ) ;

f w r i t e ( n n a m e . s i z e o f ( n n a m e ) , 1 , f h d ) ;

Wenn jemand das Programm später liest, kann er daran aber erkennet! ob der Pro-

grammierer einen String, wie im ersten Fall, oder ein Feld von char-Elementery wie im

zweiten Fal| abspeichert. Denn es kann manchmal nützlich seiru ein Feld von clrar-Ele-

menten 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 dritte Ttorife-Anweistrnt ist nicht erklärungsbedürftig. Die vierte Anweisung be'

nutzt für den siz-eofoperator nicht den Variablennamery sondern den Typ der Varia-

blen. Dies ist möglidr" aber nicht elegant. Denn sollten Sie in der Definition der Varia-

blen eine Typänderung vornehmerL müssen Sie dies auch in derfnrite-Anweisung ma-

chen. Lassen Sie aber die Länge über den Variablennamen bestimmeru wie in der drit-

ten Anweisung, dannbleibt Ihnen die Anderung der fwrtte-Anweisung erspart.

sie sollten sich angewöhnen alle im Programm benutzten Konstanten als Makros zu

definiereru wenn sie eine Konstante irgendwann einmal ändern wollerL ändem sie

nur das Makro, und die Anderung ist im ganzen Programm wirksam' Haben Sie je'

doch die Konstante direkt angegeben, müssen sie das ganze Programm durchforstery

um alle Vorkommnisse det K-oist"nt t zu finderu was bei langen Programmen sehr

mühsam sein kann.

Die Funktion lescz muß nicht besProchen werder\ denn sie müßte ohne weiteres ver-

ständlich sein.

23.g Verändern des Dateipositionszeigers

st"tt"n ri" sich folgendes Problem vor: sie haben eine Datei, die ein Feld mit lfi)fi)O inf-

werten enthält. wenn sie jetzt den 8ü)c[. wert brauchm, milssen sie, nadrdem sie die

Datei geöffnet haben, zuerst die 7999rüerte, die davor stehery lese& um an die Positi-

or, "rrt*"n. Dies ließe sictr vermeiden, wenn es die Möglidrkeit gäbe, nach dem

öffrren der Datei den Dateipositionszeiger direkt auf das 80000. Element zu setzen und

nur dieses dann zu lesen. Ünd diese Möglichkeit gibt es, zumindest für Binärdateien'

fsetpos

6-ie F-tior! die dem Dateipositionszeiger einen neuen Wert zuweist, heißt fsetpos.

Sie wird folgendermaßen aufgerufen:

f p o s - t P o s i t i o n ;

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

Die Variable a enthält den Wert Q wenn das Setzm des Dateipositionszeigers erfolg-

."i.h *"r. Bitte beachten Sie, daß, obwohl der Wert der Variablen position nicht verän-

dert wird, deren Adresse übergeben werden muß. Dies bedeutet auö daß an dieser

Stelle keine Konstante benutzt-werden kann. Der Variablentyp ircs-t ist ein selbstde'

klarierter Variablentyp und zählt nicht zu den Grundvariablentypen von C' Wie man

eigene Variabl""typä" deklarieren kanru temen wir in einem späteren KaPitel. fsetpos

lOlcht auch das Dateiende-Flag. Doch schauen wir uns nun ein Beispiel an' Die Grund-

i"t" a* folgenden Funktion iit ale Eunttionlesen aus dem Programm,,PRG2342..".

Di-e Funktio:n wurde so umgeändert, daß von den mit sdreiban gepeidrerten Daten

nur noch die Größe eingelesen wird. um die Funktion auszutesterL setzen sie diese am

bestm ftir die Funktion lesez aus dem vorherigen Beispiel ein'

v o i d l e s e n 2 ( v o i d ) / * P R G 2 3 - 0 3 ' C * /

tF I L E * f h d ;

c h a r v n a m e I M A x V O R N A M E ] ' n n a m e I M A X N A C H N A M E ] ;

u n s i g n e d i n t a l t e r , g r o e s s e ;

f p o s - t s k i P :

f h d - f o o e n ( D A T N A M E , ' r b ' ) ;

i f ( ! f h d )

{o r i n t f ( ' D a t e i 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 ' ) ;

Ie l s e

{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 ) ;

f s e t p o s ( f h d , & s k i P ) ;

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 ' l o s e ( f h d ) ;

p r i n t f ( ' G r o e s s e i n c m

I

: 1 u \ n ' . g r o e s s e ) ;

Es wüd eine variable namens shp vom \p fpos_t definiert. In ihr wird die summe derIängm der zu überspringendm Datm gespeichert. Nach dem öffnm der Datei wirrd

Ytfutp* der Dateipositionszeiger an die Stelle vor den gespeicherten Daten der Grä-

ße gesetzt. Die restlichen Anweisungen mtsprechen d""Ä a", ursprünglichen Funkti-on lesez- Die Variablen onamc, nname und alter wurden definiert, obiohl"sie nur zur Be-slmmung der zu überspringendm Daten benutzt wurden. Es kann sein, daß der com-piler eine Warnung ausgibt, daß diese drei Variablen nicht benutzt wurden. Sollte diesder Fall seir\ brauchen sie sich in diesem speziellen Fall nicht daran zu stören.

fgetpos

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

f p o s _ t p o s i t i o n ;

a - f g e t p o s ( f h d , & p o s . i t i o n )

Der Aufnrf stinmt exakt mit dem vonfefpos überein, nur dasfgeeosietzt, anstatt denWert der Variblen position in den Dateipositionszeiger zu schrei-beo d�en Wert des Da_teipositionszeiters in die Variable position schleibt. Sollte die Funktion ihre Aufgabeordnungsgemäß erfüllt habe& grbt sie den Wert 0 zurück.

fseek

Es grbt eine weitere Funktiory mit der sich der Dateipositionszeiger verändern Iäß!und die ist gleidrzeitig auch die komJortabelste. Sie heiit feeek unjkann mit verschie-denen Modi aufgenrfen werrdm:

a - f s e e k ( f h d , d i s t a n z , m o d u s ) IEs stehen folgende Modi zur Verfügung:

SEEK-SE'T Der Dateipositionszeiger wird auf den Dateianfang gesetzt undbekorrmt den Wert von dislanz hinzuaddiert. Bei diesem Modusmaöm nur positive Werte für distanz einen Sinn. Der Aufnrf mitdiesem Modus kommt in der Wirkung dem Aufruf vonl9et-pos(ftd,Eposition) gleidl wenn posifion und ilßtanz den gleichenWert haben.

SEEK-END Der Dateipositionszeiger wird auf das Dateiende gesetzt, undbekommt den Wert von disfanz hinzuaddiert. Bei diesem Modusmachen nur negative Werte für dislazz Sinn.

SEEK-CUR Zum Dateipositionszeiger wird der Wert vonilistanz hinzuaddi-ert. Dies ist der einzige Modus, bei dem positive und negativeWerte für drsfanz sinnvoll sind. Der Aufruf entspricht derAnweisungsfolge:

Thbelle 23.3: Die Motli aon ßeek

f g e t p o s ( f h d , & p o s i t i o n ) ;P o s i t i o n + - d i s t a n z ;f s e t p o s ( f h d , & p o s i t i o n ) ;

wollen sie zum Beispiel den Dateipositionszeiger um zwei Bytes nach vorne beweger\machen Sie dies so:

f s e e k ( f h d , 2 , S E E K _ C U R ) ;

Die für fseek zw verfügung stehenden Modi sind Makros, die in der Headerdateisfdio.ft definiert sind..yteek liefert 0 zurück, wenn das Verändem des Dateipositionszei-gers fehlerfiei vonstatten Sln'rg.fs"ek löscht außerdem noch das Dateiende-Flag.

r.*i"d

Die letzte Funktion heißt rewind und setzt den Dateipositionszeiger auf den Anfangder 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,etenenFehler im Makro errno.

23.4 Alleemeines zu Dateien

Es werden jetzt noch einige Funktionen besprochen, die das Arbeiten mit Dateien un-terstützen und damit auch vereinfachen.

fteoPen

AIs erstes wäre da die Funktion freopen. Sie sdrließt eine Datei und öffnet eine andere.

Der Aufnrf sieht folgendermaßen aus:

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

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 geöffrret. Die

A&esse der zugehörigen FILE-Stmktur wüd in natftd gsperchert. Sollte ein Fehler auf-

treteq errth:ilt neuftil denWert 0. Der Aufruf errtspridrt folgender Anweisungsfolge:

f c l o s e ( a l t f h d ) :n e u f h d - f o p e n ( n a m e , m o d u s ) ;

frry^ kann gut dazu benutzt werder1 einem Zeiger auf eine FILE-Struktur eine neue

Datei zuzuweisen:

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

remove und renaure

Zwei Funktioneru die dirckt mit dem Dateinamen operiere4 sind remove und rename.

a- remove( name ) :

renrooe löscht eine Datei namens name und dbt bei Erfolg den Wert 0 zurück. name isldie Adresse eines Strings.

a - r e n a m e ( a l t e r n a m e . n e u e r n a m e ) ;

renamebenelnl.lt eine Datei namens alfsrname inneuername run. Bei Erfolg wird der Wert0 zurückgegeben. altername rund neuername sind Skingadressen. Zum Beispiel löscht

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

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

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

benennt die Datei namens ,,test.txt" in den Namen um, den die Stringvariable nameenthält.

tmpnam und tnpfile

Wenn man aufgrund bestimmter Umstände eine Datei erzeugen muß, die aber vor Be-endigung des Programrns wieder gelöscht wird, also eine sogenannte temporäre Da-tei, dann steht man vor dem Problem, einen Namen ftir die Datei zu wählen, der ein-zigarhgist. Dies ist wichtig, damit nicht eine andere Datei überschrieben wird, weil siezufällig den gleichm Namen hat. Um dieses Problem zu umgeherL wurde in C eineFunktion namens tmpnam implementiert, die einen einzigartigen Namen erzeugt.tmpnam wird folgendermaßen aufgerufen:

c h a r a [ 8 0 ] ;

t m p n a m ( a ) l

tmpnam schreibt dieserr Namen in die Stringvariable a. Aber tmpnam ist nodr komforta-ble4 denn sie kann auch so aufgerulen werden:

c h a r * a ;

a : t m D n a m ( N U L L ) ;

NULL ist die Makrodefnition eines Ttigers, der den Wert 0 hat, also auf Adresse 0zeigt. Ein 7*igea der auf die Adresse 0 zeigt, steht nun aber in C für einen 7*iget" detauf niöts zeigt. Deswegen geben viele Funktioneru zum Beispiel/opcn, bei Erfolg ei-nen Zeiger auf die FILE-Struktur und bei Mißerfolg den Wert 0 zurüclq weil danachdet Taiger auf Adresse O zr:ig!., was bedeutet, daß er auf nichts zeigt. Man hätte auchfolgendes schreiben können:

a - t m p n a m ( ( v o i d * ) 0 ) ;

Aber es ist viel elegante4 die Makrodefinition zu benutzen. Doch kommenwb zu tmp-ncn zurü& Rufen wir die Funktion so wie oben beschrieben auf, übergeben wir ihrden Wert 0 oder einen Nullzeiger. Das heißt für die Funktiorv daß wir keinen Zeigerübergeben. Sie reserviert darauflrin selbst Speicher und schreibt den von ihr erzeugtmNamen in diesen Speicher. Der Rückgabewert ist dann die Adresse des Speichers, in-dem der Name steht. Der Speicher wird automatisch bei Programmbeendigung fteige-geben. Er kan+ falls ein neuer Name gebraucht wird, wieder andie tmptum-Funktionübergeben werderl so daß der alte Name überschrieberr wird und kein neuer Speicherreserviert werden muß.

Eine weitere Funktioru die einem noch mehr Arbeit als tmpnam abnimmt, ist tmpfile.Sie wird folgendermaßen aufgerufen:

f h d - t m p f i 1 e ( ) ;

Die Funktion öffnet eine binäre Datei zur Ein- und Ausgabe und liefert die Adresse derFILE-Stnrktur zurück, über die die Datei verwaltet wird. Der Aufruf von tmpflekommt folgender Anweisungsfolge gleich:

a - t m D n a m ( N U L L ) :f h d - f o p e n ( a , ' w b + ' ) ;

Wobei a ein Zeiger auf einen String ist. tmpflehat jdoch den Vorteil, daß der Speiche4,der den Namen aufnimmt, nur für das Öffnen der Datei reserviert und danach wiederfreigegeben wird.

fenor

a - f e r r o r ( f h d ) :

Sollte ein Fehler im Zusammenhang mit der Dateild aufgetr,eten seir\ hat a einen Wertungleich Null.

23.5 Gepufferte Dateien

C ien zu puffem' Das bedeutet.daß nicht ie'

desmal *"* ä Zeichen in diebatei geschrieben wird, dies auch tatsächlich auf der

Festplatte oder Diskette gespeichert wird. Vielmehr wird gewartet, bisdet Puffer voll

ist, und dann werden mit einem Zugnlf. alle Daten gespeichert. Dies erhöht die Verar-

beitungsgeschwindigkei! weil es schneller geht, einen großen Datenblock einmal zu

r.h*iüÄ, ab kleinJmehrmals. Dies macht sich besonders bei Disketten bemerkbal

die sich ia im Normalfall nidrt drehen, sondem lediglich beim Zugnfr. in Rotation ver-

setzt werden.

setvbuf

ffiltioru mit der ein Puffer für eine Datei angelegt werden kann, heißt setvbuf.

Sie wird wie folgt aufgerufen:

a - s e t v b u f ( f h d , a d r e s s e , m o d u s . g r o e s s e )

Fiir die Datel die mit der FILE-Stnrktur verbunden isq aut dte N znigt, wird ein Puffer

angelegt, det groesse Bytes groß ist und an der Adresse aitresx toeg! Die Adresse muß

die Startadresse eines char-ieldes sein. xtobuf gpbt den Wert 0 zurück, wenn alles ord-

nungsgemäß ausgeführt werden konnte. Fur setobuf glbt es drei Modi:

ungen

Kommerr wir nun wieder zu ein paar Übugerv um das bisher Gelemte zu festigen.

oSchniben Sie ein Programru welches Sie nach dem Dateinamen einer Tbxtdatei fuagt.

Geben Sie diese Datei dann auf dem Bildschirm aus. Berücksichtigen Sie, daß Sie nicht

wissen können, wie lang die längste Zeile der Datei ist'

oScheiben Sie ein Prograrnrl welches Sie nach dem Namen einer Quelldatei gnd einer

äeldatei fragt. Der Tett d"r in der Quelldatei steht, soll zeilenweise umgedreht wer-

den und in der Zieldatei abgespeichert werden. Benutzen Sie hierfür Textdateien' Ange

noruner1 die Datei hat folgenden Inhalt:

Es ist warm

JohannOttoWilli klettert

Dann soll die Zieldatei so aussehen:

mraw tsi sEnnahoJottOtrettelk illiW

Der Einfachheit halber sollten Sie davon ausgeheru daß in der Textdatei keine Zeile

länger als 300 bchcn'rst.

Andern Sie die Programme aus 24.3 und 24.4 so um, daß nicht mehr das erste Vorkom-

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-

@Ana"- Sie die Programme aus 24.3 und 24.4 so um, daß nur gezählt und ausgegeben

wird, wie olt der entsprechende String in der Datei vorkommt'

@Andem Sie das Programm für 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 poäi Textdatei gescluieben werden. Am Ende der Datei sollen Sie die Anzahl der

Värkommnisse ond d"r, String selber ebenfalls noch vermerken. Das Programm soll

nadr dem Namm der zu erstellenden Textdatei fragen. Der Inhalt der erstellten Datei

sollte dann ungefähr so aussehen (bei dl€i Vorkommnissen des Strings "fubeit"):

Z e i l e 3 a n P o s i t i o n 2 3

Z e i ' l e 1 9 a n P o s i t i o n 3Z e i l e 1 2 9 a n P o s i t i o n 1 7

V o n k o m m n i s s e i n s g e s a m t : 3

G e s u c h t e r S t r i n g : ' A r b e i t '

@Tndem Sie das Programm aus 24.3 so urn" daß eine neue Datei erzeugt wir4 in der alle

vorkommnisse des suchstrings in der Datei gelöscht 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 n s 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:

D a s l l e t t e r u n d B l u m e n s i n d s c h ö n . A b e r S t r a E e i s t d r e c k i g .

Tabellc 23.4: Die Moili oon setobuf

_I)FBF, -IOLBF und -IoNBF sind Makrodefinitionen und in der Headerdatei stdio'h

enthalten.

lin Beispiel fiit das Einrichten eines Puffers wäre folgendes:

c h a r a t 1 0 0 l ;F I L E * f h d ;

i n t o k :

f h d - f o p e n ( ' t e s t . t x t ' , " w " ) :

o k - s e t v b u f ( f h d . a . - l 0 F B F . s i z e o f ( a ) ) ;

f l c o s e ( f h d ) :

xtobufhataber auch eine ähnliche Eigenschaft wie tmpnam: Soute als Adresse des Puf-

fers der wert 0, also ein Nu[zeite4 überyeben werder! reserviert die Funktion eigen-

ständig Pufferspeicher der angegebenen Gxiße und gibt ihn auch automatisch beim

Schließen der Datei wieder frei. Um dies zu bewerkstelligery mtißten wü im obigenBeispiel delrt xtobuf-Aufmf folgendersraßen 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 wärc 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 Grciße muß nämlich als ein Variablentyp namens sr'ze-t angegeben werden. fedochsollte man diese explizite Tlrpumwandlung nur vornehmerL wenn der Compiler sieverlangt. Ansonsten fördert sie nur die Unübersichtlidrkeit.

setbuf

Die Funktion xtbuf dient zum einfacheren Aufruf von setobuf. Schauen wir uns einmalden Aufnrf an:

- s e t b u f ( f h d , a d r e s s e )-

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

s e t v b u f ( f h d , a d r e s s e , _ l 0 F B F , B U F S I Z ) ;

Wobei BUFSIZ ein in stdio.h vordefiniertes Makro ist. Hat adrcsx aber den Wert 0, wirdx tobuf tolgendermaßen 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 gemeabspeichern wtirderu obwohl der Puffer noch niciht voll genug ist, um von C automa-tisch 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 gehörenden Datei wird abgespeichert. War die Abspeidrerung er-folgeich, 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.

23.6 Kontrollfragen

1. AuI welche Besondeüreit 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?

osclneiben sie ein Programrrr' welches sie nach dem Namen einer Tbxtilatei fragt. Da-

nach soll man die Möglichkeit zur Eingabe eines Strings haben' Das Programm soll

dann prü(en ob der eingegebene String in der Datei enthalten ist oder nicht. Ist er ent-

halten, soll die qste stelle,Äder der string gefunden wurde in Form von Zeilennum-

mer und Position des strings innerhalb der Zeile ausgegeben werden. wenn sie einen

suchstring angeben, der aus mehreren wörtem besteht, kann es vorkommerl daß er

sich über lweioder mehrere Zeilen erstr,eckt- Sie sollen aber nur die Vorkommnisse des

Suclrstrings berücksichtigen, dieineiner Zeile stehen. C'ehen Sie wieder davon aus, daß

keine Zeile länger als 30o Zeiüen ist-

oSchreiben Sie ein Programm mit der gleichen Funktionalität wie in Aufgabe 3, nur sol-

len Sie hier binäre Dateien beaöeiten können. Bitte bedenken Sie daß Sie bei dieser

Aufgabe nicht mehr zeilenweise vorgehen können. 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 müssen berücksichtigen daß,

werur Sie die Datei mitlread blockrveise einlesen, das gesuöte Wort oder der gesuchte

String teilweise im einen und teilweise im anderen Block enthaltqr sein könnte. Es gibt

versÄiedene Lösungswege. [.assen Sie sich einen einfallen. Das gleiche Problem tritt

übrigens bei allen Aufgaben auf, die sidr auf diese hier beziehen'

@

-IOFBF Die Ausgabe wird voltständig gepuffert.

-IOLBF Die Ausgabe wird zeitenweise gepuffert.

-IONBF Die Ausgabe wird nicht gePuffert.

schreibensie ein Programnq weldres sie nach dem Namen einer Textdatei fragt. An-schließend soll das Programn das Vorkommen aller Buchstaben und Zaftlen zählenund in eine Thxtdatei schreiben" deren Namen der Benutzer voher eingeben kann. Derlnhalt der Textdatei sollte ungefähr so ausseherq wenn die bearbeitetä Datei "text.bxt"

heißt:

Zählung der Datei "text.kt"

A=23B-18cd

'3-2

Et4

9=2Untersöeiden Sie nicht zwischen Groß- und Kleinschr,eibung. Große und kleine Buch-staben sollen zusammengefaßt angegeben werden.

@Andem sie das Programm avs24.9 so unu daß nicht mehr die Anzahl der Zeichen nu-merisch sondern grafisch dargestellt wird. Das Beispiel as 249 könnte zum Beispielso aussehen:

Zählung der Datei "text.b(t"

AAAAABBBBcc

ä44

g

Einheit : 5 Zeichen aufgerundet.

Dies ähnelt einer Art Balkendiagramm und erleichert den Vergleich der Häufigkeiten.wie oben im Beispiel sollten sie für jede angefangene 5er4ruppe ein neues Zeichenhinzufügen.

@Andern Sie das Programm aus 24.10 so uru daß die starre 5er4ruppe vom Prograu nvariabel gehalten wird. Eine G-pF sollte mindestens aus einem Zeichen bestehsuDer Balken des häu-figsten Zeichens sollte aber nicht größer als 40 Zeichm sein. DasProgramm muß deshalb die Anzalrl der Zeicheo die zu einer Einheit zusamrnerrgefaßtwerderL selbst bestimmen-