Länge Zeiger Array bestimmen
-
Hi,
ich habe das Problem das ich ein dyn. Array erzeugt habe und jetzt die Größe, also Zeilen-, Spaltenanzahl bestimmen möchte.
(hab schon im Archiv gesucht bin aber nicht so richtig fündig geworden, möchte nicht mit <vektor> und so arbeiten)
Es muss doch möglich sein OHNE externe Variable die die Längen speichert auszukommen.
Möchte das dyn Array als Rückgabevariable in Funkt. nutzen, da geht das überhaupt nicht mit den externen Variablen.
Oder soll ich die Längen noch irgendwo ans Ende(Anfang) des reservierten Speicherbereiches anfügen?? Aber wie komme ich dann dort hin wenn ich die auslesen möchte??Brauch das aber alles unbedingt in irgendeiner Form, zur Not eben auch Hilfsmöglichkeiten...
*hilflos*...ich weiss das ihr wisst wies geht
?
Hier das Array
// dyn. Arrayvariable deklarieren int **mymatrix; SetArray(mymatrix,3,3); void SetArray(int **Array, int Zeilenanz, int Spaltenanz){ if((Array = new int*[Zeilenanz]) == NULL) ShowMessage("Speicherfehler"); { for (int i = 0; i < Zeilenanz; i++) // Spaltenlänge setzten { if((Array[i] = new int[Spaltenanz]) == NULL) ShowMessage("Speicherfehler"); memset(Array[i], NULL, Spaltenanz*sizeof(int)); } } return; } // Funktion Zeilen auslesen int Zeilenanz(int **Array){ ??? } // Funktion Spalten auslesen int Zeilenanz(int **Array){ ??? }
dankedankedanke schonmal
CS
-
Also generell geht das mit
int groesse = sizeof( array ) / sizeof( array_element );
2D dann so:
int groesse = ( sizeof( array2D ) / sizeof( array ) ) * ( sizeof( array ) / sizeof( array_element ) );
-
das geht aber soweit ich weiß auch nur mit statischen arrays und nicht mit dynamischen. Meiner meinung wird sizeof zur compilezeit ausgewertet. Wie soll der compiler wissen, wie viel man später anfordert? Ich kenne keine keine Möglichkeit, die Größe eines dynamischen Arrays ohne ext Variablen zu bekommen. Warum sträubst du dich geben std::vector?
-
...und ich dachte, in C++ gibt es keine dynamischen Arrays
Also müsste Zeilenanz doch auch zur Compilezeit ausgewertet werden, dachte ich..
Ach übrigends:
int groesse = Zeilenanz * Spaltenanz * sizeof( int )
-
soll die größe deines 'arrays' dynamisch bestimmt werden, kommst du um die separate speicherung der größe nicht herum. sinnvoll ist es auf jedenfall, das ganze in einer eigenen klasse durchzuführen, etwa:
class Matrix2d { public: Matrix2d(std::size_t rows, std::size_t columns) : columns_( columns ), v_( rows * columns ) {} std::size_t rows() const { return v_.size() / columns_; } std::size_t columns() const { return columns_; } int* operator[](size_t row) { return &v_[ row * columns_ ]; } const int* operator[](size_t row) const { return &v_[ row * columns_ ]; } private: std::size_t columns_; std::vector<int> v_; };
-
@1310-Logik:
Was Maxi meint, so wie Du es beschreibst funktioniert es nur mit Arrays, nicht mit Zeigern (den Unterschied haben wir imho schon öfters durchgekaut
)
Also es geht schief, so bald Du den mit [] definierten Array einem mit * definiertem Zeiger zuweist oder übergibst. Denn ein Zeiger ist immer (Adressbusbreite) Bits groß.
-
Ist sowas denn noch C++?
Ich dachte das Zeiger-Array-Memset Zeugs wär irgendwie C?
Sowas wie Camper's Klasse ist doch C++, oder?
-
Ja, aber meine (und auch Deine erste) Antwort gingen vom OP aus.
-
..und ich dachte immer C++ - C == OOP
-
ja danke erstmal für die Antworten, aber das verwirrt mich jetzt schon...
Was geht den nun und was nicht?
@camper
Die Klasse Matrix2d sieht schonmal gut aus.
Aber der Inhalt ist mir an einigen Stellen bissl rätselhaft,
könntest du das nochmal etwas näher Beschreiben, vll. mit kl. AnwendungsBsp.
Der teil im private Abschnitt ist mir nicht wirklich klar und auch die anderern nicht 100%.Oder sagst mir link hie rim forum wo genau das behandelt wurde
danke schonmal.
-
{ // Testblock Matrix2d matrix2d( 5, 5 ); std::cout << matrix2d.rows() << std::endl; std::cout << matrix2d.columns() << std::endl; std::cout << matrix2d[3] << std::endl; std::cout << matrix2d[3][3] << std::endl; } // Testblock
-
Hi!
Machs so
void *operator new[]( size_t size ) { size_t *p = ( size_t *)malloc( size+sizeof( size_t ) ); *p = size; return p+1; } void operator delete[]( void *ptr ) { char *p = ( ( char *)ptr-sizeof( size_t ) ); free( p ); } size_t memsize( void *p ) { return *( ( size_t *)( ( char *)p-sizeof( size_t ) ) ); }
grüße
-
ja danke für die Hinweise.
das mit der Klasse klappt ja erstmal Anwendungsmäßig...auch wenn ich nicht weiss warum*g*
Würde wirklich gern bissl Erklärung dafür bekommen.
(kommentiert mir doch einfach mal bitte jeden Zeile was in der Klasse so passiert, wäre perfekt)
Die zeile unter dem Construktor ist mir z.B unter anderem ziemlich rästelhaft:: columns_( columns ), v_( rows * columns )
auch was im privat-teil steht.
für was steht eigentlich so richtig size_t...?
man gibt doch beim konstruktoraufruf keinen Typ an, ist doch eigentlich immer int???
(verzeiht mir diese primitiven fragen, aber komme eigentlich net aus der c++Richtung
muss aber aktuell was damit schreiben, geht ja auch bis auf paar Hänger...wenn ich die dann weiss kein problem*g*)@David_pb:
danke, aber wie ist das jetzt anzuwenden*g*?
Kann ich damit jetzt die länge eines 1D dyn. array bestimmen?
Geht das auch mit zweidimensionalen arrays?
Was bedeutet *operator vor dem new?
warum zeiger auf speicheradresse p+1?
Folgendes script geht jedenfalls nicht...void *operator new[]( size_t size ); int *myarray; myarray = (int*)new[](3); void *operator new[]( size_t size ) { size_t *p = ( size_t *)malloc( size+sizeof( size_t ) ); *p = size; return p+1; }
..danke das ihr dran bleibt am problem
-
Hi!
: columns_( columns ), v_( rows * columns )
Hierbei handelt es sich um eine Initialisierungsliste, die Objekte columns_ und v_ werden hier initialisiert.
void *operator new[]( size_t size ) { size_t *p = ( size_t *)malloc( size+sizeof( size_t ) ); *p = size; return p+1; } void operator delete[]( void *ptr ) { char *p = ( ( char *)ptr-sizeof( size_t ) ); free( p ); } size_t memsize( void *p ) { return *( ( size_t *)( ( char *)p-sizeof( size_t ) ) ); } int main() { int *myarray = new int[ 20 ]; std::cout << "myarray hat: " << ( memsize( myarray ) / sizeof( int ) ) << " Eintraege" << std::endl; delete [] myarray; std::cin.get(); return 0; }
Geht doch!
-
@david_pb:
ja ok na supi wenn ich doch noch bei meinen alten Arrays bleiben könnte
Aber ich sehe keine Möglichkeit das, so wie du es machst, bei zweidimensionalen Arrays zu machen, also die zeiger auf zeiger arrays(siehe ganz anfang beitrag).Könntest du das kurz beschreiben wie's gehen könnte?
hmm, und noch die Frage sag mal wenn ich doch mit der Array-Klasse arbeite...wie lässt sich so ein Ding wieder löschen???
habe folgenden Code, aber ich kann das myarray nicht nochmal erstellen,
obwohl es ja eigentlich durch den Standardkonstruktor gelöscht sein müsste.Matrix2d array(100,10); array[0][0] = 111; // nur so ne sinnlose zuweisung *g* array.~Matrix2d(); // array wird komplett gelöscht? k.a.? Matrix2d array(1000,400); // hier schreit der compiler das es nicht geht // da der Name schon vergeben sein soll?
Ach ja und lässt sich eigentlich das Klassen-Array auch mit AnsiStrings füllen statt mit int-Werten??
das ist eigentlich der Inhalt der da rein muss*g*
danke schonmal
-
Du solltest den Destructor nicht explicit aufrufen.
Entweder legst du ein neues Objekt an,Matrix2d array(100,10); array[0][0] = 111; // nur so ne sinnlose zuweisung *g* // array.~Matrix2d(); Nein! Matrix2d array2(1000,400); //neuer Name neues Glück
Oder
{ // Blockanfang Matrix2d array(100,10); array[0][0] = 111; // nur so ne sinnlose zuweisung *g* } // Blockende: array wird vom Stack gelöscht { // Blockanfang: Das selbe nochmal Matrix2d array(1000,400); array[0][0] = 222; // nur so ne sinnlose zuweisung *g* } // Blockende: array wird vom Stack gelöscht
Nich so schön, aber geht auch
Oder dynamisch auf den Heap
Matrix2d* array; // Lege einen Zeiger an array = new Matrix2d(100,10); // Ertselle dynamisch das Objekt // tu was damit delete array; // Lösche das Objekt ( nicht den Zeiger ) //... array = new Matrix2d(1000,40); // Ertselle dynamisch ein neues Objekt // tu was damit delete array; // Lösche das Objekt wieder
Edit: Ach ja, füllen kannst Du mit was Du willst, musst nur den Typ des Vectors, und die Übergabeparameter anpassen. Ev. auch ein template machen, dann kannste das Gerüst wiederverwenden für jeden Typ.
Edit2: (C)Camperclass Matrix2d { public: Matrix2d(std::size_t rows, std::size_t columns) : columns_( columns ), v_( rows * columns ) {} std::size_t rows() const { return v_.size() / columns_; } std::size_t columns() const { return columns_; } AnsiString* operator[](size_t row) { return &v_[ row * columns_ ]; } const AnsiString* operator[](size_t row) const { return &v_[ row * columns_ ]; } private: std::size_t columns_; std::vector<AnsiString> v_; };
Oder als Template
template<typename T> class Matrix2d { public: Matrix2d(std::size_t rows, std::size_t columns) : columns_( columns ), v_( rows * columns ) {} std::size_t rows() const { return v_.size() / columns_; } std::size_t columns() const { return columns_; } T* operator[](size_t row) { return &v_[ row * columns_ ]; } const T* operator[](size_t row) const { return &v_[ row * columns_ ]; } private: std::size_t columns_; std::vector<T> v_; }; // Instanzierung: Matrix2d<AnsiString> ansi_array(100,10); Matrix2d<int> integer_array(1000,400);
-
@Greenfreek zur Klarstellung:
In C und auch in C++ gibt es keine Möglichkeit, die Größe eines
Arrays zur Laufzeit festzustellen.Etwas verschärfter formuliert als bereits geschrieben wurde:
*In C und C++ gibt es kein Sprachkonstrukt Array, wie es
z.B. in Java (und ich glaube auch in Pascal) existiert.Es gibt ausschließlich Zeiger.
Die Array-Syntax kennt nur der Compiler!*
Aus diesem Grund wird auch die Länge eines Arrays nirgendwo
gespeichert und ist auch in keiner Weise zu berechnen.Dies ist auch der Grund, warum es ein argc in der main-Funktion gibt
und alle Strings mit '\0' beendet werden müssen.Ich habe den Thread nicht vollständig durchgelesen, aber alle vorgeschlagenen
Lösungen über Klassen können prinzipiell nichts anderes sein
als Minimal-Implementierungen von Klassen wie Vector.Alles läuft zwangsläufig darauf hinaus, eine Klasse zu entwickeln,
die durch Kapselung einer Längenangabe und der eigentlichen Daten
das Konzept eines Arrays simuliert.