Letztes Zeichen wiederholt sich mit fopen
-
Hallo,
ich möchte ein Programm schreiben, welches Werte einliest und in eine Datei schreibt. Nach der Eingabe sollen die eingegebenen Werte summiert werden.#include <stdio.h> #include <stdlib.h> main() { int i, temp, anzahl,summe=0, zahl=0; //Filepointer FILE *fptr; //Überprüfen auf falsches Öffnen if((fptr=fopen("input.txt","w"))==NULL) { printf("Fehler beim oeffnen der Datei"); }else{ //Anzahl festlegen printf("Wieviele Werte sollen eingegeben werden: "); scanf("%d",&anzahl); //Einlesen der Zahlen bis Anzahl erreicht for(i=0;i<anzahl;i++) { printf("Wert %d: ", 1+i); scanf("%d",&temp); fprintf(fptr,"%d\n",temp); } //Schließen der Datei } fclose(fptr); temp=0; if((fptr=fopen("input.txt","r")) != NULL) { while(temp!=EOF) { fscanf(fptr, "%d", &zahl); summe +=zahl; temp=fgetc(fptr); } }else{ printf("Fehler beim oeffnen der Datei"); } fclose(fptr); printf("Die Flaesche betraegt : %d\n", summe); }
So weit so gut. Das schreiben in die Datei funktioniert und auch das Auslesen.
Wenn ich 3 Werte eingebe 1,2,3 , steht auch in der Datei 1,2,3.
Beim 2 öffnen der Datei mit fopen ist das letzte Zeichen aber doppelt(also 1,2,3,3).
Ich versteh das nicht...in der Datei selber steht ja auch nur 1,2,3.Warum wiederholt sich die letzte Zahl beim zusammen rechnen?
Gruß
aendue
-
Versuch mal selbstständig genau Schritt für Schritt nachzuvollziehen: Wann bekommt temp den Wert EOF und was passiert dann in deinem Programm?
-
Weil du in Zeile 37 das '\n' einliest. Erst danach komm das EOF.
fscanf kann dann nichts mehr einlesen und verändert zahl daher nicht.Du kannst der Rückgabewert von fscanf auswerten. (der Rückgabewert ist z.B das temp bei fgetc)
Benutze die Funktion feof()
-
if((fptr=fopen("input.txt","r")) != NULL) { while(temp!=EOF) { fscanf(fptr, "%d", &zahl); summe +=zahl; temp=fgetc(fptr); } }else{ printf("Fehler beim oeffnen der Datei"); } fclose(fptr); printf("Die Flaesche betraegt : %d\n", summe);
Zuerst bekommt Zahl den Wert 1. Danch wird Summe+Zahl gerechnet(Ergebnis=1)
Dann bekommt Zahl den Wert 2 und wird mit Summe addiert (Ergebnis = 3).
Temp bekommt den Wert 10, da Zeilenumbruch.
Imletzten durchgang bekommt Zahl den Wert 3 und wid mit Summe addiert (Ergebnis = 6)
Jetzt sollte temp denn Wert -1(EOF) bekommen, da ja 3 die letzte Zahl ist die ich eingegeben hab und die in der Datei steht. Die Schleife sollte jetzt abbrechen und der Wert 6 ausgegeben werden.Ich hab das auch alles schon mit dem Debugger überprüft, aber der Dateizeiger hat immer den wert 1233, obwohl in der Datei nur 123 steht...
-
Nein.
Im letzten Durchgang bekommt Zahl den Wert 3.
temp erhält den Zeilenumbruch dahinter.
Die Bedingung ist falsch.
Nun wird nochmal versucht eine Zahl einzulesen.
fscanf() kann das aber nicht (weil nächstes Zeichen ist EOF), und verändert nichts an zahl. zahl (also 3) wird nochmal addiert, erst dann ist EOF in temp.
-
Ahhh...ich habs..DANKE!!!!
feof() hör ich zum ersten mal.
-
aendue schrieb:
Jetzt sollte temp denn Wert -1(EOF) bekommen, da ja 3 die letzte Zahl ist die ich eingegeben hab und die in der Datei steht.
Halt! fgetc liest Zeichen! Du hast "%d**\n**" in die Datei geschrieben.
-
aendue schrieb:
feof() hör ich zum ersten mal.
Wird auch meistens falsch benutzt. Hier willst du sowieso mit dem Rückgabewert von (f)scanf arbeiten. Falls du tatsächlich mal feof benutzen möchtest, denk daran, dass eine Datei eof wird, nachdem über das Ende gelesen wurde, nicht (wie sehr oft falsch gemacht wird, selbst in Lehrbüchern!) wenn der Dateizeiger vor dem Ende steht. Entsprechend müssen Leseschleifen in der Reihenfolge Leseversuch, Prüfung, Verarbeitung gemacht werden. Also im Prinzip genau so wie hier mit dem Rückgabewert von scanf. Wird aber aus unerfindlichen Gründen oft falsch gemacht.
-
aendue schrieb:
feof() hör ich zum ersten mal.
Wegen so etwas gibt es Referenzen:
http://www.cplusplus.com/reference/
Die C-Library ist für dich interessant, die Header sind ohne c vorne und mit .h hinten.
-
Soo ich hab mal bissel probiert und glaube auch verstanden.
if((fptr=fopen("input.txt","r")) != NULL) { while(temp!=EOF) { fscanf(fptr, "%d", &zahl); if(feof(fptr)) { break; } summe +=zahl; temp=fgetc(fptr); } }else{ printf("Fehler beim oeffnen der Datei"); } fclose(fptr); printf("Die Flaesche betraegt : %d\n", summe);
Also temp bekommt denn Wert 10, da Zeilenumbruch. Danach wird mit fscanf das nächste Zeichen eingelesen, da aber EOF ist, bleibt die 3. Jetzt wird mit feof geprüft ob Dateiende schon erreicht ist und bricht dann ab.
Ich glaub ich hab es verstanden...
Vielen Dank an alle Helfer!!!!!
-
Jetzt hast du die Prüfung aber doppelt gemoppelt. Wann soll denn jemals die Prüfung von temp anschlagen?
Und wieso nutzt du nicht den Rückgabewert von scanf, der drückt doch viel stärker aus, was du möchtest und reagiert daher auch auf alle anderen Arten von Fehlern.
Du willst meistens so etwas wie:
while (leseaktion == erfolg) verarbeite_ergebnis;
Hier konkret:
while (fscanf(fptr, "%d", &zahl) == 1) summe +=zahl;
Kürzer und gleichzeitig auch noch besser! Was will man mehr?
-
Der Rückgabewert von scanf:
int retval; ... retval = fscanf(fptr, "%d", &zahl); // Hier kannst du jetzt den Wert von retval überprüfen. Was der zu bedeuten hat, steht in der Referenz zu fscanf. if (retval != ...)
Die Bedingung muss aber nicht in einer if-Abfrage sein. Und den Zwischenschritt mit retval musst du auch nicht machen.
-
Man sollte die Antworten der Anderen schon komplett lesen.