ubuntuusers.de

C: Mehrdimensionale Arrays

Status: Gelöst | Ubuntu-Version: Nicht spezifiziert
Antworten |

BobWheeler

Anmeldungsdatum:
26. September 2006

Beiträge: 32

Hallo

ich weiß, dies ist kein "richtiges" Programmier-forum, aber trotzdem 😉

folgendes Anliegen:

ich habe ein 1D-array

int *array;

dieses wird dann mittels array = new int[variable];

"variable" ist ein beliebiger int

jetzt möchte ich aber ein zweites dreidimensionales (Pointer-) Array welches auf den obigen zeigt, so dass ich dann auf dieses wie folgt zugreifen kann:

int a = array3d[wert1][wert2][wert3];

Kann da einer weiterhelfen?

Senex

Anmeldungsdatum:
17. September 2007

Beiträge: 88

Google beispielsweise: Wenn du deinen Thread-Titel bei google eingibst, kriegst du unter anderem dies hier: http://www.peacesoftware.de/ckurs8.html wo der Gebrauch von mehrdimensionalen Arrays erläutert wird.

Gruß, Ich

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

BobWheeler schrieb:

ich weiß, dies ist kein "richtiges" Programmier-forum

Was denn dann? Ein falsches Programmierforum?

Und zum eigentlichen Problem: C kennt keinen new-Operator, ich nehme an, Du sprichst von C++. Außerdem ist die Variable array kein Array, sondern ein Pointer. Zwischen Pointern und Arrays besteht ein fundamentaler Unterschied, den jeder C++-Programmierer verstanden haben sollte. Das ganze ist hier ganz gut erklärt.

ryiden

Avatar von ryiden

Anmeldungsdatum:
2. Juni 2006

Beiträge: 826

Wohnort: Mos Eisley

BobWheeler schrieb:

ich habe ein 1D-array int *array;

Das ist kein Array, sondern ein Zeiger.

dieses wird dann mittels array = new int[variable];

Du verwendest den new-Operator, bist Du sicher dass Du nicht C++ programmierst?

jetzt möchte ich aber ein zweites dreidimensionales (Pointer-) Array welches auf den obigen zeigt

Es gibt keine Pointer-Arrays, weder in C noch in C++.

Kann da einer weiterhelfen?

In C sowie in C++ kannst Du folgende Lösung verwenden:

 // 3x3-Matrix
 int matrix[3][3];
 matrix[0][0] = 5;

Ein mehrdimensionales Array mit variabler Feldgröße kannst du in C++ folgendermaßen implementieren:

 // 3x3-Matrix erzeugen
 int **matrix = new int*[3];
 for (int i = 0; i < 3; i++)
 {
   matrix[i] = new int[3];
 }

Doch wer in C++ dynamisch Speicher erzeugt, muss diesen auch wieder freigeben. Daher gehört zu jedem new auch immer ein delete.

 // Speicher der 3x3-Matrix freigeben
 for (int i = 0; i < 3; i++)
 {
   delete[] matrix[i];
 }
 delete[] matrix;

PS: Ich würde Dir zu Lösung 1 raten, da dort keine Zeigerarithmetik verwendet wird, eine Begründung dafür findest im Abschnitt Nachteile und Gefahren auf http://de.wikipedia.org/wiki/Zeiger_(Informatik).

BobWheeler

(Themenstarter)

Anmeldungsdatum:
26. September 2006

Beiträge: 32

Hello World schrieb:

Und zum eigentlichen Problem: C kennt keinen new-Operator, ich nehme an, Du sprichst von C++. Außerdem ist die Variable array kein Array, sondern ein Pointer. Zwischen Pointern und Arrays besteht ein fundamentaler Unterschied, den jeder C++-Programmierer verstanden haben sollte. Das ganze ist hier ganz gut erklärt.

Die Theorie dahinter habe ich verstanden. Mir ist klar, dass es ein Pointer ist, aber ich drücke mich teils unklar aus :/ Nun, und das ich die Theorie verstanden habe, heisst nicht das ich den Umgang mit Pointern verinnerlicht habe XD Habe zuvor meist in Java programmiert und in C/C++ meist auf Zeiger verzichtet...
Und wegen C/C++: ja, das oben ist C++. Habe aber die (dumme) Angewohnheit C und C++ zu vermischen...
Der Link oben ist gut, danke dafür

ryiden schrieb:

jetzt möchte ich aber ein zweites dreidimensionales (Pointer-) Array welches auf den obigen zeigt

Es gibt keine Pointer-Arrays, weder in C noch in C++.

http://www.netzmafia.de/skripten/ad/thomas-c/zeiger.html
das Wort ist nur haften geblieben 😉

Ein mehrdimensionales Array mit variabler Feldgröße kannst du in C++ folgendermaßen implementieren:

 // 3x3-Matrix erzeugen
 int **matrix = new int*[3];
 for (int i = 0; i < 3; i++)
 {
   matrix[i] = new int[3];
 }

Doch wer in C++ dynamisch Speicher erzeugt, muss diesen auch wieder freigeben. Daher gehört zu jedem new auch immer ein delete.

 // Speicher der 3x3-Matrix freigeben
 for (int i = 0; i < 3; i++)
 {
   delete[] matrix[i];
 }
 delete[] matrix;

Vielen Dank schonmal ☺
ich brauche genau das: ein mehrdimensionales Array mit variabler Feldgröße. Nur eben für eine 3x3x3-Matrix (z.B.)

wünschenswert wäre folgendes, ein Beispiel für ein 2D-Array (z.B. "3x3"):

1
2
3
4
5
6
7
8
9
int zeilen, spalten;
int *array;
int **array2d;


array = new int[zeilen*spalten];
array2d = new int*[zeilen];
for(i=0; i<zeilen; i++)
	array2d[i] = &(array[i*spalten]);

Dann wäre

1
array[my*zeilen+mx] == array2d[mx][my]

und sowas ähnliches bräuchte ich für ein 3D-Array (z.b. "3x3x3"), also quasi ein array3d[][][]

freebirth_one

Avatar von freebirth_one

Anmeldungsdatum:
19. Juli 2007

Beiträge: 5051

Wohnort: Mönchengladbach

Also, was dein Problem angeht, da kann ich dir leider nicht helfen (wir hatten sowas auch mal mit dynamischen Arrays, aber da ist laaaaange her.ICh glaube, wir haben das schließlich mit linked Lists realisiert).

Allerdings habe ich ein kurzes Video gefunden, was das Händlicng mit Pointern in verschiedenen Programmiersprachen erläutert (ja, intern arbeitet Java _nur_ mit Pointern resp. Refernzen. Nur dass das nach aussen hin nicht ersichtlich wird.)

–> Binky Pointer Fun.

stfischr Team-Icon

Avatar von stfischr

Anmeldungsdatum:
1. März 2007

Beiträge: 19197

Ich mach sowas immer mit nem Zeiger. Für den hol ich mir x*y*z*sizeof(typ) Speicher mit malloc (new in C++) und dann schreib ich mir ne Adressierungsfunktion.

BobWheeler

(Themenstarter)

Anmeldungsdatum:
26. September 2006

Beiträge: 32

habe es jetzt so und es läuft ☺

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    int i,j;
    int dim_x, dim_y, dim_z;
    int*** array3d = new int**[dim_x];
    int** array_tmp = NULL;
    int* array = NULL;

    for (i = 0; i < dim_x; i++) {
      array_tmp = new int*[dim_y];
      for (j = 0; j < dim_y; j++) {
	array = new int[dim_z];
        array_tmp[j] = array;
      }
      array3d[i] = array_tmp;
    }

ich lasse das thema mal noch geöffnet (als noch nicht gelöst markiert), könnt noch vorschläge posten (ob und wie es besser geht z.b.)

danke an alle!

*EDIT* → gelöst

ryiden

Avatar von ryiden

Anmeldungsdatum:
2. Juni 2006

Beiträge: 826

Wohnort: Mos Eisley

BobWheeler schrieb:

http://www.netzmafia.de/skripten/ad/thomas-c/zeiger.html#8.6 das Wort ist nur haften geblieben

Lustig wie sie das Pointer-Array nennen.

ich brauche genau das: ein mehrdimensionales Array mit variabler Feldgröße. Nur eben für eine 3x3x3-Matrix (z.B.)

Funktioniert eigentlich analog zu meinem Beispiel für das 2D-Array, nur eben mit einer weiteren verschachtelten Schleife.

 
 // Array erzeugen
 int ***array3d = new int**[3];
 for (int i = 0; i < 3; i++)
 {
   array3d[i] = new int*[3];
   for (int j = 0; j < 3; j++)
   {
     array3d[i][j] = new int[3];
   }
 }
 // Werte setzen
 array3d[0][0][0] = 1;
 array3d[0][0][1] = 2;

 // Werte ausgeben
 cout << array3d[0][0][0] << endl;
 cout << array3d[0][0][1] << endl;
 // Speicher freigeben
 for (int i = 0; i < 3; i++)
 {
   for (int j = 0; j < 3; j++)
   {
    delete[] array3d[i][j];
   }
   delete[] array3d[i];
 }
 delete[] array3d;

habe es jetzt so und es läuft ☺

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
    int i,j;
    int dim_x, dim_y, dim_z;
    int*** array3d = new int**[dim_x];
    int** array_tmp = NULL;
    int* array = NULL;

    for (i = 0; i < dim_x; i++) {
      array_tmp = new int*[dim_y];
      for (j = 0; j < dim_y; j++) {
	array = new int[dim_z];
        array_tmp[j] = array;
      }
      array3d[i] = array_tmp;
    }

In Zeile 3 verwendest du die Variable dim_x, ohne sie vorher initialisiert zu haben.

Wozu der ganze Aufwand mit den tmp-Variablen? Ich finde, das macht das ziemlich unübersichtlich.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

Wenn Du schon C++ verwendest, dann mache auch sinnvollen Gebrauch von der Standardbibliothek. Eine Möglichkeit für zweidimensionale Arrays ist bspw.

1
2
3
#include <vector>
typedef std::vector<int> intvec;
std::vector<intvec> x(20, intvec(20));

Das geht theoretisch auch für drei- oder gar vierdimensionale Arrays, aber wenn ich so etwas verwende, würde ich dann eher zu boost.MultiArray greifen.

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

Na ja, ob der Einsatz eines vectors so viel sinnvoller ist, wenn man die Element-Anzahl, bzw. die Dimension schon vorher kennt? Ich vermute einfach mal, dass ein Array etwas perfomanter ist; zumindest wenn man die Funktionen für einen vector nicht braucht.

e1bart0 Team-Icon

Avatar von e1bart0

Anmeldungsdatum:
12. Mai 2007

Beiträge: 927

Wohnort: München

Kinch schrieb:

Na ja, ob der Einsatz eines vectors so viel sinnvoller ist, wenn man die Element-Anzahl, bzw. die Dimension schon vorher kennt?

BobWheeler schrieb:

ein mehrdimensionales Array mit variabler Feldgröße.

(Hervorhebung von mir.)

Das heisst für mich, dass er nicht die Anzahl der Elemente kennt, und deshalb dynamisch Elemente (oder Dimensionen) hinzufügen will, was den Einsatz eines vectors rechtfertigen würde.

Kinch

Anmeldungsdatum:
6. Oktober 2007

Beiträge: 1261

Er kennt die Anzahl der Element zur Compiler-Zeit nicht, aber, so wie ich es sehe, doch zur Laufzeit, oder? Ich habe es jedenfalls so verstanden, dass er zu einem Zeitpunkt im Programmablauf sagen kann, dass er nicht mehr als n Element benötigt wird und demnach genauso viel Speicher alloziert.

ryiden

Avatar von ryiden

Anmeldungsdatum:
2. Juni 2006

Beiträge: 826

Wohnort: Mos Eisley

Kinch schrieb:

Na ja, ob der Einsatz eines vectors so viel sinnvoller ist, wenn man die Element-Anzahl, bzw. die Dimension schon vorher kennt? Ich vermute einfach mal, dass ein Array etwas perfomanter ist; zumindest wenn man die Funktionen für einen vector nicht braucht.

Da die vector-Klasse selbst auch als dynamisches Array implementiert ist, dürfte sich an der Performance nichts ändern (siehe http://www.cplusplus.com/reference/stl/vector/).

Der Einsatz eines vectors ist soweit sinnvoll, da der Umgang mit ihm keine Zeigerarithmetik erfordert. Die Nachteile von Zeigerartihmetik hatte ich bereits verlinkt.

PS: Ich muss sagen Hello World hat da wirklich eine elegante Lösung eingebracht.

Hello_World

Anmeldungsdatum:
13. Juni 2006

Beiträge: 3620

ryiden schrieb:

Kinch schrieb:

Na ja, ob der Einsatz eines vectors so viel sinnvoller ist, wenn man die Element-Anzahl, bzw. die Dimension schon vorher kennt? Ich vermute einfach mal, dass ein Array etwas perfomanter ist; zumindest wenn man die Funktionen für einen vector nicht braucht.

Da die vector-Klasse selbst auch als dynamisches Array implementiert ist, dürfte sich an der Performance nichts ändern (siehe http://www.cplusplus.com/reference/stl/vector/).

Sobald der vector einmal erstellt ist, stimmt das. Allerdings muss zunächst Speicher für den vector allokiert werden, und das kostet etwas Zeit. Wenn die Größe des Arrays zur Compile-Zeit bekannt ist, kann man ein std::tr1::Array verwenden. Das ist ein Wrapper für primitive Arrays, der ihnen das Interface eines STL-Containers verpasst.

Der Einsatz eines vectors ist soweit sinnvoll, da der Umgang mit ihm keine Zeigerarithmetik erfordert, die Nachteile von Zeigerartihmetik hatte ich bereits verlinkt.

Die Semantik eines std::vector<T>::iterator ist so definiert, dass sie genau der eines Zeigers entspricht (manchmal ist dieser Typ sogar einfach als T* definiert). Deswegen wird z. B. ein Iterator ungültig, wenn man vector<T>::resize aufruft. Unter Umständen muss beim resize neuer Speicher allokiert und der Inhalt verschoben werden. der Iterator zeigt dann aber noch auf den alten, freigegebenen Speicher. Dabei heraus kommt nichts anderes als ein sog. hängender Zeiger, der nicht auf eine gültige Stelle im Speicher zeigt. Ähnliche Probleme gibt es auch bei vielen anderen Iterator-Typen in der STL, und das ist eine direkte Folge des kompromisslos auf Effizienz ausgelegten Designs der STL. Die Collections im Qt4-Framework (mit new Style-Iteratoren) sind einfacher und sicherer zu benutzen, dafür aber eben ein wenig langsamer.

Antworten |