Hilfe bei Zeigerproblemen; variable Dateinamen
-
Stiefel2000 schrieb:
Was die Array-Größe angeht: Die lasse ich solange variabel, wie irgend möglich
ok, das ist eine gute Begründung, dennoch musst du
malloc
richtig verwenden.Stiefel2000 schrieb:
Ich muss sagen, dass ich nicht sehe, warum ich in Zeile 12 zu wenig Platz reserviere? Ich erstelle ein Array mit exakt K Speicherzellen, in der Schleife danach werden alle Elemente gefüllt (da ja i<k gilt und das Zählen bei 0 anfängt).
ganz einfach: Eingabe ist ein zweifacher Zeiger auf char. Du willst damit ein Array von Strings realisieren. Ein String ist ebenfalls ein Array von chars.
Mit
Eingabe=malloc(k*sizeof(char));
reservierst du aber nur k-Bytes, was zu wenig Platz für für k-Zeiger (was auf x86 Rechnern 4*k Bytes entspricht) ist. Richtig wäre:
Eingabe = malloc(k * sizeof(char*));
denn du willst Speicher für k-char-Zeiger reservieren. Wärst du nach FAQ - ANSI C :: Dynamischer Speicher mit malloc/calloc/realloc/free vorgegangen, hättest du sogar so gemacht
Eingabe = malloc(k * sizeof *Eingabe));
was von Anfang, vom Typ von
Eingabe
unabhängig genau viele Bytes reserviert hätte, die du brauchst.Stiefel2000 schrieb:
Zu guter Letzt: Das printf in der Datei ist nur zur Kontrolle des Arrays, das ich gerade eingelesen habe - wie ich im letzten Post erwähnte, scheint das "printf("\n");" in der zweiten for-Schleife sogar Macht über das Laufverhalten meines Programms zu haben - und ich habe keine Ahnung, weshalb das so sein sollte.
das leigt an
printf(*(Eingabe+i));
wie ich schon vorhin gesagt habe. Da du die Zeilen (die Anscheinend keine Leerzeichen enthalten) mit scanf liest, enthalten sie kein '\n' Zeichen.printf
macht einfflush(stdout);
, wenn er das '\n'-Zeichen findet, was in *(Eingabe + 1) nicht vorkommt, somit werden die Ausgaben nicht sofort ausgegeben. Wenn das Programm mit segfault sich ins Nirvane verabschiedet, wird stdout nicht geflusht und somit erscheint nichts.Stiefel2000 schrieb:
EDIT: Was genau bewirkt das "i < ++i" in deiner for-Schleife?
sorry, Tippfehler von mir, es soll nur
++i
stehen.Weil du anscheinend das nicht sauber hinkriegen wirst (du liest die Posts und/oder dein C Tutorial/Buch einfach nicht genau), hier eine dynamisch Lösung:
#include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { FILE *fp; int c; char **lines, **tmp1; char *input, *tmp2; int num_lines, num_chars; if(argc != 2) { fprintf(stderr, "usage: %s file\n", argv[0]); return 1; } fp = fopen(argv[1], "r"); if(fp == NULL) { perror("fopen"); return 1; } lines = NULL; input = NULL; num_lines = num_chars = 0; for(;;) { c = fgetc(fp); if(c == '\n' || c == EOF) { /* Wir haben eine ganze Zeile gelesen, * ins array hinzufügen */ tmp1 = realloc(lines, (num_lines + 1) * sizeof *lines); if(tmp1 == NULL) { /* Kein Speicher mehr */ free(input); break; } lines = tmp1; lines[num_lines] = input; /* input bereinigen für neue Zeile */ input = NULL; num_chars = 0; if(c == EOF) break; /* Ende der Datei oder Lesefehler */ num_lines++; continue; } /* normales Zeichen, in input hinzufügen, +2 wegen \0 */ tmp2 = realloc(input, (num_chars + 2) * sizeof *input); if(tmp2 == NULL) { /* Kein Speicher mehr */ free(input); break; } input = tmp2; input[num_chars] = c; input[++num_chars] = 0; } /* Ausgabe */ int i; for(i=0; i < num_lines; ++i) printf("%0.3d %s\n", i+1, lines[i]); /* Freigabe des Speichers */ for(i=0; i < num_lines; ++i) free(lines[i]); free(lines); fclose(fp); return 0; }
-
supertux schrieb:
Stiefel2000 schrieb:
Ich muss sagen, dass ich nicht sehe, warum ich in Zeile 12 zu wenig Platz reserviere? Ich erstelle ein Array mit exakt K Speicherzellen, in der Schleife danach werden alle Elemente gefüllt (da ja i<k gilt und das Zählen bei 0 anfängt).
ganz einfach: Eingabe ist ein zweifacher Zeiger auf char. Du willst damit ein Array von Strings realisieren. Ein String ist ebenfalls ein Array von chars.
Mit
Eingabe=malloc(k*sizeof(char));
reservierst du aber nur k-Bytes, was zu wenig Platz für für k-Zeiger (was auf x86 Rechnern 4*k Bytes entspricht) ist. Richtig wäre:
Eingabe = malloc(k * sizeof(char*));
Danke für diese Klarstellung, daran hatte ich leider nicht gedacht. Das wird mir wohl ab jetzt die ein oder andere Fehlersuche ersparen :).
supertux schrieb:
Stiefel2000 schrieb:
Zu guter Letzt: Das printf in der Datei ist nur zur Kontrolle des Arrays, das ich gerade eingelesen habe - wie ich im letzten Post erwähnte, scheint das "printf("\n");" in der zweiten for-Schleife sogar Macht über das Laufverhalten meines Programms zu haben - und ich habe keine Ahnung, weshalb das so sein sollte.
das leigt an
printf(*(Eingabe+i));
wie ich schon vorhin gesagt habe. Da du die Zeilen (die Anscheinend keine Leerzeichen enthalten) mit scanf liest, enthalten sie kein '\n' Zeichen.printf
macht einfflush(stdout);
, wenn er das '\n'-Zeichen findet, was in *(Eingabe + 1) nicht vorkommt, somit werden die Ausgaben nicht sofort ausgegeben. Wenn das Programm mit segfault sich ins Nirvane verabschiedet, wird stdout nicht geflusht und somit erscheint nichts.Das bedeutet also, dass ich das printf entfernen kann und das Programm damit keine Probleme haben sollte? Oder muss ich an anderer Stelle noch einen Zeilenumbruch einfügen, damit später keine Probleme auftreten?
supertux schrieb:
Weil du anscheinend das nicht sauber hinkriegen wirst (du liest die Posts und/oder dein C Tutorial/Buch einfach nicht genau), hier eine dynamisch Lösung:
Danke für das Vertrauen in meine Fertigkeiten!
Und natürlich danke für den Quelltext und die Hilfe - wobei mir die Erklärungen der Fehler um einiges wertvoller sind als der fertige Quelltext. Wenn ich nicht genügend Verständnis für die Vorgänge in der Maschine aufbringen kann, dann ist mein Problem nicht die funktionsuntüchtige Software.
-
Stiefel2000 schrieb:
Das bedeutet also, dass ich das printf entfernen kann und das Programm damit keine Probleme haben sollte?
nein, das war nie das Problem, sondern, dass du zu wenig Speicher reservierst und weit über die Grenzen von
Eingabe
geschrieben hast, was früher oder später zu einem segfault führt. Dein printf hat nur den "Todesstoss" gegeben. Guck dir meinen Code an, vor allem im Bezug auflines
, was deinemEingabe
entspricht.Generell ist
printf(variable);
schlecht. Wennvariable
Zeichenfolgen wie '%s' oder ähnlcihes hat, kann das zu segfaults führen, weil printf erwartet, dass das erste Argument ein char* ist, aber beiprintf(variable);
ist das nicht der Fall, also liest irgendwas und das kann auch "verboten" sein, was zum segfault führt. Das ist aber ein anderes Problem, was vielleicht zu deinen Abstürtzen geführt hat, aber weil ich den Inhalt deiner DateiC:\Quelle.txt
nicht kenne, weiß ich es nicht.Stiefel2000 schrieb:
Danke für das Vertrauen in meine Fertigkeiten!
Bitte. Ich hab sowas nicht aus "Bösheit" gesagt, sondern aus Erfahrung, und ich kenne die Threads der letzten Tagen. Du stellst manchmal Fragen auf die du bereits eine Antwort bekommen hast, also was soll ich denn dann denken? Dass du die Sachen nicht genau liest. Viele deine Fehler würde man vermeiden, wenn man unsere Antworten genauer lesen würdest und wenn sie dennoch unverständlich sind, kannst du sagen 'den Teil verstehe ich nicht' anstann einfach loszulegen und irgendwas schreiben.
Stiefel2000 schrieb:
Und natürlich danke für den Quelltext und die Hilfe - wobei mir die Erklärungen der Fehler um einiges wertvoller sind als der fertige Quelltext.
ich hab jedenfalls dir schon paar mal in diesem Thread auf deine Fehler hingewiesen und erklärt und dennoch tust du sie. Darum der Code, als Anhaltspunkt.
-
Auch wenn die letzte Antwort schon ein wenig her ist, wollte ich mich nochmal bedanken. Ich hatte leider erst heute Zeit, das Programm fertigzustellen und muss sagen, dass der Quelltext von supertux an so mancher Stelle ziemlich "inspirierend" war :). Es hat zwar eine ganze Weile gedauert, bis ich alles verstanden hatte, aber danach konnte ich das Programm an einem Stück schreiben - ich musste nur wegen ein paar unerwarteter Steuerzeichen in der Datei hier und da feilen und dann gab's noch kleinere Probleme mit meinen Funktionen... Aber das Programm läuft jetzt wunderbar und ist dank der vielen reallocs sehr viel variabler geworden, als mein ursprünglicher Ansatz es ermöglicht hätte.
-
test
-
Hallo!
Ich hab eine Reihe von Dateien, die sehr ähnliche Namen haben und sich nur um Ziffern unterscheiden, welche ich ja durch Variablen ersetzen kann...
Seien diese drei Daten test1, test2, test3
über snprintf wie, am Anfang dieses Threads erläutert, hab ich mir nun über den char "test" und eine Schleife für i=1, i<4 die Namen dieser Dateien oben zusammengebastelt.
was ich nun machen will, ist die Ausgabe von snprintf, welche ich wie auch hier im Beispiel str genannt habe an fopen übergeben, damit nun in dieser Schleife für die i jeweils der Dateiname gebastelt und an fopen übergeben wird.
Nur erwartet fopen als Eingangsparameter ein char, snprintf gibt das str allerdings als string aus.
Der Rest meines Programmes funktioniert einwandfrei, ich möchte nur gerne diese Lücke überwinden und die generierten Filenamen an fopen übergeben können.
Die wesentliche Frage lautet also, wie ich eine string in eine char umwandeln kann... bei c++ gibt es wohl die Funktion c_str(), aber wie wird das in C gelöst?!
Womöglich ist diese Frage ein Standardfrage, dann gebe ich mich auch mit einem Link auf einen bestehenden Thread zufrieden!
Vielen Dank im Vorraus!
blaM
-
fopen erwartet doch gar keinen einzelnen char, sondern auch einen String, also einen char-Zeiger. Genau wie s(n)printf.
#include <stdio.h> int main(void) { for (int i = 1; i <= 3; i++) { char name[20]; sprintf(name, "test%d", i); FILE *file = fopen(name, "w"); fprintf(file, "Ich bin Datei %d!!!\n", i); fclose(file); } return 0; }
-
Oh Gott, das darf doch nicht wahr sein
Ich hatte schon alles richtig gemacht... der einzige Fehler lag darin, dass ich statt
fopen(str, "r");
in meiner File
fopen("str", "r");
stehen hatte....
Daher kam ständig der Speicherzugriffsfehler zu stande und ich dachte ständig, es läge am Aus- und Eingabeformat.... und das ist mir dann erst in deinem Beispielprog aufgefallen----
Aber dennoch vielen Dank für die Mühe namespace invade!!
-
blaM schrieb:
Die wesentliche Frage lautet also, wie ich eine string in eine char umwandeln kann...
gar nicht, es sind völlig unkompatible Typen. Ein char nimmt nur ein einzelenes Zeichen auf, keine Folge von Zeichen (== String).
blaM schrieb:
Daher kam ständig der Speicherzugriffsfehler zu stande
deshalb überprüft man IMMER, ob die Pointer NULL sind
FILE *file = fopen("str", "r"); if(file == NULL) { perror("fopen"); exit(1); }
-
oh... korrekt! danke vielmals für den Nachtrag!