Strukturinhalt kopieren



  • Hi, habe ein Kopierproblem mit Strukturen. Ich habe folgende Struktur:

    struct _Test
    {
    int a;

    int nAnzSubTests;

    float b;

    _Test *SubTests;
    };

    Die Struktur enthält u.a. einen Zeiger auf weitere Strukturen, also eine Liste mit weiteren Strukturen.
    Nun will ich eine Funktion schreiben, die z.B. als Parameter zwei Zeiger auf diese Struktur übernimmt und komplett den Inhalt von Struktur 1 in die zweite kopiert, d.h. auch die Unterstrukturen sollen vollständig mitkopiert werden.

    Das bedeutet aber auch, dass ich 1. für die ganze neue Struktur Speicher reservieren muss und 2. auch Speicher für die Unterstrukturen. Da es eine Liste sein soll, muss ich z.B. den Zeiger SubTests an die nächste Stelle (++) setzen usw.

    Zudem dachte ich an eine rekursive Funktion, die sich aufruft, um die Substrukturen auch zu kopieren.

    Das Ganze gerade beschriebene habe ich auch irgendwie umgesetzt. Nur: Als die erste Unterstruktur kopiert werden sollte, also die Funktion sich mit der ersten Unterstruktur, die kopiert werden soll, und der Zielunterstruktur aufgerufen hatte, war für die zu kopierende Struktur kein Speicher reserviert (er wurde aber vorher außerhalb der Funktion bereits reserviert!).

    Lange Rede kurzer Sinn, wie würdet ihr das Problem angehen? Hat das was mit Bäumen etc. zu tun?



  • // Namen, die wie _Test mit einem Unterstrich und einem Großbuchstaben beginnen,
    // sollte man nicht benutzen, um keine Kollision mit compilerinternen Namen zu riskieren,
    // also lieber Test statt _Test
    struct Test
    {
    	int a;
    	int nAnzSubTests;		
    	float b;
    	Test *SubTests;
    };
    

    JensE schrieb:

    Nun will ich eine Funktion schreiben, die z.B. als Parameter zwei Zeiger auf diese Struktur übernimmt und komplett den Inhalt von Struktur 1 in die zweite kopiert, d.h. auch die Unterstrukturen sollen vollständig mitkopiert werden.

    Das bedeutet aber auch, dass ich 1. für die ganze neue Struktur Speicher reservieren muss und 2. auch Speicher für die Unterstrukturen.

    Da ist ein kleiner Widerspruch drin. Du hast eben gesagt, du willst der Funktion einen Zeiger auf das Original und einen Zeiger auf einen "Rohling" übergeben, in den dann die Kopie geschrieben wird. Das impliziert, dass dafür schon Speicher reserviert wurde.

    Ich vermute, dass dein Problem damit zusammenhängt, dass dir das nicht klar war.

    Ohne dass ich mir über deine Idee den Kopf zerbreche, eine ganz simple rekursive Lösung, die auch funktionieren sollte, sieht so aus:

    Test * copy_structure(Test * orig)
    {
      if (orig != 0)
      {
        Test * result = new Test;
        result->a = orig->a;
        // etc...
        result->SubTests = copy_structure(orig->SubTests);
        return result;
      }
      else
        return 0;
    }
    

    Ich hoffe es macht nichts, dass es nicht exakt deiner Spezifikation entspricht.



  • Werde ich dann gleich mal ausprobieren, danke!



  • @Bashar:

    Der Code, den du gepostet hast, funktioniert.

    Das Problem ist nur, dass eine Teststruktur nicht nur eine Unterstruktur haben können soll, sondern der Zeiger auf eine Teststruktur soll auf eine Liste solcher Strukturen verweisen und ein anderer Member der Struktur speichert beispielsweise, wieviele Unterstrukturen die Struktur enthält.

    Nun will ich die gesamte Liste kopieren.

    Da dachte ich, ich erhöhe den Zeiger des Zieles und der Quelle in einer for-Schleife (Anzahl Unterstrukturen) immer mit ++ und rufe jeweils die Kopierfunktion rekursiv auf, setze die Zeiger nach der Schleife wieder an ihre alte Zeigeposition zurück.

    Das Ergebnist ist aber, dass dennoch nur der erste Wert der Unterliste kopiert wurde, die anderen Werte aber irgendwelche zufällig im Speicher gelegenen Werte
    sind. Hier der Code meiner Copy-Funktion:

    Test * copy_structure(Test * orig) 
    { 
      if (orig != 0) 
      { 
        Test * result = new Test; 
        result->a = orig->a; 
    
        Test *pResCopy = result->SubTests;
        Test *pOrigCopy = orig->SubTests;
    
        for (int i = 0; i < orig->nAnzSubTests)
        {
          pResCopy = copy_structure(pOrigCopy);
    
          pResCopy++;
          pOrigCopy++;
        }
    
        return result; 
      } 
    
      return 0; 
    }
    

    Was ist daran falsch?



  • Achso, du meinst eigentlich Array, wenn du Liste sagst. Sag das doch! 🙂 Darf ich mir das also als Baum vorstellen?

    Dann funktioniert mein Ansatz nicht, weil copy_structure immer einzeln allozierte Strukturen zurückgibt. Also nochmal komplett von vorn:

    void copy_structure(Test * orig, Test * target)
    {
      target->a = orig->a;  target->b = orig->b;
      target->nAnzSubTests = orig->nAnzSubTests;
      if (orig->nAnzSubTests != 0)
      {
        target->SubTests = new Test[orig->nAnzSubTests];
        for (int i = 0; i < orig->nAnzSubTests; ++i)
          copy_structure(&orig->SubTests[i], &target->SubTests[i]);
      }
      else
        target->SubTests = 0;
    }
    

    Der Hauptunterschied liegt darin, dass du vorher Speicher für die Kopie besorgen musst, sei es auf dem Stack oder auf dem Heap.



  • Klasse, danke, hat so funktioniert. 🙂


Anmelden zum Antworten