Hallo, habe zwei kleine Funktionen geschrieben, die aus dem main aufgerufen werden: int main(void) { int *m, *n; double *arrayzeiger; einlesen (m, n, arrayzeiger); ausgeben (m, n, arrayzeiger); return (0); } void einlesen (int *m, int *n, double *arrayzeiger) { int temp; char Dateiname[50]; FILE *Datei; printf ("bitte Dateinamen eingeben\n"); scanf ("%s", Dateiname); Datei = fopen (Dateiname, "r"); if (Datei == NULL) { printf ("Datei nicht gefunden\n"); exit (1); } fscanf (Datei, "%i", m); fscanf (Datei, "%i\n", n); ZV_c = (double*) malloc (n sizeof (double*)); for (temp= 0; temp< *n; temp++) { fscanf (Datei, "%lf\n", &arrayzeiger[temp]); } fclose (Datei); } void ausgeben (int *m, int *n, double *arrayzeiger) { int temp; for (temp= 0; temp< *n; temp++) { printf ("nachher: = %lf\n", arrayzeiger[temp]); } } Die einlesen Funktion holt sich aus der Datei die Größe des Arrays und belegt anschließend mittels malloc Speicher fürs das Array. Das Problem ist nur, dass mir die Funktion nicht den neuen Zeiger von malloc zurückgibt, der also nur lokal existiert :=( Deshalb habe ich den Aufruf der Funktion auch schon mal zu &(*arrayzeiger) verändert, womit ich ja eigentlich die Adresse des Zeigers in die Funktion bekommen sollte. Aber das klappt auch nicht. Wie macht man das richtig? Gruß, Mark P.S. Wenn ich den Speicher mit malloc schon vorher im main reserviere geht alles gut (da der Zeiger ja auch nicht verändert wird).
Es ist sowieso Zufall, dass das Programm funktioniert. Du speicherst in der Zeile "fscanf (Datei, "%lf\n", &arrayzeiger[temp]);" wegen der uninitialisierten Variable arrayzeiger irgendwo im Speicher. Einlesen könnte den allozierten Speicher als Pointer an Main zurückgeben. Und am Ende von main() (oder bei neuem Aufruf von einlesen()) kannst du den per free() auch wieder freigeben.
1 | void * einlesen (int *m, int *n, double *arrayzeiger) // <== |
2 | {
|
3 | int temp; |
4 | char Dateiname[50]; |
5 | FILE *Datei; |
6 | |
7 | printf ("bitte Dateinamen eingeben\n"); |
8 | scanf ("%s", Dateiname); |
9 | Datei = fopen (Dateiname, "r"); |
10 | |
11 | if (Datei == NULL) |
12 | {
|
13 | printf ("Datei nicht gefunden\n"); |
14 | exit (1); |
15 | }
|
16 | |
17 | fscanf (Datei, "%i", m); |
18 | fscanf (Datei, "%i\n", n); |
19 | |
20 | if (arrayzeiger != NULL) // <== |
21 | {
|
22 | free(arrayzeiger); |
23 | }
|
24 | |
25 | arrayzeiger = (double *) malloc (*n * sizeof (double*)); // <== |
26 | |
27 | if (arrayzeiger == NULL) // <== |
28 | {
|
29 | printf ("Speicherproblem\n"); |
30 | fclose (Datei); |
31 | exit (1); |
32 | }
|
33 | |
34 | for (temp = 0; temp < *n; temp++) |
35 | {
|
36 | fscanf (Datei, "%lf\n", &arrayzeiger[temp] /* oder arrayzeiger+temp */); // <== |
37 | }
|
38 | |
39 | fclose (Datei); |
40 | |
41 | return ((void *)arrayzeiger); // <== |
42 | }
|
43 | |
44 | int main(void) |
45 | {
|
46 | int *m, *n; |
47 | double *arrayzeiger = NULL; // <== |
48 | |
49 | arrayzeiger = (double *) einlesen (m, n, arrayzeiger); |
50 | ausgeben (m, n, arrayzeiger); |
51 | free((void *)arrayzeiger); // <== |
52 | |
53 | return (0); |
54 | }
|
Eigentlich dürfte noch weniger funktionieren... da die Zeiger alle uninitialisiert sind d.h. wenn einlesen in main aufgerufen wird, bekommt einlesen irgendetwas nur keine Zeiger auf benutzbare Variablen in denen die neuen Werte gespeichert werden könnten. Soll arrayzeiger nach dem Aufruf auf den angeforderten Speicher zeigen, muss einlesen entweder den neuen Zeiger zurückliefern (double* einlesen(int* m, int* n) oder man übergibt einen Zeiger auf einen Zeiger.
1 | // aus
|
2 | int *m, *n; |
3 | double *arrayzeiger; |
4 | einlesen(m, n, arrayzeiger) |
5 | |
6 | // müsste entweder
|
7 | int m, n; |
8 | double *arrayzeiger; |
9 | einlesen(&m, &n, &arrayzeiger); |
10 | // oder
|
11 | int mv, nv; |
12 | int *m = &mv, *n = &nv; |
13 | einlesen(m, n, &arrayzeiger) |
14 | // werden
|
Stimmt. Typ. Fall von Problemfixierung bei mir.
Hallo, vielen Dank für die schnelle Rückmeldung. Nun bleibt noch ein Problem: später sollte die Funktion mehrere Arrays einlesen, d.h. ich müstte auch mehrere Zeiger zurückgeben. Aber wenn ich erst mal weiß wie ich die Zeiger korrekt in die Funktion ein/übergeben bekomme, dann probliere ich da erst mal weiter und melde mich evtl. noch mal. Danke, Mark
Hallo, habe das ganze nun zu
1 | void einlesen (int *m, int *n, double **arrayzeiger) |
2 | { |
3 | int temp; |
4 | char Dateiname[50]; |
5 | |
6 | FILE *Datei; |
7 | printf ("bitte Dateinamen eingeben\n"); |
8 | scanf ("%s", Dateiname); |
9 | Datei = fopen (Dateiname, "r"); |
10 | if (Datei == NULL) |
11 | { |
12 | printf ("Datei nicht gefunden\n"); |
13 | exit (1); |
14 | } |
15 | fscanf (Datei, "%i", m); |
16 | fscanf (Datei, "%i\n", n); |
17 | if (*arrayzeiger != NULL) |
18 | { |
19 | free (*arrayzeiger); // <== evtl. ist hier auch ein Fehler |
20 | } |
21 | *arrayzeiger = (double*) malloc (*n * sizeof (double*)); |
22 | if (*arrayzeiger == NULL) |
23 | { |
24 | printf ("Speicherproblem\n"); |
25 | fclose (Datei); |
26 | exit (1); |
27 | } |
28 | for (temp = 0; temp < *n; temp++) |
29 | { |
30 | fscanf (Datei, "%lf\n", &(*arrayzeiger)[temp]); |
31 | } |
32 | fclose (Datei); |
33 | } |
34 | |
35 | void ausgeben (int m, int n, double **arrayzeiger) |
36 | int temp; |
37 | for (temp= 0; temp< *n; temp++) |
38 | { |
39 | printf ("nachher: = %lf\n", arrayzeiger[temp]); |
40 | } |
41 | |
42 | int main(void) |
43 | { |
44 | int m, n; |
45 | double *arrayzeiger = NULL; |
46 | einlesen (&m, &n, &arrayzeiger); |
47 | ausgeben (m, n, &arrayzeiger); |
48 | //free (*ZV_c); // <== schlägt immer fehl |
49 | return (0); |
50 | } |
geändert. Nun läuft es (mal wieder), aber die free Aufrufe scheitern (bzw. der letzte auf jeden Fall, bei dem in der einlesen Funktion bin ich mir unsicher). Insofern nehme ich stark an, dass da mmer noch was nicht stimmt. Warum der letzte free Aufruf scheitert wundert mich, das das main ja jetzt den in arrayzeiger die Position/Adresse des eigentlichen Arrays hat. Werde da wohl noch mal ne Nacht drüber schlafen müssen... Muss gestehen, so richtig klar ist mir das leider noch nicht. Mark
Das free in einlesen ist soweit richtig, dafür das free in main nicht. Die Funktion ausgeben dürfte auch nur falsche Werte ausgeben, ausser arrayzeiger[temp] wäre ein Tippfehler und sollte *arrayzeiger[temp] sein. arrayzeiger[temp] wäre nur dann richtig, wenn auch nur ein einfacher Zeiger übergeben werden würde. So wie es jetzt da steht würde der tempte (nicht vorhandene Zeiger auf einen double Zeiger) ausgewertet. Zur Verdeutlichung:
1 | |
2 | double* array1 = (double *)malloc(sizeof(double) * 4); |
3 | double* array2 = (double *)malloc(sizeof(double) * 4); |
4 | double array3[4] = { 1.0, 2.0, 3.0, 4.0 }; |
5 | |
6 | double* ptr = array1; |
7 | double* ptr2[3] = { array1, array2, array3 }; |
8 | |
9 | double** dptr1 = &ptr; |
10 | double** dptr2 = &ptr2[0]; |
11 | |
12 | array1[0] = 1.1; array1[1] = 2.1; array1[2] = 3.1; array1[3] = 4.1; |
13 | array2[0] = 1.2; array2[1] = 2.2; array2[2] = 3.2; array1[3] = 4.2; |
14 | |
15 | // was geben die folgenden printfs aus?
|
16 | printf("%p", dptr[0]); |
17 | printf("%f", *dptr[0]); |
18 | printf("%f", **dptr); |
19 | printf("%p", dptr2[1]); |
20 | printf("%f", *dptr2[1]); |
21 | printf("%f", **dptr2); |
> double* array1 = (double *)malloc(sizeof(double) * 4);
Den Rückgabewert von malloc sollte man nicht casten. Der Cast ist
unnötig und verdeckt potentielle Fehler.
Rolf Magnus wrote: >> double* array1 = (double *)malloc(sizeof(double) * 4); > > Den Rückgabewert von malloc sollte man nicht casten. Der Cast ist > unnötig und verdeckt potentielle Fehler. In C++ ist dieser Cast zwingend nötig. In C nicht...
In C++ verwendet man eh gleich den Operator new. In C sollte man wie gesagt den Cast besser weglassen.
Hallo, habe nun alles soweit ohne Fehler am laufen, nur das letzte free bereitet mir nach wie vor noch Kopfzerbrechen. Meiner Meinung (und dem C-Buch Beispiel) nach sollte ein [...] ausgeben (m, n, &arrayzeiger; if (ZV_c != NULL) { free (arrayzeiger); } return (0); } richtig sein. Das fliegt mir aber immer noch um die Ohren. Da ich gelesen habe, dass nach Terminierung des Programms der Speicher eh wieder freigegebn wird, hat das jetzt Zeit bis morgen. Werde da noch mal ein paar Dinge ausprobieren. Ist zwar mit Sicherheit kein sauberer Programmierstil, aber das zählt ja zum Glück auch nicht... Bis hierhin: vielen Dank für eure Hilfe, habe wieder was dazugelernt und steige da (so langsam) durch. Mark
muss das nicht "free(*arryzeiger)" heißen....aslo mit "*"?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.