Zeiger auf Struct als rückgabewert von Funktion ?



  • 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.
    Entweder

    struct 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 statt struct tiere ein unsigned 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:

    http://ideone.com/jsHd2



  • @ 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 ?


Anmelden zum Antworten