Forum: Compiler & IDEs programmieren aufgabe


von Gerhard (Gast)


Lesenswert?

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
long printLines(FILE *filehandle, long lines){
2
    char text[TEXTMAX];
3
    int i;char zeichen;
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
    return 0;
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.

von Karl H. (kbuchegg)


Lesenswert?

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, .....

von Mik (Gast)


Lesenswert?

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.

von guest (Gast)


Lesenswert?

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
return 0;

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:
1
if(x){
2
 return 0;
3
}
4
if{y}{
5
 return -1;
6
}
usw...

von guest (Gast)


Lesenswert?

Gerhard schrieb:
>
1
 for(; zeichen != '\n' && zeichen != EOF ;)

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.

von Stefan R. (srand)


Lesenswert?

guest schrieb:
>>
1
 for(; zeichen != '\n' && zeichen != EOF ;)
>
> 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?

von Rolf M. (rmagnus)


Lesenswert?

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.

von Stefan E. (sternst)


Lesenswert?

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'.

von Jarald Hhunke (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Diskette

Was ist denn das?
Ich glaube, so etwas schon mal im Deutschen Museum gesehen zu haben ;-)

von Mik (Gast)


Lesenswert?

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'.

von Rolf M. (rmagnus)


Lesenswert?

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.

von Gerhard (Gast)


Lesenswert?

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?

von Rolf M. (rmagnus)


Lesenswert?

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.

von Steffen (Gast)


Lesenswert?

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

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.