fscanf oder sonst was macht trouble
-
also ich hab ein problem mit fscanf oder vielleicht auch mit meinem compiler, weil ich mir überhaupt nicht erklären aus welchem grund der hier mucken macht...
#include <string.h> #include <conio.h> #include <stdio.h> int main() { FILE *datei; //char *blablabla; char *string; datei=fopen("c:/programme/dev-cpp/datei.txt","r"); if (datei==NULL) printf("Konnte Datei nicht öffnen!"); else { printf("Alles in Ordnung..."); fscanf(datei,"%s",string); printf("\n\nDie Datei enhaelt folgendes:\n\n%s",string); } getch(); fclose(datei); }
wohingegen hier alles in butter ist... (einziger unterschied ist die erste char initialisierung!)
#include <string.h> #include <conio.h> #include <stdio.h> int main() { FILE *datei; char *blablabla; char *string; datei=fopen("c:/programme/dev-cpp/datei.txt","r"); if (datei==NULL) printf("Konnte Datei nicht öffnen!"); else { printf("Alles in Ordnung..."); fscanf(datei,"%s",string); printf("\n\nDie Datei enhaelt folgendes:\n\n%s",string); } getch(); fclose(datei); }
die variable "char blablabla" wird doch eh nie gebraucht also wo liegt dann der fehler??? übrigens ist mir schon bewusst, dass nur bis zur ersten leerzeile eingelesen wird und er spuckt ja beim zweiten code auch immer korrekt "Das" aus nur beim ersten erhalte ich komischerweise immer "unbennant 1 hat ein problem festgestellt..."
wenn ihr das nicht erhaltet muss es wohl am compiler liegen, wenn doch wo steckt dann der fehler???
-
wie wäre es mal damit, Speicher für die Strings zu reservieren. Dass das 2. Beispiel funktioniert ist einfach nur eine Glückssache.
Bevor du fragst, womit man Speicher reserviert man: malloc(3)
PS. ist es als Anfänger generell keine gute Idee, davon auszugehen, dass der Compiler eine Macke hat. Das ist in 99,9% der Fälle eh nicht der Fall.
-
Versuchs mal hiermit:
#include <string.h> #include <conio.h> #include <stdio.h> int main() { FILE *datei; //char *blablabla; char string[1024]; //Größe hängt von der Datei ab, besser wäre dynamischer Speicher datei=fopen("c:/programme/dev-cpp/datei.txt","r"); if (datei==NULL) printf("Konnte Datei nicht öffnen!"); else { printf("Alles in Ordnung..."); fscanf(datei,"%s",string); printf("\n\nDie Datei enhaelt folgendes:\n\n%s",string); } getch(); fclose(datei); }
Das Problem bei deinem Programm war, dass du keinen String, sondern einen
char-Zeiger definiert hast der auf keinen gültigen Speicherbereich zeigt.
-
Gebt ihm doch keinen Code mit einer BufferOverflow-Lücke...
Tip: Lass gerade als Anfänger die Finger von scanf und Konsorten. Damit baut man sich leicht Sicherheitslücken ein.Und fread() dürfte für deine Zwecke locker ausreichen.
Das fclose(datei); dürfte auch Probleme machen, wenn die Datei nicht geöffnet werden konnte und datei dann ein NULL-Pointer ist.
-
jo ok klappt jetzt soweit! also fread() und fgets() und auch malloc() waren mir schon davor bekannt nur war mein problem, dass ich dachte,
char string[20]="inhalt"
waere gleichbedeutend mit
char *string="inhalt"
und das fclose() werd ich dann in den else zweig machen.
-
@amartin755: dynamischer speicher klingt
aber wie soll ich das anstellen?
mit "verketteten Listen"? dann müsste ich doch jedes Zeichen einzeln einlesen oder nicht?
-
Nein, du kannst auch größere Blöcke mit malloc()* anfordernd und per fscanf() füllen (mit "%20s" kannst du auch die Blockgröße für den Aufruf angeben, damit du nicht über's Ziel hinausschießt).
* und mit realloc() nachträglich vergrößern
-
sorri aber ich brings einfach nich hin:
also ich will eine funktion die ein txt-file ausliest. als rückgabewert soll sie einen pointer auf eine speicheradresse angeben, deren speicher zuvor mit malloc() reserviert und solange weitere zeichen folgen, immer mit realloc() erweitert werden soll! die zeichen sollen dann fortlaufend in diese adresse geschrieben werden!
also der funktionskopf sollte dann, wenn mich nicht alles täuscht so aussehen:
char *getstr(FILE *file)
der Rest dann in etwa so...
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <conio.h> char *getstr(FILE *file) { char zeichen,*string; int size=sizeof(char),newsize=size; string=malloc(size); if (string==NULL) { printf("\n\nSpeicher konnte nicht angefordert werden\n\n"); } else { printf("\n\nSpeicher wurde reserviert...\n\n"); while (( z = getc(file)) != '\n' )/*hier soll meien eigene abbruchbedingung stehn */ { //strcat(string,z); /*an der Stelle weiss ich nich wie ich das anfügen soll*/ realloc(string,newsize+=size); if(string==NULL) { printf("\nSpeichererweiterung fehlgeschlagen!\n"); return (NULL); } }; } return string; } int main() { FILE *datei; char *string; datei=fopen("c:/datei.txt","r"); if(datei==NULL) printf("\n\nDatei konnte nicht geoeffnet werden!\n\n"); else { string=getstr(datei); printf("Textinhalt ist folgender:\n\n%s",string); getch(); free(string); fclose (datei); exit(1); } }
hab jetzt grad eben bemerkt, dasses ne ähnliche funktion und zwar fgets gibt. allerdings muss man da einen pointer mitübergeben und zusätzlich eine zeichenlänge, deshalb will ich die funktion selbst proggen, aber auch weil ich die abbruchbedingung der while-schleife selbst bestimmen will, z.B. mit EOF. mein hauptproble liegt an der stelle, wo jetzt noch provisorisch "//strcat()" steht, das wäre eine lösung so ähnlich wie sie in diesem thread schon vorgeschlagen wurde, wenn mans mit dynamischer speicherverwaltung auch anders lösen kann is das auch erwünscht
-
Tipp1: sizeof(char) ist immer 1 (beachte auch die Konsequenzen, siehe auch Tipp3)
Tipp2: ruf malloc und realloc selten auf, die Funktionen sind sehr teuer
Tipp3: Strings werden in C mit 0 abgeschlossen.Wo ist dein Problem beim anfügen? Überlege dir mal, wie man ein Zeichen an ein String anfügt. Warum sollte sich da etwas ändern, nur weil du den Speicher dynamisch reservierst?
-
Du könntest es z.B. so lösen:
#include <stdio.h> #include <stdlib.h> int main() { FILE *datei; char *string; unsigned long fileLen; datei=fopen("c:/programme/dev-cpp/datei.txt","r"); if (datei==NULL) printf("Konnte Datei nicht öffnen!"); else { printf("Alles in Ordnung..."); fseek(datei, 0L, SEEK_END); // Filepointer ans Dateiende verschieben fileLen = ftell(datei); // Dateigroesse ermitteln rewind(datei); // Filepointer wieder an den Anfang setzen string = malloc(fileLen); if(string) { fscanf(datei,"%s",string); fread(string, 1, fileLen, datei); printf("\n\nDie Datei enhaelt folgendes:\n\n%s",string); free(string); } else printf("Zu wenig Speicher verfügbar\n"); fclose(datei); } getchar(); return 0; }
Beachte bitte, dass es sich hier um ein verbesserunswürdiges Beispiel handelt. Z.B werden einige Rückgabewerte nicht ausgewertet.
-
ok danke erstmal an euch 4... und @ rüdiger:
tipp 1 mit verweis auf tipp 3 soll dann wohl bedeuten, dass ich noch speicher für den null-terminator reservieren muss aber was meinst du mit tipp 2 bzw wie kann ich das umgehen?wäre ist prinzipiell sinnvoll, eine zählervariable i einzuführen, die pro schleifendurchlauf um 1 erhöht wird und dann nach i_max schleifendurchläufen wieder resttet wird und speicher für weitere i_max zeichen reserviert (also je mehr speicher man auf einmal veranschlagt, desto eher läuft man gefahr mehr zu reservieren, als man später benötigt bzw. je weniger, desto öfter muss eben realloc aufgerufen werden...) oder würde das die sache noch komlpizierter machen?
und zu der letzten frage:
rüdiger schrieb:
Wo ist dein Problem beim anfügen? Überlege dir mal, wie man ein Zeichen an ein String anfügt. Warum sollte sich da etwas ändern, nur weil du den Speicher dynamisch reservierst?
eigentlich gute frage
aber da weiss ich leider auch keine antowrt drauf,
da ich in solchen fällen dann meistens strcat() benutzt habe...
-
Ode schrieb:
ok danke erstmal an euch 4... und @ rüdiger:
tipp 1 mit verweis auf tipp 3 soll dann wohl bedeuten, dass ich noch speicher für den null-terminator reservieren muss aber was meinst du mit tipp 2 bzw wie kann ich das umgehen?Indem du von vornherein größere Datenblöcke anforderst.
und zu der letzten frage:
rüdiger schrieb:
Wo ist dein Problem beim anfügen? Überlege dir mal, wie man ein Zeichen an ein String anfügt. Warum sollte sich da etwas ändern, nur weil du den Speicher dynamisch reservierst?
eigentlich gute frage
aber da weiss ich leider auch keine antowrt drauf,
da ich in solchen fällen dann meistens strcat() benutzt habe...Ja, das kannst du auch auf dynamisch angefordertem Speicher einsetzen (und genau wie bei einem Arry solltest du darauf achten, nicht über "deinen" Speicher hinauszuschreiben).