Ich studiere gerade an der technischen Universität in Wien. Einige
Kollegen haben mir geraten mich hier mit meinen Problemen zu wenden, ich
hoffe ihr könnt mir dabei helfen.
Die Aufgabe lautet folgende:
Implementieren Sie die Funktion
long printLines(FILE *filehandle, long lines);
die lines Zeichenaus einer Datei ausgibt. filehandle soll der Pointer
auf die bereits geöffnete
Datei sein. Die Funktion soll 1 zurückgeben, falls während der Ausgabe
das Dateiende erreicht wurde,
ansonsten 0. Falls die Datei nicht gelesen werden kann, so gebe die
Funktion eine Fehlermeldung aus und
den Wert -1 zurück.
Also das Programmieren an sich ist nicht so das Problem. Eher die
Formulierung verstehe ich nicht ganz. Also ich soll eine Funktion
schreiben, die n Zeilen aus einem Textfile ausliest. Das habe ich einmal
so gemacht:
1
longprintLines(FILE*filehandle,longlines){
2
chartext[TEXTMAX];
3
inti;charzeichen;
4
5
for(i=0;i<lines;i++){
6
for(;zeichen!='\n'&&zeichen!=EOF;){
7
zeichen=fgetc(filehandle);
8
printf("%c",zeichen);
9
}
10
zeichen=0;
11
}
12
13
return0;
14
}
Und jetzt kommt das unverständliche. Rein grammatikalisch ist es zwar
alles korrekt, aber rein technisch verstehe ich den Sinn nicht.
Die Funktion soll 1 zurückgeben falls wärend der Ausgabe das EOF
erreicht wurde? Wie bitte? Wie soll denn das gehen oder wie soll ich
diese sinnlose Aufgabe überhaupt programmtechnisch sinnvoll realisieren?
ansonsten soll sie 0 zurückgeben. Heißt das, in meinem Fall würde sie
immer 0 bzw 1 zurückgeben?
Und jetzt kommts: Falls die Datei nicht gelesen werden kann, dann return
-1. Aber filehandle ist doch schon die geöffnete Datei. D.h. diese
Kontrolle musste vorher schon passiert sein.
Bitte vereiht mir meine dummen Fragen, aber ich verstehe so manch Zweck
nicht.
Danke schon mal im Voraus.
Gerhard schrieb:> Das habe ich einmal> so gemacht:
Du hättest dir eine Menge Arbeit sparen können, wenn du ganz einfach die
Funktion fgets benutzt hättest. Denn die liest genau 1 Zeile in einen
von dir bereitzustellenden Buffer.
> Die Funktion soll 1 zurückgeben falls wärend der Ausgabe das EOF> erreicht wurde? Wie bitte?
Was heißt da "Wie bitte?". Wenn die Vorgabe so lautet, dann lautet sie
halt so.
> Wie soll denn das gehen oder wie soll ich> diese sinnlose Aufgabe überhaupt programmtechnisch sinnvoll realisieren?
Indem du überprüfst, ob du nach einem Lesevorgang auf EOF gestossen
bist. Dazu gibt es eine Funktion: feof()
Regel römisch 2 in der C Programmierung: C hat zwar eigentlich gar nicht
mal so viele vorgefertigte Funktionen in den Systemlibraries. Aber
wenigstens die sollte man kennen.
> ansonsten soll sie 0 zurückgeben. Heißt das, in meinem Fall würde sie> immer 0 bzw 1 zurückgeben?
Nö. -1 kann auch noch sein.
Je nachdem ob es ein EOF (also ein 'End of File') gab, oder eben nicht.
Oder ob sonst irgendein Fehler aufgetreten ist.
> Und jetzt kommts: Falls die Datei nicht gelesen werden kann, dann return> -1. Aber filehandle ist doch schon die geöffnete Datei. D.h. diese> Kontrolle musste vorher schon passiert sein.
Auch während des Lesens können Dinge passieren. Jemand nimmt die
Diskette aus dem Laufwerk, die CD hat einen Kratzer,
Netzwerkverbindungen brechen zusammen, .....
Gerhard schrieb:> Also das Programmieren an sich ist nicht so das Problem.
Mal ganz ehrlich, es ist ein riesengroßes Problem für Dich. Wie kann
man nur soviel Fehler in so bisschen Code machen? Und wie kann man so
wenig Code so unübersichtlich gestalten? ... und so wenig von der
Aufgabe implementieren?
Gerhard schrieb:> wie soll ich> diese sinnlose Aufgabe überhaupt programmtechnisch sinnvoll realisieren?
Für Dich ist diese Aufgabe absolut keinesfalls sinnlos. Sondern etwas
mit dem DU Dich mal ausführlich beschäftigen solltest. Du hast dringend
Bedarf hier deine Lücken zu schließen. Das sind Basics. Für einen
erfahrenen Programmiere ist sie allerdings sehr trivial, aber wenn man
es lernen will muss man sich mit so etwas auch mal ausführlich
auseinandersetzte und sich nicht nur Lösungen erbetteln.
Du solltest Dich mal etwas einlesen, die hier etwas vorzukauen, hilft
Dir absolut nicht. Beschäftige Dich damit ! Ein Ansatz ist z.B. Dir mal
alle Funktionen anzuschauen die es im Zusammenhang mit getc() gibt und
dann die richtigen auswählen.
Wenn du dann was gefunden hast, dann stell es hier vor, dann können
wird drüber reden.
Gerhard schrieb:> Heißt das, in meinem Fall würde sie> immer 0 bzw 1 zurückgeben?
Nein, so wie du das gemacht hast würde sie nicht:
Gerhard schrieb:>
1
return0;
Deine Funktion würde IMMER 0 zurückgeben.
Du müsstest Bedingungen (switch-case oder if) einfügen und dort dann den
jeweiligen Rückgabewert reinschreiben.
Als Beispiel:
das Erste und letzte Semikolon gehören nicht dort hin.
Bin mit dem folgenden etwas unsicher, wäre nett wenn jemand mit mehr
Ahnung sich dazu äußern könnte:
EOF -> hinter dem letzten Zeichen in deiner Datei. Quasi das
ALLERALLERLETZTE Zeichen
NULL -> hinter dem letzten Zeichen in der Zeile.
Du liest also mit deiner Schleife gleich die ganze Datei, statt nur
einer Zeile aus.
>> das Erste und letzte Semikolon gehören nicht dort hin.
Du, ganz ehrlich, wer die allereinfachste C-Syntax aus der zweiten
Unterrichtsstunde nicht kennt, der kann doch auch einfach mal die Finger
ruhig halten, findest du nicht?
Gerhard schrieb:> Die Funktion soll 1 zurückgeben falls wärend der Ausgabe das EOF> erreicht wurde? Wie bitte? Wie soll denn das gehen oder wie soll ich> diese sinnlose Aufgabe überhaupt programmtechnisch sinnvoll realisieren?
Wieso ist das sinnlos? Der Aufrufer deiner Funktion soll halt die
Möglichkeit haben, zu erkennen, ob tatsächlich soviele Zeilen ausgegeben
werden konnten, wie angefordert oder nicht.
Stell dir mal vor, mit deiner Funktion soll ein Programm geschrieben
werden, das die ersten 10 Zeilen einer Datei ausgibt, und es müssen
zwingend genau 10 Zeilen sein. Dann muss das Programm irgendeine
Möglichkeit haben zu erkennen, ob das auch funktioniert hat, damit es
ggf. reagieren kann.
> ansonsten soll sie 0 zurückgeben. Heißt das, in meinem Fall würde sie> immer 0 bzw 1 zurückgeben?
Was meinst du mit "in meinem Fall"? Laut Aufgabe muss sie 0, 1 oder -1
ausgeben können, also ist das auch so zu implementieren, PUNKT! Dinge
einfach wegzulassen, weil man den Sinn nicht erkennt, ist so ziemlich
das schlimmste, was man tun kann, wenn man nach einer Spezifikation
Software schreibt.
> Und jetzt kommts: Falls die Datei nicht gelesen werden kann, dann return> -1. Aber filehandle ist doch schon die geöffnete Datei. D.h. diese> Kontrolle musste vorher schon passiert sein.
Die Kontrolle, ob die Datei geöffnet werden konnte, ist hoffentlich
schon erfolgt. Eine erneute Prüfung schadet aber nicht. Ob es beim
lesen einen Fehler gibt, z.B. weil die Datei auf einem USB-Stick
liegt, der mitten beim Lesen rausgezogen wird, ist beim Öffnen noch
nicht bekannt, da auch Software nicht in die Zukunft sehen kann.
Genrell ist es ja gut, Dinge zu hinterfragen, aber wenn du eine
Spezifikation bekommst, nach der du was implementieren musst, dann tu
das doch einfach. Ob das sinnvoll ist oder nicht, ist an der Stelle
nicht unbedingt zu erkennen.
guest schrieb:> for(; zeichen != '\n' && zeichen != EOF ;)> das Erste und letzte Semikolon gehören nicht dort hin.
Natürlich gehören die dort hin. Ich würde in so einem Fall aber gleich
eine while-Schleife nehmen. Was hier schlimmer ist, ist, daß die Prüfung
auf EOF an der falschen Stelle ist. Das ist ein klassischer
Anfängerfehler.
Rolf Magnus schrieb:> Was hier schlimmer ist, ist, daß die Prüfung> auf EOF an der falschen Stelle ist. Das ist ein klassischer> Anfängerfehler.
Außerdem erfolgen die ersten Tests mit nicht initialisiertem 'zeichen'.
guest schrieb:> EOF -> hinter dem letzten Zeichen in deiner Datei. Quasi das> ALLERALLERLETZTE Zeichen
Nein. eigentlich ist es kein zeichen das gespeichert wird.
>> NULL -> hinter dem letzten Zeichen in der Zeile.
NULL ist ein Pointer und nicht das letzte Zeichen eine Zeile.
Das letzte Zeichen einer Zeile ist EOL. welches Zeichen das Ende einer
Zeile in einer Datei markiert ist unterschiedlich. Bei MSDOS sind es
z.B: zwei Zeichen.
Du meintest evt das eine einer Zeichenkette, das ist aber auch nicht
NULL, sondern '\0'.
Mik schrieb:> guest schrieb:>> EOF -> hinter dem letzten Zeichen in deiner Datei. Quasi das>> ALLERALLERLETZTE Zeichen> Nein. eigentlich ist es kein zeichen das gespeichert wird.
Heute eher nicht mehr. Früher war das aber nicht unüblich.
>> NULL -> hinter dem letzten Zeichen in der Zeile.> NULL ist ein Pointer und nicht das letzte Zeichen eine Zeile.
NULL ist eine Nullzeigerkonstante.
> Das letzte Zeichen einer Zeile ist EOL. welches Zeichen das Ende einer> Zeile in einer Datei markiert ist unterschiedlich.
In der Datei ja. Die C-Standardbibliothek konvertiert aber beim Einlesen
eines Textfiles automatisch das systemspezifische Zeilenende in ein
'\n'.
> Du meintest evt das eine einer Zeichenkette, das ist aber auch nicht> NULL, sondern '\0'.
Was allerdings beides im Prinzip das gleiche ist wie 0.
Karl Heinz Buchegger schrieb:> Du hättest dir eine Menge Arbeit sparen können, wenn du ganz einfach die> Funktion fgets benutzt hättest. Denn die liest genau 1 Zeile in einen> von dir bereitzustellenden Buffer.
Aber wie soll ich dann feststellen, ob EOF erreicht wurde?
Gerhard schrieb:> Aber wie soll ich dann feststellen, ob EOF erreicht wurde?
Auch wenn's unglaublich klingt: Auch fgets() bietet die Möglichkeit
dazu. Ich überlasse dir die Aufgabe, in der Doku nachzulesen, wie. Du
solltest schon in der Lage sein, so einfache Dinge selbst rauszufinden,
sonst wird dein Programmierer-Dasein für dich selbst und das Forum sehr
mühsam werden.
Hallo Gerhard,
Gerhard schrieb:> ... Einige> Kollegen haben mir geraten mich hier mit meinen Problemen zu wenden,
Möglicherweise haben sich da die Kollegen einen Scherz erlaubt. Du
merkst ja an den Antworten selbst, dass hier nicht immer feinfühlig
vorgegangen wird. Wenn Du aber darüber hinweggucken kannst, und noch die
Spreu vom Weizen trennst, dann kann man auch hier im Forum sinnvolle
Hinweise finden. ^^
> Die Funktion soll 1 zurückgeben, falls während der Ausgabe> das Dateiende erreicht wurde,
Das musste ich auch zweimal lesen. Es sollte wohl während des
"Einlesens" heißen.
Bevor Du Dein Programm schreibst, mach Dir einen kurzen Ablaufplan.
Bspw:
1. Lese Zeichen
2. Fehler aufgetreten? Rückgabe -1
3. EoF? Rückgabe 1
4. Zeichen ausgeben
5. n-tes Zeilenende erreicht? Rückgabe 0
6. Weiter mit 1
fgetc() ist einfacher zu handhaben als fgets(), da hast Du nichts falsch
gemacht. Die andere Funktion, die Du noch benötigst, ist ferror()
(sicherheitshalber auch clearerr()). Guck Dir die
Funktionsbeschreibungen genau an, und dann leg einfach nochmal los.
Grüße, Steffen