Dynamisches Array



  • ich habe volgendes problem ich muss eine Methode schreiben mit der man ein array auf das doppelte seines aktuellen wertes vergrößert. die im array abgelegten objekte sollen dann in das neue array(doppelte größe) gespeichert werden.

    mir ist inzwischen klar, dass ich new, std::copy, delet verwenden muss aber nicht wie.

    Hier mein code der sicher nicht funzt aber weiter komme ich nicht.

    objects_[capacity_] ist das ausgangs array

    void Inventory::expandArray()
    {
    newCapacity_ = capacity_ * 2; //capazity_ ist die aktuelle größe
    Objects cObjects_[newCapacity];
    int *a3 = new Object [newCapazity_];
    std::copy(objects_, objects+capazity, a3);
    setCapazity(newCapazity);
    delete[] a3; //NICHT VERGESSEN!
    }

    in zeile 4 wollte ich ein array anlegen in dem die Daten zwischengespeichert werden(ist das überhaupt nötig.

    zeile 5 verstehe ich nicht is aus einem bsp. ausm internet wo 2 arrays zusammengefühgt werden



  • So in etwa:

    int *oldarray; 
    int oldarray_size; //gehen wir mal davon aus das beide sinnvoll gefüllt sind
    
    // erweitern:
    int *newarray = new int[oldarray_size*2];
    std::copy(oldarray, oldarray+oldarray_size, newarray);
    delete oldarray[];
    oldarray = newarray;
    oldarray_size *= 2;
    

    oder aber natürlich:

    std::vector<Object> alt;
    alt.resize(alt.size() * 2);
    


  • Das hat mir sehr weitergeholfen ich hab irgendwie das problem dass ich weis was ich ungefähr machen muss es aber nicht in einem gescheiten code formulieren kann.

    das wird dann halt einfach die übung sein oder?!



  • void Inventory::expandArray()
    {
       // Schritt 1: temporäres Array erzeugen
       Objects_* tmp = new Objects[capacity_ *2];
    
       // Schritt 2: bestehende Daten kopieren
       std::copy( objects_, objects_ + capacity_, tmp );
    
       // Schritt 3: bestehende Daten löschen
       delete[] objects_;
    
       // Schritt 4: aktuelle Daten und neue Kapazität merken 
       objects_ = tmp;
       capacity_ *= 2;
    }
    

    Das Problem an deiner Zeile 4 ist, dass du ein lokales Array auf dem Stack anlegst. Wenn deine Objekte relativ groß und die Anzahl der Objekte ebenfalls recht groß sind kann es passieren, dass du nicht genügend Platz auf dem Stack hast, um das Array zu erzeugen -> boom, Programm bleibt mit Stacküberlauf stehen.

    Zeile 5 ist Standardvorgehen der STL, da werden Objekte von Ort A nach Ort B kopiert, es ist eine Art memcpy, bei der C++ Objekte korrekt kopiert werden. Gibt´s im INet jede Menge Hilfe zu, einfach mal google befragen.

    PS:
    Der Code oben ist nicht exception-safe, bei einer Exception während des Kopierens entsteht ein Speicherleck. Experten können gerne Verbesserungsvorschläge anbieten.

    PPS:
    Dein komplettes Inventory kann durch std::vector ersetzt werden, das solltest du tun, wenn es sich nicht um eine Programmieraufgabe handelt, die ein Verständnis für dynamische Speicherverwaltung vermitteln soll.



  • void Inventory::expandArray()
    {
    // Schritt 1: temporäres Array erzeugen
    Objects * tmp = new Objects [capacity_ *2];

    // Schritt 2: bestehende Daten kopieren
    std::copy( objects_, objects_ + capacity_, tmp );

    // Schritt 3: bestehende Daten löschen
    delete[] objects_;

    // Schritt 4: aktuelle Daten und neue Kapazität merken
    objects_ = tmp;
    capacity_ *= 2;
    }

    so nur mehr zum (hoffentlich) totalem verständnis.

    schr.1:
    ich erzeuge einen pointer tmp vom typ objects und weise dem die doppelte größe zu.Hmm wenn eh der pointer weis, dass Objects daherkommen erspare ich mir nicht dann = new "Objects" [capazity*2] also das 2te Objects? bzw was macht new in diesem fall genau

    Schritt 2:
    is klar hab ich gegoogled thx Schritt 3 auch

    Schritt 4
    hab gar nicht gewusst, dass man einem Array sagen kann sei genau so wie das andere.
    bei x=2;
    y=x;
    war es klar.

    P.S.: wie kann ich so einen code posten so wie ihr das macht



  • [.cpp]...[./cpp] ohne die . in den Klammern.

    Das "new" fordert den Speicher auf dem Heap an. Das heißt du hast ab dann auch die Verantwortung den wieder freizugeben wenn er nicht mehr benötigt wird (wie du es mit dem delete[] für das alte Array machst).



  • Codetags benutzen:

    und
    

    Du solltest vielleicht ein bisschen Zeit in das Verständnis von Zeigern stecken, wenn dir nicht klar ist, warum man Zeiger einander zuweisen kann.


  • Mod

    EvilStuff schrieb:

    schr.1:
    ich erzeuge einen pointer tmp vom typ objects und weise dem die doppelte größe zu.Hmm wenn eh der pointer weis, dass Objects daherkommen erspare ich mir nicht dann = new "Objects" [capazity*2] also das 2te Objects? bzw was macht new in diesem fall genau

    Oha. Grundlagen lernen!
    Du hast einen Pointer tmp auf ein Objects. New erzeugt ein Array von Objectss mit 2*capacity. Die Adresse dieses Arrays wird tmp zugewiesen.

    Schritt 4
    hab gar nicht gewusst, dass man einem Array sagen kann sei genau so wie das andere.
    bei x=2;
    y=x;
    war es klar.

    Oha. Grundlagen lernen!
    Du hast einen Pointer objects_ auf Objects. Und einen Pointer tmp auf Objects. Pointer kann man einander zuweisen. Somit zeigt objects_ hinterher auf das Array auf das tmp zeigt. Ansonsten passiert da nichts.

    P.S.: wie kann ich so einen code posten so wie ihr das macht

    Guck mal unter dem Editierfeld, bei den Smileys. Da sind auch lauter andere tolle Optionen zur Textformatierung.



  • ich geb mein bestes die grundlagen zu lernen.
    das ist mein erstes Bsp. und das gleich mit .h .cpp und die main wurde bereitgestellt(ausser die aus meinem C++ Buch).
    ich geb zu ich bin total überfordert mit dem ganzen deshalb hab ich ja in einem Forum gepostet.
    Also hoffe ich auf nachsicht.



  • Was bedeutet

    Object** objects_[capacity_]
    capacity=1
    

    dass ich ein Pointer Array(objects_) vom Typ Object anlege und es im selben schritt dereferenziere d.h. ich habe dann wenn ich das object_ Array an stelle 0 z.b.: so aufrufe

    Object test;
    test = object_[0]
    

    nicht die adresse sondern die darin gespeicherte info an test weitergegeben habe oder?!?!?


  • Mod

    Evilstuff schrieb:

    Was bedeutet

    Object** objects_[capacity_]
    capacity=1
    

    dass ich ein Pointer Array(objects_) vom Typ Object anlege und es im selben schritt dereferenziere d.h. ich habe dann wenn ich das object_ Array an stelle 0 z.b.: so aufrufe

    Object test;
    test = object_[0]
    

    nicht die adresse sondern die darin gespeicherte info an test weitergegeben habe oder?!?!?

    Nein. Object** objects_[capacity_] ist einfach ein Zeiger auf einen Zeiger auf ein Array von Objects. Und test = object_[0] dürfte gar nicht compilieren (hast du es ausprobiert?) weil du versuchst, einem Object einen Zeiger auf ein Array von Objects zuzuweisen.



  • nein ich habs nicht compiliert. da alles in meiner klasse noch nicht funzt. in meiner literatur werden zwar zeiger behandelt aber nicht zeiger auf zeiger und ka. was. man sollte sich das anscheinend dann selbst zusammenreimen und du sihst ja was dabei rauskommt. in meiner vorlesung wurde dass auch nicht behandelt es hat den anschein als würde die aufgabe nach dem motto friss un stirb sein. nach mehrmaligen durchlesen meines buches bin ich noch immer kein stück gescheiter kann sein dass es an mir ligt oder an der kompexität der aufgabenstellung.

    ich versuch jez schon seit 2 ner woche das ganze hinzubekommen aber ich weis nicht 😕
    kannst du mir noch etwas empfehlen damit ich c++ besser checke



  • Evilstuff schrieb:

    [...]
    Schritt 4
    hab gar nicht gewusst, dass man einem Array sagen kann sei genau so wie das andere.
    bei x=2;
    y=x;
    war es klar.

    objects_ war -- obwohl das eigentlich nie explizit erwähnt wurde -- ein Zeiger und kein Array. Das ist ein großer Unterschied. Mit objects_ = tmp; wurde der Zeiger auf das neue vergrößerte Array umgebogen.

    Evilstuff schrieb:

    Object** objects_[capacity_]
    capacity=1
    

    Das ergibt nicht viel Sinn. Das erste wäre eine Definition eines Arrays mit statischer Größe: object_ ist ein Array von capacity_ vielen Zeigern auf Zeigern auf Objekte des Typs Object . Damit das klappt, müsste capacity_ aber eine Compile-Zeit-Konstante sein. Ich glaube auch nicht, dass es das ist, was Du willst.

    ich versuch jez schon seit 2 ner woche das ganze hinzubekommen aber ich weis nicht 😕
    kannst du mir noch etwas empfehlen damit ich c++ besser checke

    Du hast Zeiger und Arrays noch nicht 100%ig verstanden. Versuch das nachzuholen.

    int meinefunktion(int n) {
      int foo[] = {1,2,3};  // foo ist vom Typ int[3] -- ein Array mit einer
                            // Länge, die zur Compile-Zeit feststeht. foo ist
                            // kein Zeiger, sondern direkt eine Sammlung von 3
                            // hintereinander liegenden ints im automatischen
                            // Speicherbereich -- also der Ort, wo "normale lokale
                            // Variablen" auch leben.
    
      int* p = foo;         // p ist ein Zeiger auf int. Hier findet
                            // "array to pointer decay" statt. p wird mit
                            // der Adresse des ersten Array-Elements initialisiert.
    
      p[2] += 5;            // sieht nach Array-Syntax aus, p ist aber immer noch
                            // ein Zeiger. Der Klammer-Operator bei p[2] ist hier
                            // eine Abkürzung für *(p+2). --> Zeigerarithmetik +
                            // Dereferenzieren.
    
      int* q = new int[n];  // q ist auch ein Zeiger auf int. In diesem Fall auf das
                            // erste Element eines n-elementigen dynamischen Arrays.
                            // Der Wert von n ist zur Compile-Zeit noch nicht
                            // bekannt.
    
      for (int i=0; i<n; ++i)
        q[i] = 99;          // Werte der Array-Elemente auf 99 setzen.
    
      delete[] q;           // Löschen des dynamischen Arrays
    
      return foo[2];        // gibt den Wert 8 zurück
    }
    

  • Mod

    EvilStuff schrieb:

    ich versuch jez schon seit 2 ner woche das ganze hinzubekommen aber ich weis nicht 😕
    kannst du mir noch etwas empfehlen damit ich c++ besser checke

    Dann bietet sich ein anderes Lehrbuch an. Was benutzt du denn derzeit?

    Wenn es speziell um das Thema Pointer geht, wird man sicher auch gute Online-Tutorials dazu finden. Die meisten allgemeinen Tutorials sind zwar ziemlich schlecht, aber zu speziellen Fragen gibt es gute Anleitungen. Zur Not auch reine C statt C++ Tutorials - die Behandlung und der Nutzen von Zeigern ist in beiden Sprachen ziemlich gleich.



  • Ich denke beim Thema Zeiger ist es oftmals auch ganz nützlich eine Stufe weiter runter zu gehen und sich klar zu machen, wie üblicherweise Speicher aufgebaut ist und wie da Daten drin gespeichert sind. Wenn man das einmal in etwa begreift, dann eribt sich die Funktionsweise von Zeigern recht schnell von selbst.

    Ein gutes (besseres?) Buch ist aber auch eine gute Idee.


Log in to reply