Problem beim Abspeichern in Datei
-
Guten Tag!
Mein Programm stürzt aus mir unerklärlichen Gründen jedes Mal ab - mit der Meldung, dass der Heap beschädigt werden könnte.
Würde ich jedoch free(pSave) weglassen, könnte er es zumindest debuggen, jedoch steht dann im Textfile rein gar nichts.
int main() { int punkte[] = {10,20,30}; char name[][10] = {"Sepp", "Hias", "Zenzi"}; FILE *pSave; pSave = fopen("Highscore.txt", "w"); if(pSave != NULL) { for(int i = 2; i >= 0; i--) { fprintf(pSave, "%d\n ", punkte[i]); fprintf(pSave, "%s\n ", name[i]); } free(pSave); } getch(); return 0; }
-
Wie kommst du darauf, dass man
FILE*
mitfree
freigibt? Dafür gibt esfclose
.
-
Och Mann, ich bin vielleicht ein Depp
Danke!
-
MichaelE schrieb:
char name[][10] = {"Sepp", "Hias", "Zenzi"};
Oftmals (wenn du den Speicherplatz für die Strings nicht beschreiben willst) reicht es in solchen Fällen auch aus, statt char[N] besser char* zu verwenden.
char *name[] = {"Sepp", "Hias", "Zenzi"};
Das lässt sich auch anschließend besser bearbeiten und ist robuster gegen Speicherplatz"knappheit", z.B.
name[1] = "String der länger als 10 Zeichen ist"; /* sollte klaglos funktionieren */
statt
strcpy( name[1], "String der länger als 10 Zeichen ist" ); /* hier sollte es dann unschön werden */
-
Anderes Programm bzw. Übung:
In meinem Textfile steht folgendes:
12
123.124
Hallo Welt!
MAENNLICHNun will ich einfach aus dieser Datei lesen und am Bildschirm ausgeben, jedoch habe ich Schwierigkeiten die 3. Zeile zu erfassen.
FILE *pRead; char buffer1[10]; char buffer2[10]; char buffer3[20]; char buffer4[10]; pRead = fopen("Test.txt", "r"); if(pRead != NULL) { fscanf(pRead, "%s", buffer1); fscanf(pRead, "%s", buffer2); fgets(buffer3, sizeof(buffer3), pRead); fscanf(pRead, "%s", buffer4); printf("%s ... %s ... %s ... %s",buffer1, buffer2, buffer3, buffer4); fclose(pRead); }
-
Kurz:
Nach demfscanf(pRead, "%s", buffer2);
steht noch das '\n' (Zeilenumbruch) im Eingabepuffer von pRead.
fgets()
liest nur bis zu einem Zeilenumbruch.Lies einfach jede Zeile mit
fgets()
.
-
Alles klar, das wusste ich nicht - besten Dank
-
Und nun wieder stellt sich mir ein Programm in den Weg, dass mir Probleme bereitet. Generell ist mein Problem bzw. die Hürde an der ich oftmals scheitere, einzelne Programmteile sinnvoll miteinander verknüpfen zu können - Aufgabenstellung:
In einer Binär-Datei sind eine gewisse Anzahl von double Werten gespeichert. Schreibe ein Programm das alle Werte einliest und als Text in eine Textdatei schreibt. Jeder Wert soll in einer eigenen Zeile stehen. Am Ende soll das Programm außerdem den Durchschnitt aller eingelesenen Zahlen am Bildschirm ausgeben.
Der Name der zu lesenden Datei wird als Kommandozeilen-Parameter übergeben. Der Name der Ausgabedatei soll im Programm automatisch erstellt werden indem die Dateierweiterung durch txt ersetzt wird. Beispiel: "werte.bin" ! "werte.txt".#include <stdio.h> #include <conio.h> int main(int argc, char *argv[]) { FILE *pRead; FILE *pSave; int anz; int buffer[128]; /*double zahl1 = 1; double zahl2 = 2; double zahl3 = 3; double zahl4 = 4; pSave = fopen("argv[1]", "wb"); if(pSave != NULL) { fwrite(&zahl1, sizeof(double), 1, pSave); fwrite(&zahl2, sizeof(double), 1, pSave); fwrite(&zahl3, sizeof(double), 1, pSave); fwrite(&zahl4, sizeof(double), 1, pSave); fclose(pSave); }*/ pRead = fopen("argv[1]", "rb"); if(pRead != NULL) { while(!feof(pRead)) { anz = fread(&buffer, sizeof(double), 1, pRead); fclose(pRead); } } pSave = fopen("Textdatei.txt", "w"); if(pSave != NULL) { for(int i = 0; i < anz; i++) { fprintf(pSave, "%lf\n", buffer[i]); } fclose(pSave); } getch(); return 0; } //Stringmanipulation: Ansich ist diese kein Problem, nur wie ich damit weiterarbeiten soll/kann bereitet mir Probleme char string[] = {argv[1]}; //möglich? for(int i = 0; string[i] != 0; i++) { if(string[i] == '.') { string[i+1] = 't'; string[i+2] = 'x'; string[i+3] = 't'; } }
Ich weiß, ich stelle fast zu häufig Fragen (:D), doch selbst nach langem Grübeln weiß ich einfach auch nicht weiter.
-
Da weiß man gar nicht, wo man anfangen soll.
#include <stdio.h> #include <conio.h> // kein Standard-C int main(int argc, char *argv[]) { FILE *pRead; FILE *pSave; int anz; // entscheide dich für eine Sprache int buffer[128]; // int? pRead = fopen("argv[1]", "rb"); // hä? "argv[1]" ist doch wohl so offensichtlich falsch.. if(pRead != NULL) { while(!feof(pRead)) // Darüber sage ich mal nichts { anz = fread(&buffer, sizeof(double), 1, pRead); // So bekommst du die Anzahl bestimmt nicht.. fclose(pRead); // warum schließt du die Datei hier? } } pSave = fopen("Textdatei.txt", "w"); if(pSave != NULL) { for(int i = 0; i < anz; i++) { fprintf(pSave, "%lf\n", buffer[i]); // %lf gibt's nicht, fprintf Doku richtig lesen. } fclose(pSave); } getch(); // .. nimm halt getchar(), das ist zumindest Standard-C return 0; } //Stringmanipulation: Ansich ist diese kein Problem, nur wie ich damit weiterarbeiten soll/kann bereitet mir Probleme char string[] = {argv[1]}; //möglich? // nope for(int i = 0; string[i] != 0; i++) { if(string[i] == '.') { // Ne, also ich verstehe die Aufgabenstellung völlig anders.. string[i+1] = 't'; string[i+2] = 'x'; string[i+3] = 't'; } }
Wie gesagt, da ich nicht mal weiß, wo ich da anfangen soll, einfach ein kleines Beispiel:
#include <stdio.h> #include <string.h> int main(int argc, char *argv[]) { FILE *in, *out; double d; char buf[256]; if (argc != 2 || strlen(argv[1]) >= 256 - 5) { fprintf(stderr, "..."); return -1; } sprintf(buf, "%s.bin", argv[1]); in = fopen(buf, "rb"); sprintf(buf, "%s.txt", argv[1]); out = fopen(buf, "wt"); if (!in || !out) { fprintf(stderr, "..."); return -2; } while (fread(&d, 1, sizeof(d), in) == sizeof(d)) { fprintf(out, "%f\n", d); } return 0; }
Edit:
Höhö
-
Eigentlich ist das Problem weniger, dass du zu viele Fragen stellst, als dass du gar keine Frage gestellt hast. Was möchtest du wissen?
char string[] = {argv[1]};
ISt möglich, macht aber nicht das, was du vermutlich meinst. Wenn dir Stringmanipulation an sich keine Probleme bereitet, dann solltest du wissen, wie man den Inhalt von Strings kopiert.
Außerdem bezweifle ich, dass das Einlesen so funktioniert, wie du möchtest. Lass dir mal das Ergebnis ausgeben.
-
Inzwischen habe ich weiter dran gearbeitet und müsste jetzt auf jeden Fall der Lösung näher sein als zuvor:
int main(int argc, char *argv[]) { FILE *pRead; FILE *pSave; char buffer[128]; /*double zahl1 = 1; double zahl2 = 2; double zahl3 = 3; double zahl4 = 4; pSave = fopen("argv[1]", "wb"); if(pSave != NULL) { fwrite(&zahl1, sizeof(double), 1, pSave); fwrite(&zahl2, sizeof(double), 1, pSave); fwrite(&zahl3, sizeof(double), 1, pSave); fwrite(&zahl4, sizeof(double), 1, pSave); fclose(pSave); }*/ pRead = fopen(argv[1], "rb"); char* buff = buffer; if(pRead != NULL) { while(!feof(pRead)) { fread(&buff, sizeof(double), 1, pRead); buff++; } fclose(pRead); } for(int i = 0; argv[1][i] != '\0';i++) { argv[1][i-1]='t'; argv[1][i-2]='x'; argv[1][i-3]='t'; } pSave = fopen(argv[1], "w"); if(pSave != NULL) { for(int i = 0; i < anz; i++) { fprintf(pSave, "%f\n", buffer[i]); } fclose(pSave); } getch(); return 0; }
-
MichaelE schrieb:
Inzwischen habe ich weiter dran gearbeitet und müsste jetzt auf jeden Fall der Lösung näher sein als zuvor:
Nein.
Du musst in der selben Schleife lesen und schreiben. Du musst daher beide Dateien gleichzeitig offen haben.Zudem musst du auch 2 Variablen vom Typ
double
haben, damit du damit rechnen kannst.cooky451 schrieb:
// Ne, also ich verstehe die Aufgabenstellung völlig anders..
Ich habe das so verstanden wie in deinem ersten Beispiel. Du sollst die Ereiterung ersetzen. Schau dir mal die Funktionen aus
string.h
an. Z.B.strcpy()
,strrchr()
undstrcat().
Aber, in argv spielt man nicht rum, mach eine Kopie.
-
--- Ja, vermutlich hast du recht.
-
Ich werde daraus einfach nicht schlau...
Wenn es euch passt, möchte ich nochmals ganz von vorne beginnen.
1. Ich erstelle eine Binärdatei in die ich eine gewisse Anzahl an double Werten eintrage:
double zahl1 = 1; double zahl2 = 2; double zahl3 = 3; double zahl4 = 4; pSave = fopen(argv[1], "wb"); if(pSave != NULL) { fwrite(&zahl1, sizeof(double), 1, pSave); fwrite(&zahl2, sizeof(double), 1, pSave); fwrite(&zahl3, sizeof(double), 1, pSave); fwrite(&zahl4, sizeof(double), 1, pSave); fclose(pSave); }
2. Ich lese die Daten aus der Binärdatei aus:
pRead = fopen(argv[1], "rb"); char* buff = buffer; if(pRead != NULL) { while(!feof(pRead)) { fread(&buff, sizeof(double), 1, pRead); buff++; //Doch warum sollte ich gleichzeitig Lesen und Schreiben? } fclose(pRead); }
3. Dateiendung ändern:
for(int i = 0, buffer[i] != '\0', i++) { if(buffer[i] == '.') { buffer[i+1] = 't'; buffer[i+2] = 'x'; buffer[i+3] = 't'; } }
4. Anschließend in diese txt Datei schreiben:
pSave = fopen(argv[1], "w"); if(pSave != NULL) { fprintf(pSave, "%s\n", buffer); //Wie oft wird geschrieben? Der buff pointer zählt hoch... fclose(pSave); }
-
Wenn du Schwierigkeiten hast, den Gesamtablauf zusammenzusetzen, dann teil das Problem doch mal in Unterfunktionen mit klar abgegrenzten Aufgaben auf. Schreibe folgende Funktionen:
void binaeres_schreiben(double *array, unsigned int N, FILE *datei); // Schreibt N doubles aus array binär in datei unsigned int binaeres_lesen(double* array, FILE *datei); // Liest doubles im Binärformat aus datei in array ein. Gibt die Anzahl der gelesenen Elemente zurück void my_strcat(char *ziel, const char* quelle); // Fügt die Zeichenkette quelle hinten an die Zeichenkette ziel an. ziel muss groß genug für das Ergebnis sein. void normales_schreiben(double *array, unsigned int N, FILE *datei); // Schreibt N doubles aus array in menschenlesbarer Form in datei. Einzelne Werte werden durch Zeilenumbrüche getrennt.
Jede Unterfunktion sollte für dich leicht zu schreiben sein. Und es sollte nicht schwer sein, mit diesen Funktionen ein Hauptprogramm zu schreiben.
P.S.: Und der von mir gewählte Funktionsname my_strcat ist ein Wink mit dem Zaunpfahl.
-
Nochmal zur Aufgabe:
In einer Binär-Datei sind eine gewisse Anzahl von double Werten gespeichert. Schreibe ein Programm das:
a) alle Werte einliest und als Text in eine Textdatei schreibt. Jeder Wert soll in einer eigenen Zeile stehen.
b) Am Ende soll das Programm außerdem den Durchschnitt aller eingelesenen Zahlen am Bildschirm ausgeben.
c) Der Name der zu lesenden Datei wird als Kommandozeilen-Parameter übergeben. Der Name der Ausgabedatei soll im Programm automatisch erstellt werden indem die Dateierweiterung durch txt ersetzt wird. Beispiel: "werte.bin" ! "werte.txt".a) Du kannst alle Werte erst einlesen und dann in die Textzdatei speichern. Dafür musst du aber vorher wissen wieviel Zahlen du hast.
Dafür brauchst du dann aber einArray von double
Besser: Du liest ein Wert ein und speicherst ihn gleich in der Textdatei. Dann ist egal wie viele Daten du hast.b) Dafür brauchst du die Summe der Zahlen und die Anzahl. Du musst also mit den double-Werten rechnen. Darum brauchst du double-Variablen.
c) hast du schon
Zu 2.
char* buff = buffer; if(pRead != NULL) { while(!feof(pRead)) { fread(&buff, sizeof(double), 1, pRead); // Hier list du 8 Byte an die Stelle von buff (8 = sizeof(double)) buff++; // Hier erhöhst du buff um 1 Byte, da buff ein char* ist. //Du überschreibst als immer fleißig deine Werte.
Zu 4.
fprintf(pSave, "%s\n", buffer); //Wie oft wird geschrieben? Der buff pointer zählt hoch...
In buffer (wenn es richtig gemacht wäre) stehen noch Binörwerte. In die Textdatei sollen aber (ASCII-)Zeichen.
Das wird mit printf("%f") gemacht. Und wegen " ... in einer eigenen Zeile .." ein "%f\n"
-
Irgendwie komme ich jetzt noch mehr durcheinander, als ich es zuvor schon war.
Die Funktionen sehen bei mir jetzt folgendermaßen aus:
void binaeres_schreiben(double *array,FILE *datei) { int i; if(datei != NULL) { for(i = 0; i < N; i++) { fwrite(&array, sizeof(double), 1, datei); } } } unsigned int binaeres_lesen(double* array, FILE *datei) { int i; int anz; if(datei != NULL) { while(!feof(datei)) { anz = fread(&array,sizeof(double), 1, datei); if(anz == 0); { break; } } return anz; //falsch - ich weiß } } void endung(double* array) { for(int i = 0; array[i] != '\0'; i++) { if(array[i] == '.') { array[i+1] = 't'; array[i+2] = 'x'; array[i+3] = 't'; } } } void normales_schreiben(double *array, FILE *datei) { int i; for(i = 0; i < N; i++) { fprintf(datei, "%f\n", array[i]); } }
Um die Anzahl zu ermitteln, muss ich mir noch den Wert zwischenspeicher, bevor der pointer wieder erhöht wird, nur bekomme ich immer Konvertierungsfehler.
-
fread() gibt die Anzahl der gelesenen Zeichen/Bytes zurück.
Für dich ist doch aber die Anzahl der gelesenen double-Werte wichtig.Nebenbei ist array doch schon ein Zeiger auf das Feld. Da darfst du dann keinen Adressoperator (&) mehr nehmen
Und das N gehört in die Parameterliste. Nix mit globalen Variablen.
-
Zusätzlich zu dem was DirkB gesagt hat:
Beim binären Schreiben, schreibst du immer den gleichen Wert. Weißt du uberhaupt, was der dritte Parameter von fwrite macht?Anzahl beim Lesen: Zähl doch mit!
Endung anfügen: Da hatte ich die Aufgabenstellung nicht gelesen. Ein Zusammenfügen von Zeichenketten war gar nicht gefragt. Die Ersetzung sollte so an sich ok sein. Aber der Parameter der Funktion stimmt überhaupt nicht. Merh Sorgfalt beim Programmieren und weniger Copy&Paste!
Und damit dir alles klarer wird, versuch mal ein Hauptprogramm mit den Funktionen zu schreiben, egal ob sie schon vollständig funktionieren oder nicht. Fehler kannst du mit dieser Aufteilung recht gut isolieren und aufspüren.
-
SeppJ schrieb:
Zusätzlich zu dem was DirkB gesagt hat:
Beim binären Schreiben, schreibst du immer den gleichen Wert. Weißt du uberhaupt, was der dritte Parameter von fwrite macht?Anzahl beim Lesen: Zähl doch mit!
Endung anfügen: Da hatte ich die Aufgabenstellung nicht gelesen. Ein Zusammenfügen von Zeichenketten war gar nicht gefragt. Die Ersetzung sollte so an sich ok sein. Aber der Parameter der Funktion stimmt überhaupt nicht. Merh Sorgfalt beim Programmieren und weniger Copy&Paste!
Und damit dir alles klarer wird, versuch mal ein Hauptprogramm mit den Funktionen zu schreiben, egal ob sie schon vollständig funktionieren oder nicht. Fehler kannst du mit dieser Aufteilung recht gut isolieren und aufspüren.
Nun dieser gibt die Anzahl der zu schreibende Elemente an:
unsigned int binaeres_lesen(double* array, FILE *datei) { int anz; int zaehler = 0; if(datei != NULL) { while(!feof(datei)) { anz = fread(array,sizeof(double), 1, datei); if(anz == 0) { break; } zaehler++; } return zaehler; } }
Müsste doch eigentlich so passen, da ja bis zum Dateiende durchlaufen wird.
Auch hier habe ich wieder Schwierigkeiten, denn welche Parameter würden sonst in Frage kommen? Aber an diesem Beispiel sieht man perfekt, dass es mir einfach schwer fehlt einzelne Aufgaben miteinander zu verknüpfen.
Das Programm ist fertig (ich habe nur die einzelnen Fkt. gepostet), jedoch erhalte ich jedesmal ein Debug Assertion Failed. Anscheinend funktioniert in Zeile 54 (bei mir) ein fopen nicht, komischerweise befindet sich in dieser Zeile aber keines.
-
Woher sollen wir wissen in welcher deiner Quelltextfassungen der Fehler in Zeile 54 angezeigt wird. Es kann auch sein das die Ursache für die Fehlermeldung ein paar Zeilen früher liegt.
Und, wenn noch ein Fehler auf Grund des Quelltextes angezeigt wird ist ein Programm noch nicht fertig