Probleme beim Einlesen von Werten
-
Vorab vielen Dank für Deine Hilfe,
das Inhalt vom Typ char war und die Ausgabe mit %f ist irgendwann beim Ausprobieren schief gegangen.
Hab deine Änderungen vorgenommen und mir wurde dann keine 0.000000 sondern -107374176 ausgeben. Kannst du mir das Erklären?habs jetzt mit fread probiert und die Messwerte werden jetzt richitg angezeigt
fread(&inhalt[i],sizeof(float),1,dateizeiger);
und weiter verarbeiten kann ich die Werte im Programm so auch.
juhu
-
Erst mal ist es interessant, wie du die Daten geschrieben hast.
Mit printf oder mit fwrite. (kannst du die Datei mit dem Editor ansehen)?Wenn du sie mit printf geschrieben hast funktioniert deine Rechnung mit g/sizeof(float) nicht.
Hast du sie mit fwrite geschrieben, kannst du sie nicht mit fscanf einlesen.
-
Hab sie mit fwrite in die Datei geschrieben. Mit fread klappt es jetzt aber.
Bin Anfänger und froh das es jetzt überhaupt klappt. Hat denn fread irgendwelche Nachteile, so dass ich es auf scanf ändern sollte?
-
fread()/fwrite() hat eventuell den Nachteil, daß es nicht portabel sein könnte - und daß du die Daten nicht mit dem Texteditor bearbeiten kannst. Im Gegenzug bekommst du wirklich exakt die selben Werte zurück, die du in die Datei geschrieben hast.
Ansonsten ist es eher wichtig, daß die Einlese-Funktion zur Schreib-Funktion passt - fwrite()/fread() arbeiten mit der binären Repräsentation der übergebenen Daten, fprintf()/fscanf() mit ihrer Darstellung als lesbarer Text.
-
eydasgehtab schrieb:
Hab sie mit fwrite in die Datei geschrieben.
Wie kommt man dann auf die Idee, sie mit scanf() einzulesen?
floats sehen in Binär halt anders aus, als in einer für Menschen lesbaren Form.
http://de.wikipedia.org/wiki/Gleitkommazahl
-
Hab jetzt wieder auf fscanf umgestellt. Jetzt ist das Problem, dass die Dateigröße nicht mehr richtig ermittelt wird. Liegt das jetzt an dem fseek?
Kann man fseek für Textdateien verwenden?Wie kann ich denn jetzt die Dateigröße auslesen?
Cooky451 du hast bei einem Beitrag schon den Rückgabewert von fscanf erwähnt?
Wie geht das denn damit?
-
Zeig doch mal bitte, wie du die Dateien schreibst.
-
Wir haben mal ein Programm geschrieben mit dem wir eine Datei erstellen und Inhalte einfügen können. Hier der Quellcode:
#include <stdio.h> #include <eigene.h> #include <conio.h> //<dateizeiger>=fopen(<dateiname>,<modus>); void datei (char[]); void schreiben (char[]); void lesen (char[]); void groesse (char[]); void main (void) { char name[30]; char wahl; datei (name); do { clrscr(); printf("\t\tDateinamen eingeben..........1\n"); printf("\t\tWerte in Datei schreiben.....2\n"); printf("\t\tWerte aus Datei lesen........3\n"); printf("\t\tGroesse der Datei anzeigen...4\n\n"); printf("\t\tProgramm beenden...........X/x\n\n"); wahl=getch(); switch (wahl) { case'1':datei (name);break; case'2':schreiben (name);break; case'3':lesen (name);break; case'4':groesse (name);break; } }while (wahl!='x'&&'X'); } void datei (char name[30]) { clrscr(); printf("\nBitte Name der Datei: "); scanf ("%s",name); } void lesen (char name[30]) { float wert; FILE*datei; datei=fopen(name,"r"); if (datei) { clrscr(); do { //fscanf(datei,"%f ",&wert); fread(&wert,sizeof(float),1,datei); if (!feof(datei))printf("%f\n",wert); }while (!feof(datei)); fclose (datei); }else printf ("\Aus der gewünschten Datei kann nicht gelesen werden"); getch(); } void schreiben (char name[30]) { float wert; char ant; FILE*datei; datei=fopen(name,"w"); do { clrscr(); printf("Bitte eine reele Zahl: "); scanf("%f",&wert); //fprintf(datei,"%f ",wert); fwrite(&wert,sizeof(float),1,datei); printf("\nNoch eine Zahl ?"); ant=getch(); }while (ant=='j'); fclose (datei); } void groesse (char name[30]) { FILE*datei; int g; datei=fopen(name,"r"); fseek(datei,0,SEEK_END); g=ftell (datei); g=g/sizeof(float); printf("Es sind derzeit: %i Zahlen in der Datei.",g); fclose(datei); getch(); }
[code]
Damit erzeuge ich dann beispielsweie eine Datei hallo.csv: Kopier die in den entsprechenden Ordner und ruf die in meinem Programm dann auf.
-
Zeile 50 gehört jetzt in das Projekt und Zeile 71 auch. Zeilen 51 und 72 gehören raus. Wir wollen ja auch mit fscanf wieder einlesen und nicht mehr mit fread.
-
Wenn du mit fprintf schreibst, stehen die Zahlen als Text in der Datei. Somit kannst du von der Größe der Datei nicht mehr darauf schließen, wie viele Zahlen jetzt drin stehen.
<conio.h> und somit auch getch() etc. sind kein standard C.
Was mir immer noch nicht so ganz klar ist, was soll das Programm überhaupt machen? Es schreibt Zahlen als Text in eine Datei, und liest diese auch wieder aus - aber letzten Endes machst du nichts damit
(Kommentare über die Einrückung etc. spare ich mir hier mal oO)
-
Ne das sind nur Teilprogramme. Wollte die Fehlermöglichkeiten möglichst klein halten. Das Programm soll auf Wunsch Standardabweichung, Schwankungsbreite und Trendgerade von Werten, aus einer Datei eingelesen, berechnen. Die Datei erstellen wir vorher mit einem anderen Programm.
Hier ist mal mein aktueller Quellcode:
Das Problem mit der Dateigröße hat sich auch geklärt.#include <stdio.h> //normale Ein-/Ausgabe #include <math.h> //wegen Wurzel und Quadrat #include <conio.h> // wegen getch() #include <eigene.h> // wegen clrscr() #include <string.h> // wegen Dateiarbeit void datei(char[]);// unsere einzelnen Funktionen void lesen(char[]); void Schwankungsbreite(char[]); void arithmetisches_Mittel(char[]); void Koeffizienten(char[]); void Vergleich_Trendgerade (char[]); int g; // Dateigroesse double messwert[50]; // Feld für einzelne Messwerte void main (void) { char name [30]; char wahl; datei(name); // gezwungener Aufruf der Funktion: datei do { clrscr(); // Bildschirm löschen und dann unser Menü anzeigen printf ("\t\n\nImportieren der Messwerte aus CSV-Datei.................................1\n"); printf ("\t\n\nBerechnung und Ausgabe der Schwankungsbreite der Messwerte..............2\n"); printf ("\t\n\nBerechnung und Ausgabe des arith. Mittels und der Standardabweichung....3\n"); printf ("\t\n\nBerechnung und Ausgabe der Koeffizienten der Trendgeradenm..............4\n"); printf ("\t\n\nVergleich der tatsaechlichen Messwerte mit der Trendgeraden.............5\n"); printf ("\t\n\nProgrammende ...........................................................E\n"); wahl=getch(); switch (wahl) // Menüauswahl treffen { case '1':datei(name);break; case '2':Schwankungsbreite (name);break; case '3':arithmetisches_Mittel (name); break; case '4':Koeffizienten (name); break; case '5':Vergleich_Trendgerade (name); break; case 'E':printf("\nProgrammende\n\n");break; default: printf ("Falsche Eingabe, bitte neu: "); getch(); } } while (wahl!='E'); } void datei (char name [30]) { clrscr(); FILE*datei; printf ("\nBitte Namen der einzulesenden CSV-Datei eingeben: "); scanf ("%s",name); datei=fopen(name,"r"); // Dateigröße ermitteln struct {float a;short b;char c[];}satz; fseek(datei,0,SEEK_END); g=ftell (datei); g=g/sizeof(satz); printf("Dateigroesse: %i daten ",g); // Messwerte einlesen int i; // Zählervariable rewind (datei); // Dateizegier wieder auf Anfang setzen for (i=0;i<g;i++) { //fread(&messwert[i],sizeof(float),1,datei); fscanf(datei,"%lf ",&messwert[i]); printf("\nDer %i. Wert betraegt: %lf",i+1,messwert[i]);//brauch man nicht nur zu Kontrolle }fclose (datei); getch(); }// Ende Funktion: datei // Schwankungsbreite void Schwankungsbreite(char name [30]) { clrscr(); float max,min,diff; int i; max=0; for (i=0;i<g;i++) { if (messwert[i]>max) max=messwert[i]; else ; }printf("\nDer maximal Wert betraegt: %lf",max); min=max; for (i=0;i<g;i++) { if (messwert[i]<min) min=messwert[i]; else ; }printf("\nDer minimal Wert betraegt: %lf",min); printf("\n\nDie Messwerte schwanken zwischen %lf und %lf.",min, max); diff=max-min; printf("\n\nDie Messwerte schwanken um %lf.",diff); // Werte in Protokolldatei schreiben { FILE*fp; fp=fopen ("Protokolldatei.txt","a"); fprintf (fp,"\nDer maximal Wert betraegt: %lf",max); fprintf (fp,"\nDer minimal Wert betraegt: %lf",min); fclose (fp); }getch(); } // arithmetisches Mittel und Standardabweichung void arithmetisches_Mittel(char name [50]) { clrscr(); float ergebnis,summe; // Hilfsvariablen: ergebnis=Arith. Mittel und Summe=Summe aller Messwerte int i; // Zählervariable summe=0; for (i=0;i<g;i++) { summe+=messwert[i]; ergebnis=summe/g; } printf ("\nDas arithmetische Mittel betraegt: %lf\n\n",ergebnis); float v[50],z,s; // v=x-/x; z= Zwischenergebnis nach dem Quadrieren; t= z/(n-1); s=standardabweichung int j; // Zählervariable for (j=0;j<g;j++) z=0; for (i=0;i<g;i++) { v[j]=messwert[i]-ergebnis; // berechnung von v für jeden einzelnen Messwert z=z+pow((v[j]),2); } s=sqrt(z/(g-1)); printf("Die Standardabweichung betraegt: %lf\n\n",s); getch(); // Werte in Protokolldatei schreiben { FILE*fp; fp=fopen ("Protokolldatei.txt","a"); fprintf (fp,"\nDas arithmetische Mittel betraegt: %lf",ergebnis); fprintf (fp,"\nDie Standardabweichung betraegt: %lf",s); fclose (fp); } }// Ende der Funktion: Arithmetisches Mittel // Koeffizienten der Trandgeraden void Koeffizienten(char name [30]) { } // Vergleich der Koeffizienten der Trandgeraden void Vergleich_Trendgerade(char name [30]) { }
[code]
-
Globale Variablen sind böse
Wenn die Zahlen eh als Text vorliegen, braucht man kein Programm mehr um sie zu schreiben oder? Geht ja auch mit einem Texteditor. Von dem Menü würde ich auch Abschied nehmen, über Startparameter kann man das eigentlich einfacher regeln. (Ist auch üblicher).Einlesen kann man z.B. so machen:
void read_file(const char *name, double *buf, int size) // Größe des Arrays übergeben, um Überlauf zu vermeiden. Wichtig! { FILE *file = fopen(name, "r"); if (!file) perror(name), exit(-1); while (size-- && 1 == fscanf(file, "%lf ", buf++)) // scanf() gibt die Anzahl der erfolgreich gelesenen Einheiten zurück. printf("%lf\n", *(buf - 1)); // hier kannst du auch einfach ein ";" schreiben, das printf dient nur der Überprüfung. } int main(int argc, char *argv[]) { double nums[50]; if (argc < 2) return -1; // Hier würde man dann ausgeben, wie das Programm zu bedienen ist. read_file(argv[1], nums, sizeof(nums) / sizeof(*nums)); }
-
Gut,also das mit der Dateigrösse auslesen klappt doch nicht. Es werden mehr Werte eingelesen als in der Datei sind und als 0 angegeben. Weist du warum?
-
eydasgehtab schrieb:
Gut,also das mit der Dateigrösse auslesen klappt doch nicht. Es werden mehr Werte eingelesen als in der Datei sind und als 0 angegeben. Weist du warum?
cooky451 schrieb:
Wenn du mit fprintf schreibst, stehen die Zahlen als Text in der Datei. Somit kannst du von der Größe der Datei nicht mehr darauf schließen, wie viele Zahlen jetzt drin stehen.
Lies bitte meinen Post oben, du musst die Dateigröße gar nicht auslesen!
-
eydasgehtab schrieb:
Gut,also das mit der Dateigrösse auslesen klappt doch nicht. Es werden mehr Werte eingelesen als in der Datei sind und als 0 angegeben. Weist du warum?
Wenn du eine Fließkommazahl mit %f bei printf ausgibst, werden üblicherweise 6 Nachkommstellen angegeben. Dann kommen noch die Vorkommastellen, der Dezimalpunkt und das Leerzeichen dazu. Macht ca. 10 bis 16 Zeichen.
sizeof(float) ist auf den meisten Systemen 4.
Mit printf werden die Variablen (meist) in ASCII-Zeichen geschrieben.
Bei fwrite wird die Variable binär in die Datei geschrieben.
-
Hab jetzt von meinem Dateigröße Auslesen und der For- Schleife danach Abschied genommen. Mach es jetzt nur noch mit einer Do-while-Schleife. und lass dann auch jedes mal g inkrementieren. Funktioniert soweit auch.
do { i=i+1; g=g+1; fscanf(datei,"%lf ",&messwert[i]); printf("\nDer %i. Wert betraegt: %lf",i+1,messwert[i]); }while(!feof(datei));
-
Wo ist denn jetzt der Unterschied zwischen
i
undg
?
Und warum machst du am Anfang schoni=i+1
?
-
Hab das noch geändert, ich inkrementier i und g natürlich erst am Ende der Schleife. Der erste Index ist also 0 so wie i auch initialisiert wird. Der Unterschied zwischen i und g ist der, dass i einfach in jeder Funktion als Index des Feldes und als Zählervariable für for- Schleifen genommen wird und somit der Index immer stimmt. g ist global vereinbart und stellt die Anzahl der Messwerte da. Man hätte es bestimmt auch kombinieren können.Aber so funktionierts auch