multidimensionale arrays in c++
-
Du kannst nicht davon ausgehen, dass die Zeilen und Spalten (und bei dir noch die "Tiefe") hintereinandern im Speicher liegen, da "new" irgendwo Speicher belegt. Aus diesem Grund dürfte die Zeigearithmetik, die du Anwendest (++ptr; *ptr = i;) nicht funktionieren, bzw. nur bedingt. Wenn du allerdings das Feld nicht dynamisch anforderst, sondern schon im Voraus die Größe festlegst, liegen alle Werte hintereinander im Speicher und es sollte funktionieren.
Wenn du bei der dynamsichen Variante bleiben möchtest, brauchst du drei verschiedene Interatoren. Einen, der über die Zeilen iteriert, einen weiteren der in jeder Zeile über die Spalten interiert und noch einen weiteren, der in jeder Spalte über die "Tiefe" iteriert.
bnz
-
Du kannst nicht davon ausgehen, dass die Zeilen und Spalten (und bei dir noch die "Tiefe") hintereinandern im Speicher liegen, da "new" irgendwo Speicher belegt. Aus diesem Grund dürfte die Zeigearithmetik, die du Anwendest (++ptr; *ptr = i;) nicht funktionieren, bzw. nur bedingt.
Warum nur bedingt? Wieso erhalte ich dann eine korrekte Ausgabe ohne Segmentation Fault?
Wenn du bei der dynamsichen Variante bleiben möchtest, brauchst du drei verschiedene Interatoren. Einen, der über die Zeilen iteriert, einen weiteren der in jeder Zeile über die Spalten interiert und noch einen weiteren, der in jeder Spalte über die "Tiefe" iteriert.
Hier der Versuch:
// pointer to array for dynamically allocated arrays // ptr_to_arr_dyn #include<iostream> int main() { // input data int row, column, depth; std:: cout << "Enter the values for row; column, depth"; std:: cin >> row >> column >> depth; // dynamic allocation int ***arr = new int**[row]; for (int i=0; i<row; ++i) { arr[i] = new int*[column]; for (int j=0; j<column; ++j) arr[i][j] = new int[depth]; } // fill in the natural numbers int n=0; for(int (*itrrow)[column][depth]=arr; itrrow<arr+row; ++itrrow) for(int (*itrcolumn)[depth]=*itrrow; itrcolumn<*itrrow+column; ++itrcolumn) for(int *itrdepth=*itrcolumn; itrdepth<*itrcolumn+depth; ++itrdepth) { *itrdepth=n; std::cout << *itrdepth << "\n"; ++n; } // free memory for (int i=0; i<row; ++i) { for (int j=0; j<column; ++j) delete[] arr[i][j]; delete[] arr[i]; } delete[] arr; return 0; }Es scheitert nur lediglich noch an Zeile 21, bzw. daran, das ich nicht weiß, wie man einen Pointer mit dem ersten Element eines dynamisch allozierten multidimensionalen arrays initialisiert. Ich finde auch nichts darüber im w3. Schon mal danke für die Tipps.

-
Hallo!
Ich hab das mal für die Schule machen müssen, also ein mehrdimensionales Array mit Pointer auf Pointer.
Kannst ja mal schauen ob du irgendwas davon brauchst.
#include<iostream> #include<conio.h> using namespace std; //Prototypen int** make2dFeld(int,int); void init2dFeld(int**,int,int); void out2dFeld(int**,int,int); void delete2dFeld(int**,int); //Definitionen void delete2dFeld(int** zeig,int z) { //Spalten des Feldes freigeben for(int i=0;i<z;i++) { delete []zeig[i]; } //Zeilen(Zeigerfeld) freigeben delete []zeig; cout<<"Feld geloescht!"<<endl; } void out2dFeld(int** zeig,int s,int z) { cout<<"Inhalt des Feldes"<<endl<<endl; //Ausgabe des Feldes for(int i=0;i<z;i++) { cout<<endl; for(int j=0;j<s;j++) { cout<<zeig[i][j]<<" "; } } cout<<endl; } int** make2dFeld(int s,int z) { int** zeiger = new int*[z]; for(int i=0;i<z;i++) { zeiger[i] = new int[s]; } //Jedes Feldelement 0 zuweisen for(int i=0;i<z;i++) { for(int j=0;j<s;j++) { zeiger[i][j]=0; } } cout<<"Feld erstellt."<<endl; return zeiger; } void init2dFeld(int** zeig,int s,int z) { int zahl = 0; //Zeilenweise die Spalten durchlaufen for(int i=0;i<z;i++) { for(int j=0;j<s;j++) { zeig[i][j]=zahl; zahl++; } } cout<<"Feld initialisiert."<<endl; } //Hauptprogramm int main() { int** test; test = make2dFeld(10,10); cout<<"Feldadresse: "<<&test<<endl; getch(); init2dFeld(test,10,10); getch(); out2dFeld(test,10,10); getch(); delete2dFeld(test,10); cout<<"Feldadresse: "<<&test<<endl; getch(); return 0; }
-
Dieser Thread wurde von Moderator/in rüdiger aus dem Forum Rund um die Programmierung in das Forum C++ verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Warum nur bedingt? Wieso erhalte ich dann eine korrekte Ausgabe ohne Segmentation Fault?
Bedingt, weil du den Pointer auf die erste "Tiefe" (int *ptr=arr[0][0];) setzt. Die nächste "Tiefe" (echt ein blödes Wort, hätte nicht ein 2d-Array gerreicht?
) kann sich irgendwo anders im Speicher befinden, da "new" ja den Speicher nicht hintereinander reserviert. Wenn es doch klappt, dann sollte das eigentlich Zufall bzw. wurde es ggf. vom Compiler so eingerichtet, dass es funktioniert.Falls ich hier Falschaussagen mache, möge mich bitte einer der Code-Gurus hier berichtigen.
Ansosnten sieht dein neuer Code eigentlich gut aus. Ich sehe da keinen direkten Fehler...
bnz
-
Hi, also ich hab mir jetzt deinen code mal angeschaut und wie es aussieht scheitert das ganze mMn an zeile 28:
delete[] arr[i][j];bis dahin läuft das programm, alle pointer und arrays werden ordnungsgemäß erstellt, gefüllt und ausgegeben aber an dieser einen stelle ist irgendwie der wurm drin. Kommentier mal die zeile aus dann wird alles laufen, frag mich aber nicht warum

-
Ich beziehe mich auf den allerersten post ganz oben.
-
Es hilft tatsächlich. Es ist zwar ziemlich eigenartig aber trotzdem vielen Dank.
Wenn mir nun noch jemand erklärt, wie man einen Pointer mit dem ersten Element eines dynamisch allozierten multidimensionalen arrays initialisiert, was nämlich zum Problem in Zeile 21 des zweiten Codes wird, gebe ich Ruhe.
Gute Nacht
-
Warum willst du das denn unbedingt mit pointern an dieser stelle machen?
Habe nochmal über das von mir beschriebene problem nachgedacht. Der grund dafür könnte zeile 18 sein:
int *ptr=arr[0][0];Du hast einen pointer der auf die elemente des arrays zeigt. Wenn dann die elemente gelöscht werden sollen, gibts ein problem. Das hört sich zwas spanisch an aber eine andere erklärung hab ich im moment dafür nicht. Hoffe das hilft dir nochmal weiter.
-
Jup, wenn ich *ptr entferne geht alles, es wird auch alles ordnungsgemäß gelöscht

-
Diese ganze Rumfrickelei mit Zeigern ist hochgrading fehleranfällig. In C mag man das ja vielleicht so machen, aber in C++ kann man mit relativ wenig Aufwand eine recht robuste Klasse daraus machen.
#include <vector> #include <cstddef> #include <stdexcept> template<typename T> class Array2D { std::size_t Rows_; // Anzahl Zeilen std::size_t Cols_; // Anzahl Spalten std::vector<T> Data_; // Inhalt public: Array2D() : Rows_( 0 ), Cols_( 0 ) { } Array2D( std::size_t Rows, std::size_t Cols ) : Rows_( Rows ), Cols_( Cols ), Data_( Rows * Cols ) { } T& operator()( std::size_t Row, std::size_t Col ) { if( Row < rows() && Col < cols() ) { return Data_[Row * cols() + Col]; } throw std::out_of_range( "Array index out of range" ); } const T& operator()( std::size_t Row, std::size_t Col ) const { if( Row < rows() && Col < cols() ) { return Data_[Row * cols() + Cols]; } throw std::out_of_range( "Array index out of range" ); } std::size_t rows() const { return Rows_; } std::size_t cols() const { return Cols_; } bool empty() const { return Data_.empty(); } std::size_t size() const { return Data_.size(); } void resize( std::size_t Rows, std::size_t Cols ) { Data_.resize( Rows * Cols ); Rows_ = Rows; Cols_ = Cols; } }; int main() { // erzeuge 0x0 Array, dann auf 5x3 vergrössern Array2D<int> a1; a1.resize( 5,3 ); // erzeuge 10x20 Array Array2D<int> a2( 10, 20 ); }Edit:
Mal durch den Compiler geschickt und Bugs entfernt
-
@ DocShoe:
ist zwar alles gut und schön was du sagst, aber bei mir z.B. wurden nie Vectoren dran genommen, also durften wir sowas auch nicht benutzen (wahrscheinlich weil es der Lehrer selbst nicht kann
).Also blieb uns nix anderes übrig als Pointer auf Pointer usw.
-
Na jut, dann will ich das mal durchgehen lassen...
Nach wie vor ist mein Einwand gültig, durch den Zugriff auf Rohzeiger landest du schneller in undefiniertem Verhalten als du gucken kannst. Selbst wenn du eine Lösung ohne std::vector schreiben musst kannst du die Zugriffe auf die Daten soweit kapseln, dass du robusten Code erhälst.
Wenn ihr std::vector nicht behandelt habt, dann hast du sicherlich auch noch nichts über templates gelernt, daher solltest du versuchen, eine 2D Array Klasse mit einem konkreten Datentyp zu programmieren. Den std::vector kann man durch 10 Zeilen weiteren Code ersetzen, lediglich die resize() Methode erfordert etwas mehr Aufmerksamkeit. Und du musst natürlich den Kopierkonstruktor und Zuweisungsoperator implementieren oder verbieten, aber das sind auch schon fortgeschrittene Themen.
Probier´s einfach mal, ist nicht so schwierig. Was man Programmieren unbedingt begreifen muss, ist dass robuster und leicht wartbarer Code wichtiger ist als irgendeine schnelle Lösung, die eher schlecht als recht funktioniert. Was du dir jetzt als Programmierstil aneignest wirst du später schwer wieder los.
-
Stimmt, wir hatten keine Vectoren und dementsprechend auch keine Templates.
Wir durften nicht mal strings benutzen, wir mussten alles schön in chars kloppen.
BTW: ich habe die Frage gar nicht gestellt, wollte dem Threadersteller nur mal zeigen wie es gehen könnte mit Pointer auf Pointer, und hab nur auf deine Aussage geantwortet dass es evtl. sein kann, so wie bei mir, das die das gar nicht benutzen dürfen.
