Zeiger auf Struct als rückgabewert von Funktion ?
-
Hi,
ich komme gerade nicht weiter. Folgenden Code habe ich bis jetzt:
#include <stdio.h> #include <stdlib.h> struct Tdata { char *text; int zahl; }; struct elemente { struct Tdata *element; }; struct elemente *get_elemente() { // Soll vom Hauptprogramm aufgerufen werden // Hier wird create_elemente aufgerufen um speicher zu reservieren } struct elemente *create_elemente(int num) { struct elemente *temp; temp->element = malloc(num * sizeof(struct Tdata)); return(temp); }
Ich komme nun aber mit dem struct als Rückgabewert einer Funktion nicht weiter. Wenn ich weder eine Kopie noch einen Pointer auf ein bestehendes Struct an die Funktion übergebe wie kann dann die Funktion create_elemente speicher reservieren ?
Wenn ich in der Funktion create_elemente ein Struct anlege den speicher reserviere und einen Pointer auf struct zurückgebe existiert dieses struct doch nach ablauf der Funktion nicht mehr ?
Ich hoffe jemand kann mir ein wenig auf die Sprüge helfen
-
blamaster schrieb:
#include <stdio.h> #include <stdlib.h> struct Tdata { char *text; int zahl; }; struct elemente { struct Tdata *element; }; struct elemente *get_elemente() { // Soll vom Hauptprogramm aufgerufen werden // Hier wird create_elemente aufgerufen um speicher zu reservieren } struct elemente *create_elemente(int num) { struct elemente *temp; temp->element = malloc(num * sizeof(struct Tdata)); return(temp); }
Wenn ich in der Funktion create_elemente ein Struct anlege den speicher reserviere und einen Pointer auf struct zurückgebe existiert dieses struct doch nach ablauf der Funktion nicht mehr ?
Wie kommst Du darauf? Speicher, der mit malloc angefordert wurde, bleibt Dir so lange erhalten, bis es mit free wieder freigegeben wurde, mit realloc vergrößert wurde oder Dein Programm beendet word.
mfg Martin
-
Du kannst auch eine struct direkt zurückgeben.
Zu deinem Problem:
struct elemente *create_elemente(int num) { struct elemente *temp; // Hier hast du einen Zeiger auf elemente und keinen Speicherplatz temp->element = malloc(num * sizeof(struct Tdata)); //Hier versuchst du aber auf diesen Speicher zuzugreifen. (mit ->element) return(temp); }
Also erstmal Speicher für elemente besorgen, dann Speicher für Tdata.
Wozu brauchst du überhaupt die struct elemente ?
-
Du meinst so oder ?
struct tiere *create_tiere(int num) { struct tiere temp; temp.tier = malloc(num * sizeof(struct Tdata)); return(temp); }
-
Bei dem Code ist temp nur eine lokale Variable, ist also außerhalb der Funktion nicht gültig. Du bräuchtest zweimal malloc.
-
Nein, nicht ganz. Mit dem return gibst du eine struct zurück und keinen Zeiger.
Entwederstruct tiere create_tiere(int num) // ^ Da ist der * weg { struct tiere temp; temp.tier = malloc(num * sizeof(struct Tdata)); return(temp); }
oder
struct elemente *create_elemente(int num) { // Ohne Fehlerbehandlung. struct elemente *temp; temp = malloc(sizeof(struct elemente)); // Speicherplatz für elemente temp->element = malloc(num * sizeof(struct Tdata)); return(temp); }
@F
Man kann structs genauso zurückgeben wie integrale Werte.
Würde da stattstruct tiere
einunsigned long
stehen, hättest du auch keine Probleme.
In einigen der aller-aller-ersten C Versionen ging das nicht.
-
Hi,
das meinte ich mit der Aussage:
Wenn ich in der Funktion create_elemente ein Struct anlege den speicher reserviere und einen Pointer auf struct zurückgebe existiert dieses struct doch nach ablauf der Funktion nicht mehr
Nur wie kann ich innerhalb der Funktion eine nicht nur lokalte Struct erstellen, bzw was genau meinst du mit dem 2x malloc ?
Die Pointer machen mich bei c wirklich noch wahnsinnig
-
Du kannst keine Zeiger auf lokale Variablen zurückgeben.
Du kannst sehr wohl Zeiger auf Speicher zurückgeben, den du mit malloc besorgt hast.struct tiere *create_tiere(int num) { // ^ hier ist ein Zeiger struct tiere temp; // lokale Variable (vom Stack) temp.tier = malloc(num * sizeof(struct Tdata)); return(&temp); Das geht nicht, da temp nach dem verlassen nicht mehr gültig ist // ^ & wegen Zeiger }
Der Speicher auf den
temp.tier
zeigt ist auch weiterhin gültig, nur kommst du da nicht mehr dran, da temp ungültig wird.
-
Vielen Dank schonmal das habe ich jetzt soweit verstanden
Die Funktion gibt nun also einen Pointer auf den reservierten Speicherplatz zurück.
Wie kann ich weiter vorgehen, wenn ich den reservierten Speicherplatz jetzt nutzen möchte ?
struct tiere *get_tiere_from_file() { struct tiere *test; test = create_tiere(length); }
Das gibt nun den Fehler "Assigment makes pointer without cast"
Wenn ich nun versuche einen cast zu machen:
struct tiere *get_tiere_from_file() { struct tiere *test; test = (struct tiere*)create_tiere(length); }
Nun kommt "Conflicting types for 'create_tiere'"
-
Welche Version von create_tiere() hast du denn jetzt?
-
struct tiere *create_tiere(int num)
{
struct tiere *temp;temp = malloc(sizeof(struct tiere));
temp->tier = malloc(num * sizeof(struct Tdata));
return(temp);
}
-
Poste mal das kleinste compilierbare Program, das den Fehler verursacht.
-
#include <stdio.h> #include <stdlib.h> struct Tdata { char *name; int groesse; }; struct tiere { struct Tdata *tier; }; struct tiere *get_tiere_from_file() { struct tiere *test; test = (struct tiere*) create_tiere(5); //return(test); } struct tiere *create_tiere(int num) { struct tiere *temp; temp = malloc(sizeof(struct tiere)); temp->tier = malloc(num * sizeof(struct Tdata)); return(temp); } int main(int argc, char *argv[]) { struct tiere main; // main = get_tiere_from_file(); system("PAUSE"); return 0; }
-
Du verwendest eine erst nachträglich deklarierte Funktion, dafür trifft der Compiler bestimmte Standardannahmen, die bei dir schiefgehen:
-
@ wutz
stimmt so funktioniert es
Hier mal der aktuelle Code. Ein Problem gibt es jetzt scheinbar noch. Es lässt sich nun zwar alles compilieren, allerdings stürzt das Programm ab.
Die Probleme treten vermutlich bei enter_tier(t, i, text, size) auf.#include <stdio.h> #include <stdlib.h> struct Tdata { char *name; int groesse; }; struct tiere { struct Tdata *tier; }; // Allokiert speicher fuer den Namen (size = lange des namens) // eines Tieres und trŠgt das Tier an der Stelle index ein! void enter_tier(struct tiere *t, int index, char *name, int size) { t->tier[index].groesse = size; t->tier[index].name = malloc((strlen(name) * sizeof(char)) + 1); strcpy(t->tier[index].name, name); } // Allokiert Speicher fuer die gegebene Datenstruktur // (num = Anzahl der Tiere) struct tiere *create_tiere(int num) { struct tiere *temp; temp = malloc(sizeof(struct tiere)); temp->tier = malloc(num * sizeof(struct Tdata)); return(temp); } // Oeffnet die Datei tiere.txt und ruft die Funktionen // create_tiere und enter_tier auf! struct tiere *get_tiere_from_file() { char *text; int length, size; int i = 0; FILE *fp; struct tiere *t; fp = fopen("tiere.txt", "r"); fscanf(fp,"%d",&length); t = create_tiere(length); while(fscanf(fp, "%s%d\n",&text, &size) != EOF) { enter_tier(t, i, text, size); i++; } for(i = 0; i < length; i++) { printf("%s %d\n", t->tier[i].name, t->tier[i].groesse); } fclose(fp); return(t); } // gibt den gesamten Speicher am Ende des Programms wieder frei! void destroy_tiere(struct tiere *t, int num) { free(t->tier); free(t); } int main(int argc, char *argv[]) { struct tiere *t; t = get_tiere_from_file(); destroy_tiere(t, 0); system("PAUSE"); return 0; }
Inhalt der "tiere.txt":
5 Loewe, 120 Gorilla, 170 Maus, 5 Hund, 40 Giraffe, 450
-
struct tiere *get_tiere_from_file() { char *text; // Das text hat keinen Speicher wo der Text abgelegt werden kann. Da gehört ein Array hin (Oder dynamischer Speicher) .... while(fscanf(fp, "%s%d\n",&text, &size) != EOF) // Das & ist bei text falsch, // Egal ob text ein Zeiger oder Array ist. // Das ',' gehört mit zum Namen. Wenn da aber "Tier , 11" steht, hast du ein Problem
-
Perfekt mit einem Char array klappt es
Gibt es eine Möglichkeit das "," direkt über die Formatierungsangabe der fscanf heraus zu filtern ?