Spalten und Zeilenanzahl 2D-Array



  • Hallo, ich bin noch recht neu hier und hab eine kleine Frage. 🙂
    Ich möchte mir gerne mit Hilfe von 2 Funktionen die Spalten und Zeilenanzahl von einem 2D-Array ausgeben lassen 🙂
    Folgendes habe ich schon probiert:

    int Matrix::n_zeilen() {
    	/*int i = 0;
    	int length = 0;
    	while (m[length][0]) i++;{
    		length = length + i;
    	}
    	
    	return length;*/
    	//size_t element_count = sizeof(*m); /// sizeof(*m);
    	 //return element_count;
    	int length = sizeof(m) / sizeof(m[1]);
    	return length;
    

    Bei der While Schleife kommt es zu keiner Ausgabe.
    und bei den anderen wird entweder 4 ausgegeben oder 0 🙂

    Hoffe, dass mir jemand weiterhelfen kann 🙂
    Vielen Dank im Voraus!



  • Warum willst du irgendetwas rechnen? Die Klasse Matrix sollte doch wissen, wie groß sie ist.



  • Naja es soll dynamisch sein 🙂
    Also es wird so aufgerufen:

    int main()
    {
    	
    	Matrix m1(5, 3), m2(3, 5);
    

    Nun möchte ich die Funktionen n_zeilen und n_spalten dazu benutzen um die Anzahl der Zeilen, bzw Spalten zurückzugeben 🙂



  • @manni66 Ich konnte es lösen 🙂
    Habe einfach 2 private Variablen deklariert, die beim Initalisieren der Matrix die Anzahl speichert 🙂
    Die kann ich dann über die 2 Methoden ausgeben. Vielen Dank für den Denkanstoß 🙂



  • @Ouvert Zeig mal den Rest.



  • Es gibt in der Klasse Matrix 3 Methoden um eine Matrix zu initalisieren:

            Matrix();
    	Matrix(int zeilen, int spalten);
    	Matrix(Matrix& m);				  
    	~Matrix();
    

    Aufruf der Fehler erzeugt:

    void matrix1(Matrix& m)
    {
    	double mat[5][3] = { { 1.0, 0.0, 0.0 },
    						  { 0.0, 2.0, 0.0 },
    						  { 0.0, 0.0, 3.0 },
    						  { 4.0, 0.0, 0.0 },
    						  { 0.0, 5.0, 0.0 }
    	};
    
    
    	for (int z = 0; z < m.n_zeilen(); z++) 
    		for (int s = 0; s < m.n_spalten(); s++) {
    			m.setze_element(0,0,5);
    			if (m.setze_element(z, s, mat[z][s]) == 0)    // :(
    			{
    				cout << "Fehler" << endl;
    				exit(EXIT_FAILURE);
    			}
    		}
    

    Nun habe ich das Problem, dass beim Aufruf von matrix1 die Funktion m.setze_element(zeile, spalte, wert) eine Lesezugriffsverletzung wirft.
    Die Funktion ist so gebaut:

    if (zeile >= 0 && spalte >= 0) {
    		m[zeile][spalte] = wert;		// Lesezugriffsverletzung da &m noch nicht initalisiert
    		cout << "Element an "<< m[zeile][spalte] << endl;
    		return 1;
    		
    	}
    	else { return 0; }
    

    Ich vermute, dass das Problem bei der Initalisierung liegt? Also in der Methode Matrix(int zeilen, int spalten); wird das dynamische Array ja erstellt aber bei Benutzung von Matrix(&m) fehlt diese bestimmt?!
    Wie kann ich das lösen? 🙂
    Hab noch nicht so viel Erfahrung bei C++.



  • @Ouvert vollständigen Code den man so wie er ist einem Compiler füffern kann.

    . o O ( warum glauben so viele immer daß potentielle Helfer lust an Ratespielen haben!? )



  • Entschuldige, dass mein Post nicht so verständlich war 🙂
    Hier der Code der Matrix:

    // matrix.h
    #include <iostream>
    using namespace std;
    
    class Matrix
    {
    private:
    	int anzZeilen;
    	int anzSpalten;
    	double** m;
    
    public:
    	Matrix();
    	Matrix(int zeilen, int spalten);
    	Matrix(Matrix& m);				  // Copy-Konstruktur
    	~Matrix();
    	Matrix operator = (Matrix& m);    // Zuweisungsoperator
    	int setze_element(int zeile, int spalte, double wert); //Setzt ein Element an die Stelle
    	double lese_element(int zeile, int spalte, int& erfolg); //gibt das Element an der Stelle aus + ob es erfolgreich war
    	int n_zeilen(); //Gibt Zeilen der Matrix zurück
    	int n_spalten(); // Gibt Spalten der Matrix zurück
    };
    
    ostream& operator <<(ostream& s, Matrix& m);
    //ich bin mir auch nicht sicher, ob die Funktion hier auch funktioniert um die Matrix anzuzeigen
    std::ostream& operator<< (std::ostream& s, Matrix& m)
    {
    	int erfolg;
    	for (int i = 1; i <= m.n_zeilen(); i++)
    	{
    		for (int j = 1; j <= m.n_zeilen(); j++)
    			s << m.lese_element(i, j, erfolg);
    		s << std::endl;
    	}
    	return s;
    }
    
    Matrix::Matrix() {	//der Default-Konstruktor
    	
    }
    
    Matrix::Matrix(int zeilen, int spalten) { 
    // 1. Schritt: Dynamische Array von Zeigern anlegen
    	
    	if(zeilen > 0 && spalten > 0){
                   	anzSpalten = spalten;
    		anzZeilen = zeilen;
    
    		double** m = new double* [zeilen];
    
    		// 2. Schritt: An jeden Zeiger ein Array hängen
    		for (int i = 0; i < zeilen; i++)
    			m[i] = new double[spalten];
    	}
    	else
    	{
    		cout << "\nUngültige Anzahl an Spalten oder Zeile";
    	}
    
    }
    Matrix::Matrix(Matrix& m) {	//Copy-Konstruktor -> Steuerung des Kopieren aus einer anderen Instanz der gleichen Klasse
    }
    Matrix::~Matrix()
    {	//der Destruktor -> wird aufgerufen wenn eine Instanz der Klasse zerstört wird
    	delete m;		//reservierten Speicherplatz freigeben
    }
    
    int Matrix::setze_element(int zeile, int spalte, double wert) {
    	if (zeile >= 0 && spalte >= 0) {
    		m[zeile][spalte] = wert;		// Lesezugriffsverletzung da &m noch nicht initalisiert
    		cout << "Element an "<< m[zeile][spalte] << endl;
    		return 1;
    		
    	}
    	else { return 0; }
    }
    
    double Matrix::lese_element(int zeile, int spalte, int& erfolg) {
    	if (zeile > 0 && spalte > 0) {
    		return m[zeile][spalte];
    		return erfolg = 1;
    	}
    	else { return erfolg = 0; }
    
    }
    
    int Matrix::n_zeilen() {
    	return anzZeilen;
    }
    int Matrix::n_spalten() {
    	return anzSpalten;
    }
    
    


  • und die dazugehörige cpp Datei:

    void belegen_m1(Matrix& m)
    {
    	double cmat[5][3] = { { 1.0, 0.0, 0.0 },
    						  { 0.0, 2.0, 0.0 },
    						  { 0.0, 0.0, 3.0 },
    						  { 4.0, 0.0, 0.0 },
    						  { 0.0, 5.0, 0.0 }
    	};
    
    	cout << "m1 belegen = erfolgt" << endl;		
    	cout << "Anzahl Zeilen der Matrix m1: " << m.n_zeilen() << endl;
    	cout << "Anzahl Spalten der Matrix m1: " << m.n_spalten() << endl;
    	
    	for (int z = 0; z < m.n_zeilen(); z++) 
    		for (int s = 0; s < m.n_spalten(); s++) {
    			m.setze_element(0,0,5);
    			if (m.setze_element(z, s, cmat[z][s]) == 0)
    			{
    				cout << "Fehler" << endl;
    				exit(EXIT_FAILURE);
    			}
    		}
    }
    
    
    int main()
    {
    	
    	Matrix m1(5, 3), m2(3, 5);
    	//Matrix m3, m4, m5, m6, m7;
    	cout << m1.n_zeilen() << endl;		
    	cout << m1.n_spalten() << endl;		
    
    	belegen_m1(m1);
    
    	cout << "m1:" << endl << m1 << endl;
    	cout << "m2:" << endl << m2 << endl;
    }
    


  • @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    Matrix::~Matrix()
    {	//der Destruktor -> wird aufgerufen wenn eine Instanz der Klasse zerstört wird
    	delete m;		//reservierten Speicherplatz freigeben
    }
    

    Alles, was mit new[] alloziiert wird, muss mit delete[] freigegeben werden. Du glaubst doch nicht ernsthaft das delete automagisch weiß, daß Du ihm einen double ** fütterst und dann ebenso automagisch jedes m[0...zeilen] durchgeht und dann nochmal automagisch weiß, daß darauf delete[] anzuwenden ist anstatt delete?

    @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    Matrix(Matrix& m);				  // Copy-Konstruktur
    

    Das Argument sollte eine Reference auf const sein:

    Matrix(Matrix const &m);
    

    @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    Matrix operator = (Matrix& m); // Zuweisungsoperator

    Entweder eine Reference auf const übergeben oder Copy and Swap.

    Nebenbei: Das was Du da baust hat mit einem 2D-Array ungefähr soviel zu tun wie ein VW-Käfer mit einem Lamborghini. Die entscheidende Eigenschaft eines Arrays ist, das die Elemente alle direkt nebeneinander im Speicher liegen. Was Du aber baust schaut so aus:

    +---------------+          +----------+
    | double **hugo |      +---| double * |
    +---------------+      |   +----------+
    | hugo[0] ------|------+   |    1.    |
    | hugo[1] ------|------+   |    2.    |
    | hugo[2] ------|----+ |   |    3.    |
    | hugo[3] ------|--+ | |   |    ...   |
    | ...           |  | | |   +----------+
    +---------------+  | | |
                       | | |     +----------+
                       | | +-----| double * |
                       | |       +----------+
                       | |       |    4.    |
                       | |       |    5.    |
                       | |       |    6.    |
                       | |       |    ...   |
                       | |       +----------+
                       | |
                       | |         +----------+
                       | +---------| double * |
                       |           +----------+
                       |           |    7.    |
                       |           |    6.    |
                       |           |    8.    |
                       |           |    ...   |
                       |           +----------+
                       |
                       |              +----------+
                       +--------------| double * |
                                      +----------+
                                      |    9.    |
                                      |   10.    |
                                      |   11.    |
                                      |    ...   |
                                      +----------+
    

    Dagegen ein 2D-Array double[4][3]:

    +-----+
    |  1. |
    |  2. |
    |  3. |
    |  4. |
    |  5. |
    |  6. |
    |  7. |
    |  8. |
    |  9. |
    | 10. |
    | 11. |
    +-----+
    


  • Danke schonmal für die Antworten,
    wie gesagt, ich bin noch neu in C++, daher weiß ich noch nicht so recht wie ich mit der delete Anweisung umgehen soll 🙂
    Ich nehme allerdings an, dass ich eine doppelte For-Schleife brauche, um jedes Element des 2D-Arrays zu löschen?!:)

    Matrix(Matrix&m) war so vorgegeben, ich weiß leider nicht so recht, was das bedeutet 😃



  • @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    daher weiß ich noch nicht so recht wie ich mit der delete Anweisung umgehen soll

    Am Besten garnicht. Aber

    @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    war so vorgegeben

    hört sich so an als ob Du müsstest. Zu jedem new gehört ein delete, zu jedem new[] gehört ein delete[]. Mischen ist nicht.

    Wie lautet die konkrete vollständige Aufgabenstellung?

    @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    Ich nehme allerdings an, dass ich eine doppelte For-Schleife brauche, um jedes Element des 2D-Arrays zu löschen?!:)

    Bingo.

    @Ouvert sagte in Spalten und Zeilenanzahl 2D-Array:

    Matrix(Matrix &m) war so vorgegeben, ich weiß leider nicht so recht, was das bedeutet

    Copy constructors



  • Die Aufgabenstellung lautet, die Matrix.h klasse so zu vervollständigen, dass sich Das Hauptprogramm(in dem die Methoden vorgegeben sind) ausführen lässt 🙂 (siehe oben).und vorgeben in der Klasse Matrix sind bloß die Methoden unter Public:, sowie die erste Zeile darunter names ostream(bin am Handy und kann es nicht kopieren, sorry)
    Des Weiteren wird von einem Array ausgegangen das ganz wenige 0 Elemente besitzt. Deswegen soll das ganze Array aus dem Produkt der Spalten und Zeilen allokiert werden 🙂

    Die Funktionalitäten der Methode habe ich selbst hinzugefügt 🙂

    also es wäre schön, wenn sich die Matrix erstmal in der Konsole ausgeben lassen würde, nachdem die Objekte in Main erschaffen wurden:D
    Das würde mir wirklich viel weiterhelfen 😃
    Glaube das Hauptproblem liegt an Matrix(Matrix& m) und die fehlende Initalisierung des Arrays?
    Gute Nacht und vielen Dank
    Ich antworte dann morgen wieder 🙂


Anmelden zum Antworten