Ein Array nachträglich vergrößern



  • AHH der Haupfehler lag wo daran das es nicht "Mitarbeiter *&Firma" ist. wie templäd gesagt hat, doch um die Situation jetzt noch n bissel schwieriger zu machen fänd ich toll alles mit Zeigern zu machen 🙂
    Hab mal was gehört das man auch Zeiger auf Zeiger machen darf also **Z oder so?

    #include <iostream>
    using namespace std;
    
    class Mitarbeiter
    {
        public:
        Mitarbeiter();
        ~Mitarbeiter();
        void SetGehalt(int a) {Gehalt=a;}
        void SetAlter(int a) {Alter=a;}
        void SetName(string a) {Name=a;}
        int GetGehalt(){return Gehalt;}
        int GetAlter() {return Alter;}
        string GetName() {return Name;}
    
        private:
        int Gehalt;
        int Alter;
        string Name;
    };
    void FromArrayToNewArray(Mitarbeiter *Firma,int OldArrayEnd,int NewArrayEnd);
    Mitarbeiter::Mitarbeiter()
    {
    
    }
    
    Mitarbeiter::~Mitarbeiter()
    {
    
    }
    
    int main()
    {
    
        int BenEing1;
        int BenEing2;
        cout << "Wieviele Mitarbeiter sollen Angestellt werden?\n";
        cin >> BenEing1;
        Mitarbeiter *Firma=new Mitarbeiter[BenEing1];
        cout << &Firma << " " << Firma << endl;
        for (int i=0;i<BenEing1;i++)
        {
            Firma[i].SetGehalt(i+(i*80)+200);
        }
        cout << "Wieviele neue Mitarbeiter?\n";
        cin >> BenEing2;
        FromArrayToNewArray(Firma,BenEing1,BenEing2);
    
        //Testen obs geklappt hat
        cout << "TEST\n";
        for (int i=0;i<BenEing1;i++)
        {
            cout << Firma[i].GetGehalt() << endl;
        }
    
        return 0;
    }
    
    void FromArrayToNewArray(Mitarbeiter **Firma,int OldArrayEnd,int NewArrayEnd)
    {
        Mitarbeiter *temp=new Mitarbeiter[OldArrayEnd];
        for (int i=0;i<OldArrayEnd;i++)
        {
            temp[i]=*Firma[i];
        }
        delete []*Firma;
        *Firma=NULL;
        *Firma=new Mitarbeiter[NewArrayEnd];
        for (int i=0;i<OldArrayEnd;i++)
        {
            *Firma[i]=temp[i];
        }
    }
    

    Hätte das dann irgendwie so gemacht,aber umso länger ich esmir anchaue desto konfuser wird es! Außerdem läuftsnicht siehe hier:
    Compiling: C:\MinGW\Andi\mitarbeiter.cpp
    Linking console executable: C:\MinGW\Andi\mitarbeiter.exe
    C:\MinGW\Andi\mitarbeiter.o:mitarbeiter.cpp:(.text+0x3aa): undefined reference to `FromArrayToNewArray(Mitarbeiter*, int, int)'
    collect2: ld returned 1 exit status
    Process terminated with status 1 (0 minutes, 0 seconds)
    0 errors, 0 warnings

    Hoffe das ihr mir wieder weiterhelfen könnt.

    PS: Sry das ich erst so spät zurückschreibe (musst lööörnen), äh und das ganze hier hat eientlich nichts mit einer Schulaufgabe zu tun.



  • Stromberg schrieb:

    1.Kann mir jemand sagen wie ich am besten nachträglich ein Array vergrößere. Damit meine ich dass der Benutzer die Array größe bestimmt (also ist noch nicht zur Laufzeit bekannt), und dann nachträglich nochmal vergrößern kann. Ich hab das mal umgesetzt, wie man bei dem "Test" sehen kann funktioniert es nicht, bzw nicht immer, manchmal kommt was manchmal auch nicht. Das blick ich überhaupt nicht! Ich glaub das liegt irgendwie an den Zahlen die der Benutzer eingibt, mh bin grad bissel verwirrt. Was mach ich falsch?

    2.Geht das auch irgendwie mit weniger Code einfacher etc.. weil ich weiß nicht ob die Funktion "FromArrayToNewArray" zu umständlich ist. Wie würdet den ihr das machen?

    erzeuge doch einfach ein Array aufem heap. das array kannst du dann während der laufzeit des programms bzw bei der erschaffung vergrößern.

    char *z = new char[länge]
    

    das is jetzt nur ein beipiel wie es geht.
    z wird dann als zeiger auf ein Array auf dem Heap erschaffen. da das auf dem heap ist,so kannst du zb die größe im vorherigem code durch eine benutzereingabe auswählen.
    ob man es auch nach der erschaffung verändern kann denke ich nicht da das ja eigentlich zum absturz führen kann.



  • Also würde ich C++ programmieren, würde ich jeden Tag feiern, dass es std::vector gibt 😉



  • iss doch klar, in der cpp verwendest du Firma** in der header nur Mitarbeiter* , Firma** == Mitarbeiter***

    args .... mir dreht sich alles

    versuchs doch bitte mit
    void bla(Mitarbeiter* &Firma, int, int);

    dann sollte meine variante auch endlich funktionieren XD

    und nenn es doch innerhalb der funtion nich wie in der main "Firma" sondern FirmaPtr oder so ...

    pointer auf pointer kannst du gern versuchen aber das endet nur in verwirrung

    belass es bei call by reference auf nen Mitarbeiter-pointer



  • in der cpp verwendest du Firma** in der header nur Mitarbeiter* , Firma** == Mitarbeiter***

    Hä das blick ich net? Ich hab doch gar keine header dabei, kannst mir das nochmal genau erklären? Dankeschön schon mal im Voraus.



  • ja sorry war schon spät hab den ganzen tag wieder quelltext auseinandergefriemelt und bissl stresst gehabt dein quelltext richtig zu lesen XD

    nien sorry so ad hoc fällt mir der fehler nciht auf ..... wuaaah schon so spät ? -.- und morgen wieder auf arbeit



  • ganz einfach, ein Array ist ein Stapel.
    Im Idealfall sieht das als Code näherungsweise so aus:

    template <typename T> class Array{
    protected:
    T* Element;
    unsigned amountOf;
    unsigned allocatedMemory; // soll regulieren, wann wieder einmal Speicher
     // allokiert werden muss
    public:
    Array(); // Sollte alles ausnullen, weil möglicherweise auch gar keine Elemente
     // in das Array geschrieben werden, also auch Element = NULL;
    
    ~Array(); // Sollte für einen sauberen Abgang sorgen
    
    T& operator[](unsigned index); /* Soll dem Anwender der Klasse den Zugriff auf 
      die Arrayelemente in gewohnter [] Syntax erlauben, und falls der Index zu groß
      ist, sorgt die Funktion natürlich dafür (mittels new), das Array notfalls
      soweit zu vergrößern, dass der Index passt */
    
    bool insert(const T& Eingefuegt); // Arbeitet ähnlich wie [], gibt dem Anwender
     // allerdings die Sicherheit, dass ein Element auch garantiert am Ende des
     // Arrays eingefügt wird
    
    bool drop(const T& Verworfen); /* Und diese Funktion sorgt letztlich dafür,
      dass das erstbeste Element, das identisch zu Verworfen ist, gelöscht wird.
      Alle 'Bausteine' des Stapels droppen dann natürlich um eins nach 'unten' */
    };
    
    /* Dieses Tolle Array kann dann überall so erzeugt werden (beispielsweise wenn man D3DMATERIAL9 Strukturen darin speichern möchte, oder auch nur einfache int)*/
    
    int WINAPI WinMain(HINSTANCE hinst, HINSTANCE phinst, LPSTR commandLine,
     int ShowStyle){
    // fuer int sieht's so aus:
    Array<int> Zahlenliste; // sofern sich operator[] und insert darum kümmern,
      // dass das Array dynamisch erweitert wird, hat man jetzt die Narrenfreiheit,
      // an einem beliebigen Array-Index einen beliebigen int Wert zu speichern
    
    // für D3DMATERIAL9 funktioniert das gleiche Array!
    Array<D3DMATERIAL9> Materials; // egal wie komplex der Datentyp auch sein mag,
     // dieses Tolle Array kann sie speichern!
     // Und die einzelnen Elemente werden dank des überladenen [] Operators in der
     // gewohnten Array-Syntax erreicht, also beispielsweise so:
    
    Zahlenliste[5]=3;
    
    return 0;
    };
    

    Damit das Array auch brav dynamisch wächst, wenn der Benutzer des Arrays einen zu großen Index angeben sollte, erzeugt man erst einen temporären T* Zeiger,
    weist dann diesem Zeiger mittels new den seit neuestem benötigten Speicherbereich mittels new zu, kopiert dann die alten Elemente aus T* Element in diesen temporären T* Zeiger, löscht dann den alten Elemente-Zeiger, setzt ihn dann gleich mit dem temporären T* Zeiger, und kopiert im Falle von insert() den Inhalt des einzufügenden neuen Elements ans Ende der Liste. Im Falle der Funktion operator[] gibt man dann einfach Element[index] zurück. Das allerdings zufälligen Inhalt haben kann, weil der Anwender des Arrays/Stapels den Indexbereich überschritten hat. Kommt auch auf die Konstruktoren von T an.
    Im Normalfall wird der Anwender aber den Index immer nur dann überschreiten, wenn er etwas in das Element-Array kopieren möchte, und noch nicht weiß, wieviele Elemente das Array einmal haben wird.

    Dieses Array ist insofern einfach zu handhaben, als dass die gewohnte Array-Syntax nicht verloren geht. Und viel öfter benötigt man Stapel als Listen. Leider kommt man auch nie darum herum, Stapel-Klassen selbst zu schreiben, weil <vector> seine Elemente irgendwo verstreut im Speicher ablegt, und man aber leider oft darauf angewiesen ist, dass Elemente auch wirklich garantiert hintereinander im Speicher abgelegt werden, und nicht irgendwo in der Wildnis.

    Viel Spass mit dieser Stapel/Array-Klasse!

    Hehe



  • Mh ja ich verstehst so halb, muss es mir noch paar mal genau durchlesen, was ich aber gar net verstehe, warum braucht man da nen WinAPI Kopf? Also mit WinAPI kenn ich mich ja gar net aus, also sollte der Kopf nötig sein dann is es keine alternative für mich.



  • Stromberg schrieb:

    Mh ja ich verstehst so halb, muss es mir noch paar mal genau durchlesen, was ich aber gar net verstehe, warum braucht man da nen WinAPI Kopf? Also mit WinAPI kenn ich mich ja gar net aus, also sollte der Kopf nötig sein dann is es keine alternative für mich.

    Nein, der ist nicht nötig - natürlich kannst du solche Arrays auch in einer "normalen" main()-Funktion anlegen.

    (@EinigesIntus: Warum selber schreiben? Nimm doch gleich std::vector<>)



  • JUHUH 😃 !!! So ich glaub es geht jetzt. Hab doch n paar Fehler gefunden und hab das so wie ichs mir gedacht hab ganz ohne Referenzen, sondern nur mit Zeigern gemacht. 😃 Hier wär dann mal der Code, vll. interessierts ja jemand, meiner Meinung nach funktionierts, würd mich aber über Verbeserungsvorschläge etc... freuen! 🙂

    #include <iostream>
    using namespace std;
    
    class Mitarbeiter
    {
        public:
        Mitarbeiter();
        ~Mitarbeiter();
        void SetGehalt(int a) {Gehalt=a;}
        void SetAlter(int a) {Alter=a;}
        void SetName(string a) {Name=a;}
        int GetGehalt(){return Gehalt;}
        int GetAlter() {return Alter;}
        string GetName() {return Name;}
    
        private:
        int Gehalt;
        int Alter;
        string Name;
    };
    void FromArrayToNewArray(Mitarbeiter **Firma,int OldArrayEnd,int NewArrayEnd);
    Mitarbeiter::Mitarbeiter()
    {
    
    }
    
    Mitarbeiter::~Mitarbeiter()
    {
    
    }
    
    int main()
    {
    
        int BenEing1;
        int BenEing2;
        cout << "Wieviele Mitarbeiter sollen Angestellt werden?\n";
        cin >> BenEing1;
        Mitarbeiter *Firma=new Mitarbeiter[BenEing1];
        for (int i=0;i<BenEing1;i++)
        {
            Firma[i].SetGehalt(i+(i*80)+200);
        }
        cout << "Wieviele neue Mitarbeiter?\n";
        cin >> BenEing2;
        FromArrayToNewArray(&Firma,BenEing1,BenEing2);
    
        //#TEST# (Testen obs geklappt hat)
        for (int i=0;i<BenEing1;i++)
        {
            cout << Firma[i].GetGehalt() << endl;
        }
    
        return 0;
    }
    
    void FromArrayToNewArray(Mitarbeiter **ArrayTemp,int OldArrayEnd,int NewArrayEnd) //hier war der Funktionsparameter
                                           //(der vorher "*Firma" hieß) falsch, da ich so nicht den Zeiger Firma aus Zeile
                                           //39 angesprochen habe, sondern nur immer die Adress des ersten Elements.
    {
        Mitarbeiter *temp=new Mitarbeiter[OldArrayEnd];
        for (int i=0;i<OldArrayEnd;i++)
        {
            temp[i]=(*ArrayTemp)[i];
        }
        delete []*ArrayTemp; //EDIT: äh ich glaub das muss doch [](*ArrayTemp) heißen? (siehe diesen Beitrag bei dem ich das gefragt               
    //habe: http://www.c-plusplus.net/forum/viewtopic-var-t-is-172525.html ) 
        *ArrayTemp=NULL;
        *ArrayTemp=new Mitarbeiter[OldArrayEnd+NewArrayEnd]; // hier warn Fehler da BinEing2 (Zeile 46) nur angibt um wieviel
                                                             // größer das Array werden soll.
        for (int i=0;i<OldArrayEnd;i++)
        {
            (*ArrayTemp)[i]=temp[i];
        }
        delete []temp;
    }
    

    @CStoll ja okay es ist sicherlich einfacher "std::vector" zu nehmen, war aber jetzt halt eher so nä kleine "Herausforderung" an mich, das zu schreiben. Und man freut sich danach richtig wenns endlich funktioniert (also äh müsst jetzt glaub schon gehen).
    Und ich hab auch wieder einiges gelernt dabei!

    Dankeschön schon mal im Voraus.


Anmelden zum Antworten