Probleme beim Einlesen von Werten
-
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