[C++] Dynamische 2dimensional Array

Pagina: 1
Acties:

  • Sebazztiaan
  • Registratie: Februari 2002
  • Laatst online: 21-04 16:53
Ik wil in een wereld een veld[][] hebben. Zeg maar als een schaakbord, de grote van de wereld moet per level kunnen verschillen. Nu weet ik dat ik in Java het volgende gewoon kan:

private Veld Velden[][];
velden = new Veld[x][y];

Een normaal enkeldimensietionele array kan in C op de volgende manier:
.h
CVeld* m_Velden;

.cpp
m_Velden = new CVeld[x];

Alleen nu wil ik dat dus in een 2d array krijgen, de search op GoT gaf geen andwoord, want die gaf alleen maar aan dat ik een vector zou moeten gebruiken, en dat wil ik dus niet.

Ook het idee dat als ik een veld heb van 8*10 en dat als een grote [] van 80 velden maak vind ik niet mooi.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dan is je enige keus een loop...

C++:
1
2
3
4
5
int** ar = new int*[n];

for (int i=0; i<n; ++i) {
   ar[n] = new int[m];
}


Met dan nog een manier om alles weer te wissen, etc...niet echt handig.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 26-05 23:14
Je streept ook wel alle opties op voorhand weg, hé! Overigens is de code die Zoijar presenteert hetzelfde als in Java achter de schermen gebeurt (die multidimensionele arrays in Java zijn dus minder mooi dan ze lijken, hoewel je als programmeur niet altijd iets met dit soort implementatie-issues hoef te doen).

De reden dat aangeraden werd om een vector van vectors te gebruiken, is dat je dan niet alle allocaties en deallocaties handmatig hoeft te verrichten. Op zich kan ik me echter voorstellen dat je deze oplossing te 'dynamisch' vind. Eventueel zou je dan nog kunnen overwegen om iets met multidimensionale arrays van Boost te doen maar dat betekent wel dat je (waarschijnlijk alleen om deze reden) Boost moet gaan gebruiken. Je kunt je afvragen of dat het waard is.

Tenslotte rest je nog de mogelijkheid om een platte array (in jouw 2x8 voorbeeld dus met 80 elementen) te wrappen in een eigengemaakt type. Vooral voor 2D arrays is dat vrij makkelijk te doen. Je hebt dan nog steeds geen ideale code achter de schermen, maar je hoeft de index-berekeningen dan niet steeds in je code te herhalen.

  • Sebazztiaan
  • Registratie: Februari 2002
  • Laatst online: 21-04 16:53
Ik zou wel een Wrapper kunnen schrijven voor dit probleem maar dat vind ik niet de mooiste oplossing met bijv de volgende functies

.setDim(int, int);
.getPos(int, int);

maar het is echt NIET mooi. En dan heb ik toch nog geen vrije container, maar alleen van de types die ik zelf aan het begin aan maak, dus het is niet echt een optie.

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 26-05 23:14
Je kunt natuurlijk iets prutsen met operator overloading, dan krijg je net een 2D-array; zoiets bijvoorbeeld (nog niet volledig):
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template <class T> class Array2D
{
private:
    T *_data;
    int _m, _n;

public:
    Array2D(int m, int n) {
        _m = m; _n = n;
        _data = new T[m*n];
    }
    
    ~Array2D() {
        delete[] _data;
    }
    
    inline T* operator[](int i) {
        return &_data[i*_n];
    }
    
    inline int m() {
        return _m;
    }

    inline int n() {
        return _n;
    }
};

Door die leuke operator[] implementatie kun je dan gewoon zulke code schrijven:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;

int main()
{
    Array2D<int> foo(3,4);
    for(int i = 0; i < foo.m(); ++i)
        for(int j = 0; j < foo.n(); ++j)
            foo[i][j] = 10*i + j;
            
    cout << foo[2][1] << endl;  // 21
}
Het instantiëren werkt wat anders dan je gewend was maar je kunt elementen wel gewoon met de gebruikelijke notatie benaderen. Door de template parameter T kun je de klasse herbruiken voor 2D arrays met allerlei verschillende typen elementen.

  • Sebazztiaan
  • Registratie: Februari 2002
  • Laatst online: 21-04 16:53
*bookmarkt*

En ja, omwille de tijd heb ik toch maar een wrapper geschreven, waardoor ik dus wel dit soort dingen kan doen, wat ik wou:

C++:
1
2
3
4
5
6
m_pSpeelbord->GetVeld(0,0).SetVeldType(MENS);
m_pMens = new CMens(0,0);

//bol begint op het laatste veld
m_pSpeelbord->GetVeld(m_WereldSize.x, m_WereldSize.y).SetVeldType(BOL);
m_pBol = new CBol(m_WereldSize.x, m_WereldSize.y);


waarbij m_pSpeelbord de wrapper is voor de 2d-array

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Soultaker schreef op 28 maart 2004 @ 18:58:
Eventueel zou je dan nog kunnen overwegen om iets met multidimensionale arrays van Boost te doen maar dat betekent wel dat je (waarschijnlijk alleen om deze reden) Boost moet gaan gebruiken. Je kunt je afvragen of dat het waard is.
In de praktijk kun je stukken Boost gewoon los gebruiken. De meeste code is template code in headers. Dan is het dus de vraag of je een boost header kopieert, of dat je dezelfde code zelf schrijft en debugt en documenteert en onderhoudt.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein

Pagina: 1