Zweidimensinales Array mit Vector Template

Schnelle objektorientierte, kompilierende Programmiersprache.
Mampf111
Beiträge: 24
Registriert: Mi Feb 05, 2014 9:59 am
Wohnort: Bielefeld

Zweidimensinales Array mit Vector Template

Beitrag von Mampf111 » Do Feb 27, 2014 11:43 am

Hallo zusammen,

Ich habe ein paar Fragen im Zusammenhang mit multidimensinalen Arrays und dem Vector-Template.

Zuerst:
Wie deklariere ich das "zweidimensinale-char-vector-array" in der Klassendefinition?

So?

Code: Alles auswählen

class Field
{
private:
    int max_Xsize, max_Ysize;
    char field[max_Xsize][max_Ysize];

//...
};
So initialisiere ich es im Konstruktor:

Code: Alles auswählen

Field::Field()
{
//...
    vector< vector<char> > field(max_Xsize);
    for( int i =0; i <= max_Xsize; i++){
        field[i].resize(max_Ysize);
    }
//...
}
Zuletzt:
Wie gebe ich den Speicher mit dem Destruktor wieder frei?

Code: Alles auswählen

Field::~Field()
{
    delete field;
}

Ich würde mich freuen, wenn ihr mir eine kleine Hilfestellung geben könnten.
Steige durch dieses Thema leider nicht wirklich durch...

Schönen Gruß!

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Zweidimensinales Array mit Vector Template

Beitrag von cloidnerux » Do Feb 27, 2014 12:03 pm

Wie deklariere ich das "zweidimensinale-char-vector-array" in der Klassendefinition?
Was ist ein "char-vector-array"?
Ich habe ein paar Fragen im Zusammenhang mit multidimensinalen Arrays und dem Vector-Template.
Punkt 1: Ein Array ist eine Stück Speicher der so groß ist, dass so viele Elemente des Datentyps reinpassen wie dein Array groß ist:

Code: Alles auswählen

char array1[10];   //10 Byte speicher
int array2[10];    //40 Byte speicher, meistens
Ein vektor ist eine Datenstruktur zur dynamischen Verwaltung von Daten, es entspricht einer Liste.
Du kannst dynamisch Daten hinzu fügen und entfernen, das geht mit einem Array nicht.

Code: Alles auswählen

int max_Xsize, max_Ysize;
    char field[max_Xsize][max_Ysize];
Das wird so nicht Funktionieren, zumindest ist mir nicht bekannt das C++ inzwischen dynamische Arrays erlaubt. Das erzeugen eines Arrays auf diese Art erfordert eine feste Größe des Arrays zur Compilierzeit. Willst du dynamisch Arrays erzeugen, musst du Speicher anfordern:

Code: Alles auswählen

char * dynamicArray = new char[sizeX * sizeY];
char  *dynamicArray2 = (char*)malloc(count * sizeof(char));
und diesen wieder Freigeben, wenn er nicht mehr benötigt wird.

Eine lokal in einer Funktion angelegte Variable ist auch nur in diesem Scope gültig, deine Variable "field" in deinem Konstruktor:

Code: Alles auswählen

Field::Field()
{
//...
    vector< vector<char> > field(max_Xsize);
    for( int i =0; i <= max_Xsize; i++){
        field[i].resize(max_Ysize);
    }
//...
}
Hat damit keinen Einfluss auf das Klassenmemeber "field", was übrigens einen anderen Datentyp hat.

Wenn deine Klasse einfach nur ein zweidimensionales Array handeln soll, dass sich nach dem Anlegen nicht mehr ändert würde ich die Verwendung eines dynamischen Arrays raten:

Code: Alles auswählen

char * data = new char[sizeX * sizeY];
Damit hast du ein stück Speicher auf den man schnell und einfach zugreifen kann und den man auch am Stück wieder freigibt.

Willst du eine Liste an arrays bauen würde ich folgendes nutzen:

Code: Alles auswählen

struct element
{
    int length;
    char * data;
};
[...]
vector<struct element> data;
So kannst du für jedes char Array ein stück Speicher reservieren über den man schnell Iterieren kann, hat aber trotzdem die Möglichkeit für jede Zeile eine andere länge zu verwenden.

Ich würde die Verwaltung von chars in einem vector nicht empfehlen. Char ist auf den meisten Systemen 1 byte groß, zur Verwaltung der Daten muss ein vector mindestens 4 byte Daten anlegen(Pointer auf das Element), was bedeutet, dass du für jedes Zeichen mindestens einen 4-fachen Overhead erzeugst.
Redundanz macht wiederholen unnötig.
quod erat expectandum

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Zweidimensinales Array mit Vector Template

Beitrag von mfro » Do Feb 27, 2014 1:01 pm

Vector-Array? Meinst Du einen Vector aus Vectors - also so was:

Code: Alles auswählen

#include <iostream>
#include <vector>

int main()
{
    std::vector<std::vector<int> > vec(10, std::vector<int>(10));

    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            vec[i][j] = i * j;

    for (int i = 0; i < 10; i++)
        for (int j = 0; j < 10; j++)
            std::cout << "vec[" << i << "][" << j << "] = " << vec[i][j] << std::endl;
    
    return 0;
}

??
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Mampf111
Beiträge: 24
Registriert: Mi Feb 05, 2014 9:59 am
Wohnort: Bielefeld

Re: Zweidimensinales Array mit Vector Template

Beitrag von Mampf111 » Do Feb 27, 2014 1:50 pm

mfro hat geschrieben:Vector-Array? Meinst Du einen Vector aus Vectors
Das könnte man so sagen. Ich habe vor eine Matrix zu erstellen bei der man auf jedes Feld zugreifen kann.
In diesem Zusammenhang habe ich gehört, dass das Vektor-Template dafür gut geeignet sein soll.
Allerdings nicht, wie es zu benutzen ist.
Da ich ich das selbe mit einem zweidimensionalen Array darstellen könnte, nehme ich an, dass ich ein Vector aus Vectoren meine.
cloidnerux hat geschrieben:Was ist ein "char-vector-array"?
Entschuldige, ich habe mich nicht gut ausgedrückt. Wusste aber auch nicht wie ich es bezeichnen sollte.
Erst ein mal vielen Dank für deine Umfangreiche Antwort!
cloidnerux hat geschrieben:Ein vektor ist eine Datenstruktur zur dynamischen Verwaltung von Daten, es entspricht einer Liste.
Kann ich so weit verstehen. Aber ist es dann überhaupt eine dynamische Datenstruktur wenn ich eine Matrix mit fester größe haben möchte und lediglich die Werte ändern möchte?
cloidnerux hat geschrieben:Wenn deine Klasse einfach nur ein zweidimensionales Array handeln soll, dass sich nach dem Anlegen nicht mehr ändert würde ich die Verwendung eines dynamischen Arrays raten:

Code: Alles auswählen

char * data = new char[sizeX * sizeY];
Damit hast du ein stück Speicher auf den man schnell und einfach zugreifen kann und den man auch am Stück wieder freigibt.
Dann denke ich, ist es das, was ich suche! Aber wie stelle ich dann damit eine Matrix dar?

mfro
Beiträge: 346
Registriert: Mi Jan 16, 2013 4:58 pm

Re: Zweidimensinales Array mit Vector Template

Beitrag von mfro » Do Feb 27, 2014 1:57 pm

Mampf111 hat geschrieben:...dass das Vektor-Template dafür gut geeignet sein soll.
Allerdings nicht, wie es zu benutzen ist.
Das hab' ich dir oben hingeschrieben. Mehr braucht's nicht.
It's as simple as that. And remember, Beethoven wrote his first symphony in C.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Zweidimensinales Array mit Vector Template

Beitrag von cloidnerux » Do Feb 27, 2014 2:36 pm

Aber ist es dann überhaupt eine dynamische Datenstruktur wenn ich eine Matrix mit fester größe haben möchte und lediglich die Werte ändern möchte?
Ja, ein vektor beleibt ein vektor, auch wenn du mit konstanten Größen arbeitest.
Dann denke ich, ist es das, was ich suche! Aber wie stelle ich dann damit eine Matrix dar?
Eine Matrix ist ein zweidimensionales Array. Du kannst entweder:

Code: Alles auswählen

char * array = new char[sizeX*sizeY];
array[0][0] = 1;
darauf zugreifen, oder den Indexoperator in der Klasse überladen und dann damit auf die Elemente zugreifen.

Im Endeffekt ist der Zugriff auf ein (mehrdimensionales)Array sehr einfach: Der Speicher ist linear und du musst nur deine Dimensionen umrechnen, aus

Code: Alles auswählen

array[4][3];
wird

Code: Alles auswählen

array[4 * maxY + 3]
Redundanz macht wiederholen unnötig.
quod erat expectandum

Mampf111
Beiträge: 24
Registriert: Mi Feb 05, 2014 9:59 am
Wohnort: Bielefeld

Re: Zweidimensinales Array mit Vector Template

Beitrag von Mampf111 » Do Feb 27, 2014 2:38 pm

Vielen Dank, das hat mir schon sehr geholfen!



EDIT:

Habe jetzt noch eine andere Frage...

Benutzt habe ich nun

Code: Alles auswählen

field = new char[xsize*ysize];
der Destruktor hat den Code:

Code: Alles auswählen

delete[] field;
Allerdings stürzt mein kleines Konsolen-Programm immer bei der Ausfühgrung des Destruktors ab.
Was ist daran falsch?
Zuletzt geändert von Mampf111 am Do Feb 27, 2014 3:09 pm, insgesamt 1-mal geändert.

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8862
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: Zweidimensinales Array mit Vector Template

Beitrag von Xin » Do Feb 27, 2014 3:09 pm

cloidnerux hat geschrieben:Eine Matrix ist ein zweidimensionales Array. Du kannst entweder:

Code: Alles auswählen

char * array = new char[sizeX*sizeY];
array[0][0] = 1;
Das Codestück möchte ich nicht unkommentiert da stehen lassen... das funktioniert so nicht.

Die Umrechnung steht allerdings darunter, dann passt's wieder - also das Codestück einfach ignorieren. Vielleicht konkretisierst Du das Posting nochmal, cloidnerux?
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
cloidnerux
Moderator
Beiträge: 3125
Registriert: Fr Sep 26, 2008 4:37 pm
Wohnort: Ram (Gibts wirklich)

Re: Zweidimensinales Array mit Vector Template

Beitrag von cloidnerux » Do Feb 27, 2014 3:21 pm

Das Codestück möchte ich nicht unkommentiert da stehen lassen... das funktioniert so nicht.
Quod erat expectandum
Ja, ich dachte das es so funktionieren könnte, hätte ich vlt mal testen sollen :D
Vielleicht konkretisierst Du das Posting nochmal, cloidnerux?
Insgesamt die "einfache" Variante nutzen:

Code: Alles auswählen

char * array = new char[sizeX * sizeY];
[...]
array[X * sizeY + Y]; //anstatt array[X][Y]
Allerdings stürzt mein kleines Konsolen-Programm immer bei der Ausfühgrung des Destruktors ab.
Was ist daran falsch?
Hast du sichergestellt, dass "field" in dem Moment nicht null ist, daher an anderer Stelle freigegeben wurde oder gar nicht erst alloziert wurde?

Code: Alles auswählen

char * field = new char[sizeX * sizeY];
if(field != null)
    delete[] field;
Redundanz macht wiederholen unnötig.
quod erat expectandum

Mampf111
Beiträge: 24
Registriert: Mi Feb 05, 2014 9:59 am
Wohnort: Bielefeld

Re: Zweidimensinales Array mit Vector Template

Beitrag von Mampf111 » Do Feb 27, 2014 3:26 pm

cloidnerux hat geschrieben:Hast du sichergestellt, dass "field" in dem Moment nicht null ist, daher an anderer Stelle freigegeben wurde oder gar nicht erst alloziert wurde?
Auch mit der If-Abfrage ändert sich an dem Absturz nichts... :cry:

EDIT:

main.cpp

Code: Alles auswählen

#include <iostream>
#include <cstdlib>
#include "field.h"

int main(int argc, char *argv[])
{
    Field field;

    field.print_field();
    return 0;
}
field.h

Code: Alles auswählen

class Field
{
private:
     char *field;
public:
     void init_field();
}
field.cpp

Code: Alles auswählen


Field::Field()
{
    max_Xsize=20;
    max_Ysize=60;
    field = new char[max_Xsize*max_Ysize];

    init_field();
}

Field::~Field()
{
    if(field != NULL){
        delete[] field;    //<--- hier stürzt es ab
    }
    field=NULL;
}

void Field::init_field()
{
    for (int x=0; x<=max_Xsize; x++){
        for (int y=0; y<=max_Ysize; y++){
            if (x==0 || x==max_Xsize || y==0 || y==max_Ysize){
                fill_field(x, y, 'x');
            }else{
                fill_field(x, y, ' ');
            }
        }
    }
}

Antworten