Mehrdimensionale Arrayklasse, wie Array erstellen?



  • Hallo zusammen,

    ich habe eine Arrayklasse geschrieben, die mehrdimensionale Arrays erzeugen können soll. Mit arrayklasse<int> testarray(2, 4, NULL); kann man z.B. einen Array erstellen, dessen erste Ebene 2 Felder hat, und dessen zweite Ebene 4 Felder hat.

    Das ganze funktioniert auch schon, die Anzahl der Felder der jeweiligen Ebene speichere ich im Array m_size. Das funktioniert bis zu dem Punkt, wo der eigentliche Array erstellt werden soll:

    m_data = new T[m_size[0]]; // Erstellen des Arrays

    Da bräuchte ich eine Anweisung wie:

    m_data = new T....
    
    for (int i = 0; i < anzahl der ebenen; i++)
    	{
    	...[m_size[i]]...
    	}
    

    denn ich kann ja nicht einmal schreiben
    m_data = new T[m_size[0]];
    für einen eindimensionalen Array und dann das nächste Mal für einen zweidimensionalen Array
    m_data = new T[m_size[0]][m_size[1]];

    Irgendwie brauche ich eine Methode, die die Klammern hinter "new T" je nach Anzahl der Arrayebenen automatisch erstellt.

    Hier noch der Quellcode:

    main.cpp:

    /*
    #include <iostream>
    #include <windows.h>
    #include <vector>
    using namespace std;
    #include "arrayklasse.cpp"
    
    void main()
    	{
    	arrayklasse<int> testarray(2, 3, 4, 5, NULL);
    	};
    

    arrayklasse.cpp:

    template<class T>					// Klassentemplate, damit die Klasse mit verschiedenen Datentypen benutzt werden kann
    class arrayklasse
    	{
    	private:
    		T	*m_data;				// m_data ist der Array
    		int *m_size;				// Array mit der jeweiligen Feldanzahl pro Ebene
    
    	public:
    		arrayklasse(int parameterbezeichner, ...)		// Konstruktor, der Array wird mit einer bestimmten Größe erstellt (kann über Funktionen noch geändert werden)
    			{
    			va_list parameter;							// Anlegen eines Pointer auf die Liste der Argumente 
    			va_start(parameter, parameterbezeichner);	// gehe an erste Position der übergebenen Variablenliste
    
    			//m_data[0] = parameterbezeichner;			// der erste Parameter wird in die Stelle 0 des Arrays geschrieben
    
    			int k = 0; // k enthält dann die Anzahl der Ebenen
    
    			while (1) // nur zum Zählen der übergebenen Argumente
    				{
    				if (k == 0)
    					{
    					if (parameterbezeichner == NULL)	{break;};
    					}
    				else
    					{
    					if (va_arg(parameter, int) == NULL)	{break;};
    					};
    
    				k++;
    				};
    
    			m_size = new int[k];
    
    			va_start(parameter, parameterbezeichner);	// gehe an erste Position der übergebenen Variablenliste
    
    			for (int i = 0; i < k; i++) // Anzahl der Felder für die jeweilige Ebene schreiben
    				{
    				if (i == 0)	{m_size[i] = parameterbezeichner;}
    				else		{m_size[i] = va_arg(parameter, int);};
    				};
    
    			va_end(parameter);							// Löschen der Parameterliste
    
    			m_data = new T[m_size[0]];	// Erstellen des Arrays, das funktioniert noch nicht <<<<<!!!!!!!!!!!!!!!!!!!!!!!!
    			};
    
    		~arrayklasse()				// Destruktor
    			{
    			delete[] m_data;		// Löschen des Arrays
    			delete[] m_size;
    			};
    
    		T& operator[](int index)	// Überladener Operator, ermöglicht Wertausgabe (z.B. cout<<arrayname[3]<<endl;)
    			{
    			return m_data[index];
    			};
    
    		int getsize() // Funktion zum Abfragen der aktuellen Arraygröße
    			{
    			//return m_size;
    			};
    	};
    

    Die Arrayklasse hat noch etliche Funktionen mehr (und ich noch mehr Fragen 😃 ), aber eins nach dem anderen.

    Viele Grüße,
    Manfred



  • Du mußt intern ein mehrdimensionales Array als ein eindimensionales Array darstellen und dann entsprechend die Indizes berechnen.
    Bei 2 Dimensionen z.B.

    int Z = X*Y;
    array = new T[Z];
    

    Für mehrere Dimensionen berechnest du "Z" einfach in einer Schleife.
    Um auf die einzelnen Element dann zuzugreifen, mußt du dann die Indizes bestimmen, z.b.

    T t = array[y*X+x];
    

    Für mehrere Diemnsionen dann analog multiplizieren und addieren...



  • Hmm,

    das hab ich schon fast befürchtet 😕

    Schön wärs wie oben halt gewesen, weils dann einfach zum ansteuern und der Code leicht zu lesen gewesen wäre. Ausserdem benötige ich verschiedene Typen, d.h. es wird wohl auf einen langsamen Array mit Pointern auf andere Arrays hinauslaufen, in dem oberen Konstrukt wär das auch möglich gewesen, ohne zusätzliche Arrays zu erstellen (bei mehreren 'T's). Nur das array[][][][][][] Problem ist halt nicht dynamisch zu lösen.

    Ich könnt aber noch sagen, daß ich halt bis zu 5-dimensionale Arrays erlaube und dann den Array in entsprechenden if-Abfragen für die Ebenenanzahl erstelle 🙂 nur ist das halt nicht dynamisch...

    Viele Grüße,
    Manfred



  • Manfred2 schrieb:

    ... Nur das array[][][][][][] Problem ist halt nicht dynamisch zu lösen.
    Manfred

    Hi!
    Das Problem ist zu lösen. Du musst mittels Hilfsklassen den operator[]
    so oft überschreiben wie du Dimensionen haben willst.

    Kleines Beispiel für dynamische zweidimensionale Arrays:

    template <class T>
    class Proxy
    {
    protected:       
            Proxy(size_t x, size_t y) 
                    : dim2(y), dim1(x), dim(0),  Myptr(NULL){}
            virtual ~Proxy(){}
            T* Myptr;
            size_t dim;
    public:        
            T& operator[](const size_t y) 
    	    {
                    return Myptr[dim*dim2+y];
            }
            size_t dim2;
            size_t dim1;
    };
    
    template<class T>
    class Array :  public Proxy<T>
    {
    public:
    
            Array(size_t x, size_t y) :  Proxy<T>(x, y)  
            {
                Myptr = new T [x*y];
            }
            ~Array() { delete[] Myptr; }
    
            Proxy<T>& operator[](const size_t x) 
            {
                    dim = x;
                    return *this;
            }  
    private:
            Array(const Array& a){}
            Array& Array::operator=(const Array& a){}    
    };
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main()
    {
        size_t x = 4, y = 5;
    
        Array<string> a(x, y); //dynamisches zweidimensionales Array
    
        a[2][1] = "Ein zweidimensionales ";
        a[3][4] = "dynamisches Array!";
        a[0][1] = a[2][1];
        cout << a[0][1]  << a[3][4] << endl;
        return 0;
    }
    

    mfg



  • Man könnte sich auch das Ganze sparen und boost::multi_array nutzen.



  • Hallo,

    erstmal vielen Dank für die Antworten, ich bin leider noch nicht dazugekommen, werde mir aber jetzt die Beispiele mal ansehen, schau ma mal was es wird 🙂

    Viele Grüße,
    Manfred


Anmelden zum Antworten