[c++] 2Dimensionen dynamischer Größe verwalten?

Wer ist Google

Grünschnabel
Hi zusammen,

ich habe ein kleines problemchen wo ich nicht genau weiß wie und ob ich es regelkonform lösen kann:

ich will in c++ ein koordinatensystem anlegen mit x und y achse wo entsprechend daten drinne sind.
dafür denke ich mal ist der vector<> eine recht gute wahl, nur weiß ich jetzt nicht wie ich die vectoren verwalten soll:

Code:
  | 0 | 1 | 2 | <x
--+---+---+---+
0 |   |   |   |
--+---+---+---+
1 |   |   |   |
--+---+---+---+
2 |   |   |   |
--+---+---+---+

/\
y

wenn ich jetzt einen
Code:
vector< vector<int> >  i(3, vector<int>(3,0));
anlege bin ich in x richtung (innerer vector) ja ziemlich eingeent, da ich (denke ich mal) wenn ich einen weitere spalte via
Code:
i[0].bush_back(x);
in den wert der jewals nächsten y zeile schreibe (wenn das proggi dann nicht wegen sig fault verreckt)

gibt es da eine möglichkeit das dynamisch zu lösen oder muss ich es dafür in einem eindimensionalen vector speichern den ich dann mittels x und y wert 2 dimensional rechne?
so siehts momentan bei mir nämlich noch aus:
Code:
vector<Tile>            tile;
vector<Tile>::iterator  ptr_tile;

void Layer::showLayer()
{
    cout << width << " x " << high << endl;
    for( ptr_tile=tile.begin() ; ptr_tile<tile.end() ; ptr_tile++)
    {    
        if( ptr_tile->valure % width == 0 )
            cout << endl;
        cout << ptr_tile->id;
    }
    cout << endl;
}

wär echt super wenn es dafür ne gute lösung gäbe,
denn die objekte, der klasse in der dashier liegt, wird auch von einem vector verwaltet (sprich 3. Dimension)

Gruß,
Daniel
 
Hi.
wenn ich jetzt einen
Code:
vector< vector<int> >  i(3, vector<int>(3,0));
anlege bin ich in x richtung (innerer vector) ja ziemlich eingeent, da ich (denke ich mal) wenn ich einen weitere spalte via
Code:
i[0].bush_back(x);
in den wert der jewals nächsten y zeile schreibe (wenn das proggi dann nicht wegen sig fault verreckt)
Ich verstehe dein Problem nicht. Was meinst du damit? Warum bist du eingeent?

Vektoren sind dynamisch, auch mehrdimensional. Die kannst du in der Größe ändern wie du lustig bist.

Gruß
 
sehr schön! dann isses ja nur ein verständniss fehler meinerseits :)

ich hab jetzt mal versucht es dementsprechend umzubauen und habe nun doch ein paar kleine handfestere probleme...

ich habe momentan folgende 4 daten:

main.cpp
C++:
#include <iostream>
#include "map.h"

using namespace std;

int main(void)
{
    Map map(7,5,4);
    map.showMap();
}

map.h
C++:
#ifndef MAP_H
#define MAP_H

#include <string>
#include <vector>

#include "layer.h"

using namespace std;

class Map {
    public:
        /*constructur Map:
            Map::Map(unsigned int width, unsigned int high);
            Map::Map(unsigned int width, unsigned int high, unsigned char layer);
        */
        Map(unsigned int, unsigned int, unsigned char);
        void showMap();
        
    private:
        string mapName;
        /*
            width   = anzahl spalten
            high    = anzahl spalten
        */
        unsigned short int          width, high;    //anzahl spalte, anzahl zeile
        unsigned char               layerCount;     //anzahl layer
        unsigned char               layerActiv;     //aktiver layer
        vector<Layer>               layer;          //die Layer selber
        vector<Layer>::iterator     ptr_layer;      //Pointer auf einen der layer
        
};


Map::Map(unsigned int width, unsigned int high, unsigned char layers)
{
    this->width = width;
    this->high  = high;
    layerCount  = layers;
    layerActiv  = 0;
    
    for(unsigned char i=0; i<layers; i++)
        layer.push_back(Layer(width, high, i));
}

void Map::showMap()
{
    for( ptr_layer=layer.begin(); ptr_layer<layer.end(); ptr_layer++)
    {
        cout << endl << "## Layer " << ptr_layer->z << " ##" << endl;
        ptr_layer->showLayer();
    }
}

#endif // MAP_H

layer.h
C++:
#ifndef LAYER_H
#define LAYER_H

#include <iostream>
#include <vector>
#include <stdio.h>  // ******ACHTUNG****** ist zu löschen! wird benötigt um z anzuzeigen "Layer::showLayer()"

#include "tile.h"

using namespace std;

class Layer
{
    public:
        Layer(unsigned short int, unsigned short int, unsigned char);
        
        void updateTile(unsigned long int, int);   //aktuallisiert den entsprechenden Tile
        void showLayer();                          //  ##  gibt den vektor aus  ##
        unsigned char z;
        
    private:
        
        unsigned short int width;
        unsigned short int high;
        
        string        layerName;
        
        //zeile Y-Wert:
        vector< vector<Tile> >              tile;
        vector< vector<Tile> >::iterator    pos_x;
        //Spalte X-Wert:
        vector<Tile>::iterator              pos_y;
//        vector<Tile>            tile;
//        vector<Tile>::iterator  ptr_tile;
        
};

Layer::Layer(unsigned short int width, unsigned short int high, unsigned char z)
{
    vector<Tile>    temp;
    
    this->width = width;
    this->high  = high;
    this->z     = z;  
          
    for(unsigned long int i=0; i < high; i++){
        for(unsigned long int j=0; j < width; j++){
            tile[i].push_back(Tile(j));
        }
    }
}

void Layer::showLayer()
{
    cout << width << " x " << high << " x ";
    for(pos_x=tile.begin(); pos_x<tile.end(); pos_x++){
        for(pos_y=(*pos_x).begin(); pos_y < (*pos_x).end(); pos_y++){
            cout << ((*pos_y)->pictureId) << " ";
        }
    }
}

#endif // LAYER_H

tile.h
C++:
#ifndef TILE_H
#define TILE_H

class Tile
{
    public:
        unsigned long int valure;
        unsigned int pictureId;
        //SDL Image
        
        Tile(unsigned long int);
        Tile(unsigned long int, unsigned int);
        
    private:
};

Tile::Tile(unsigned long int valure)
{
    this->valure    = valure;
    this->pictureId = 0;
}

Tile::Tile(unsigned long int valure, unsigned int pictureId)
{
    this->valure    = valure;
    this->pictureId = pictureId;
}

#endif // TILE_H

mein problem liegt jetzt in der layer.h in zeile 53 bis 61. ich weiß nicht genau wie ich auf die einzelnen werte zugreife, ich habs schon auf verschiedene varianten versucht aber der compiler spukt mir immer ein paar fehlermeldungen aus... im aktuellen falle:
Code:
layer.h:81:30: error: base operand '->' has non-pointer type tile

wenn ichs über
Code:
tile[i][j]->pictureId;"
versuchekomt die selbe fehlermeldung, versuche ichs über:
Code:
tile[i][j].pictureId;
schluckt der compiler es zwar aber beim start des programmes erhalte ich einen speicherzugriffsfehler

quelle meiner suche und ideen:
http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

wär super wenn vielleicht mal eben einer n äuglein drüber werfen könnte.
tausend dank schonmal.
 
Ich weiß nicht, ob dein Vergleichsoperator das Problem darstellt, aber versuche doch einmal das in den for-Schleifen.
C++:
[...]; pos_x  != tile.end(); [...]
[...]; pos_y  !=(*pos_x).end(); [...]
 
Hi.

Du hast vergessen die Größe der ersten Dimension des tile Vektors zu erweitern.

C++:
Layer::Layer(unsigned short int width, unsigned short int height, unsigned char z)
: width(width), height(height), z(z)
{
   tile.resize(height);
   for(unsigned long int i=0; i < height; i++){
        tile[i].resize(width);
        for(unsigned long int j=0; j < width; j++){
            tile[i][j] = Tile(j);
        }
    }
}
Initialisierungen in die Initialiserungsliste, height statt high und value statt valure...

Übrigens ist es (IMHO) sehr unschön aus Bequemlichkeit Iteratoren als Instanzattribute zu definieren. Und Pointer sind es auch nicht wie der Präfix "ptr_" weismachen will...

Gruß
 
Zuletzt bearbeitet:
Deine Fehlermeldung kommt daher, da der Operator -> den linken Operand automatisch dereferenziert und dann auf den rechten zugreift. (*pos_y)->pictureId ist also fehlerhaft, da pos_y schon vom -> dereferenziert wird, also weg mit dem Stern.

Lg
 
Also... danke schonmal für die tipps...
hab mal ein wenig ausprobiert und stehe jetzt seltsamer weise vor neuen problemchen ^^°

hab zum test mal die show funktionen auskommentiert und den konstruktor von layer wie folgt verändert:
C++:
Layer::Layer(unsigned short int width, unsigned short int high, unsigned char z)
    : width(width), high(high), z(z)
{
//    this->width = width;
//    this->high  = high;
//    this->z     = z;

    tile.resize(width);
    for(unsigned short int i=0; i < width; i++){
        tile[i].resize(high);
        for(unsigned short int j=0; j < high; j++){
            tile[i][j]=Tile(j);
        }
    }
    
    //layerName << "new Layer" << z;

}

ausgabe compiler:
Code:
In Elementfunktion »void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type) [mit _Tp = Tile, _Alloc = std::allocator<Tile>, std::vector<_Tp, _Alloc>::size_type = long unsigned int, std::vector<_Tp, _Alloc>::value_type = Tile]«:
layer.h:58:28: Fehler: keine passende Funktion für Aufruf von »Tile::Tile()«
layer.h:58:28: Anmerkung: Kandidaten sind:

problem ist denke ich mal das resize einen wertegröße braucht...
damit habe ich dann folgendes erweitert... daran meckert weder der compiler rum (0 errors, 0 warnings) und das programm gibt auch keine ausgabe (was durch die auskommentierten shows ja auch sinn macht.)

C++:
    tile.resize(width,vector<Tile>(width,high));
    for(unsigned short int i=0; i < width; i++){
        for(unsigned short int j=0; j < high; j++){
            tile[i][j]=Tile(j);
        }
    }
wenn ich die erste zeile jetzt mal gegen:
C++:
tile.resize(sizeof(Tile),vector<Tile>(width,high));
ist gleiches... ergibt in meinen augen mehr sinn, hab aber keine ahnung was jetzt richtiger ist.

ich werde später nochmal versuchen die ausgaben einzubinden,
dachte mir aber mal meine gedanken schonmal zu teilen ;)

mfg.
Daniel
 
Hi.

Bitte achte auf die Netiquette, insbesondere Groß-/Kleinschreibung. Danke!
ausgabe compiler:
Code:
In Elementfunktion »void std::vector<_Tp, _Alloc>::resize(std::vector<_Tp, _Alloc>::size_type, std::vector<_Tp, _Alloc>::value_type) [mit _Tp = Tile, _Alloc = std::allocator<Tile>, std::vector<_Tp, _Alloc>::size_type = long unsigned int, std::vector<_Tp, _Alloc>::value_type = Tile]«:
layer.h:58:28: Fehler: keine passende Funktion für Aufruf von »Tile::Tile()«
layer.h:58:28: Anmerkung: Kandidaten sind:

problem ist denke ich mal das resize einen wertegröße braucht...
Das Problem ist, dass Tile keinen Standardkonstruktor besitzt.

Es reicht aus, innerhalb der ersten Schleife nicht resize zu verwenden, sondern push_back in der zweiten Schleife.
wenn ich die erste zeile jetzt mal gegen:
C++:
tile.resize(sizeof(Tile),vector<Tile>(width,high));
ist gleiches... ergibt in meinen augen mehr sinn, hab aber keine ahnung was jetzt richtiger ist.
Also das ist nun wieder ganz falsch. sizeof liefert doch einen konstanten Wert...

Gruß
 
Soo (ich versuchas mal mit richtiger Groß-/Kleinschreibung X_x)

Als ich den letzten Artikel verfasst und gerade das Herunterfahren meines Rechners bestätigt hatte bin ich aufgestanden und habe mir mit der flachen Hand gegen die Stirn geschlagen.

Der Problemteil sieht jetzt so aus und funkrioniert wie gewünscht *freu*:
Code:
    tile.resize(high,vector<Tile>(width,0));
    for(unsigned short int i=0; i < high; i++){
        for(unsigned short int j=0; j < width; j++){
            tile[i][j]=Tile(j);
        }
    }

Um meinen kleinen Erfolg hier mal zu teilen habe ich hier mal das gesamte Programm für die Leute die mal ein wenig testen wollen:

Main.cpp
C++:
#include <iostream>
#include "map.h"

using namespace std;

int main(void)
{
    Map map(20,15,2);
    map.showMap();
    map.layerActiv = 2;
    map.updateTile(0,0,15);
    cout << "---------------------------------------------------------------" << endl;
    map.showMap();
    
    return 0;
}

map.h
C++:
#ifndef MAP_H
#define MAP_H

#include <string>
#include <vector>

#include "layer.h"

using namespace std;

class Map {
    public:
        Map(unsigned short int, unsigned short int, unsigned char);
        void showMap();
        void updateTile(unsigned short int, unsigned short int, int);
        
        unsigned char               layerActiv;     //aktiver layer
        
    private:
        string mapName;

        unsigned short int          width, high;    //anzahl spalte, anzahl zeile
        unsigned char               layerCount;     //anzahl layer
        vector<Layer>               layer;          //die Layer selber
        vector<Layer>::iterator     ptr_layer;      //Pointer auf einen der layer
        
};


Map::Map(unsigned short int width, unsigned short int high, unsigned char layers)
{
    this->width = width;
    this->high  = high;
    layerCount  = layers;
    layerActiv  = 0;
    
    for(unsigned char i=0; i<layers; i++)
        layer.push_back(Layer(width, high, i));
}



void Map::showMap()
{
    for( ptr_layer=layer.begin(); ptr_layer<layer.end(); ptr_layer++)
    {
        cout << endl << "## Layer " << ptr_layer->z << " ##" << endl;
        ptr_layer->showLayer();
    }
}

void Map::updateTile(unsigned short int x, unsigned short int y, int picId){
    layer[layerActiv].updateTile(x,y,picId);
}

#endif // MAP_H

layer.h
C++:
#ifndef LAYER_H
#define LAYER_H

#include <iostream>
#include <vector>

#include "tile.h"

using namespace std;

class Layer
{
    public:
        Layer(unsigned short int, unsigned short int, unsigned char);
        
        void updateTile(unsigned short int, unsigned short int, int);   //aktuallisiert den entsprechenden Tile
        void showLayer();                          //  ##  gibt den vektor aus KONSOLE!  ##
        unsigned char z;
        
    private:
        
        unsigned short int width, high;
        
        string        layerName;
        
        vector< vector<Tile> >  tile;
        
};

Layer::Layer(unsigned short int width, unsigned short int high, unsigned char z)
{    
    this->width = width;
    this->high  = high;
    this->z     = z;
    cout << width << " " << high;
    
    tile.resize(high,vector<Tile>(width,0));
    for(unsigned short int i=0; i < high; i++){
        for(unsigned short int j=0; j < width; j++){
            tile[i][j]=Tile(j);
        }
    }
    layerName = "new Layer ";

}


void Layer::updateTile(unsigned short int x, unsigned short int y, int picId)
{
    tile[x][y].pictureId = picId;
}


void Layer::showLayer()
{
    cout << layerName << " | " << width << " x " << high << " x ";
    for(unsigned short int i=0; i<high; i++){
        cout << endl;
        for(unsigned short int j=0; j<width; j++){
            cout << tile[i][j].pictureId << '\t';
        }
    }
    cout << endl;
}


#endif // LAYER_H

tile.h
C++:
#ifndef TILE_H
#define TILE_H

class Tile
{
    public:
        unsigned short int valure;
        unsigned int pictureId;
        //SDL Image
        
        Tile(unsigned short int);
        Tile(unsigned short int, unsigned int);
        
    private:
};

Tile::Tile(unsigned short int valure)
{
    this->valure    = valure;
    this->pictureId = 0;
}

Tile::Tile(unsigned short int valure, unsigned int pictureId)
{
    this->valure    = valure;
    this->pictureId = pictureId;
}

#endif // TILE_H

Danke an alle für alles,
habt mir echt geholfen :D

gruß
Daniel
 
Zurück