Class Matrix (Array füllen****)

also meine header-Datei:

C++:
#ifndef MATRIX
#define MATRIX

class matrix
{
private:

	int zeilen,spalten;
	static int anz;
	double **Z;									//Matrix mit Pointer auf Pointer
		
public:
	matrix(int m=1, int n=1);					//Standartkonstruktor
	matrix (const matrix& A);					//Copy-Konstruktor
	~matrix();									//Destruktor

	void show();								//Eine Matrix ausgeben	
	matrix transpose();							//Transponieren der matrix
	void fill();								//Matrix mit Elementen füllen

	matrix operator+ (const matrix& A);			//Arithmetischer operator +
	matrix operator- (const matrix& A);			//Arithmetischer operator -
	matrix operator* (const matrix& A);			//Arithmetischer operator *
	matrix operator= (const matrix& A);			//Zuweisungsoperator

	//double det(const matrix& A);				//Determinante der Matrix
	//double eigenwerte(const matrix& A);		//Eigenwerte der Matrix
	//matrix inverse(const matrix& A);                   //Inverse Matrix

};

#endif

dann noch meine cpp-datei:


C++:
#include <iostream>
#include "matrix.h"
using namespace std;



//Konstruktor
matrix::matrix(int m, int n)    //Standardkonstruktor
{

 	zeilen=m;		
	spalten=n;
  
	  Z = new double* [zeilen];  
	  
      
	   for (int k = 0; k < zeilen; k++) 
	    {
	     Z[k] = new double [spalten];
	    }

}	
matrix::matrix(const matrix& A)
{
	zeilen=A.zeilen;
	spalten=A.spalten;

	Z=new double* [zeilen];

	for (int k = 0; k < zeilen; k++) 
	    {
	     Z[k] = new double [spalten];
	    }
	
	memcpy (Z, A.Z, (zeilen,spalten) * sizeof(double));

}	

matrix::~matrix()
{
	delete[] Z;			//Speicher freigeben				
}

void matrix::show()
{
	for (int i = 0; i < zeilen; i++)
	 {
		for (int k = 0; k < spalten; k++) 
	 { 
	 cout << Z[i][k]<<"\t"; 
	 }
		cout<<endl;
	 }

}	

void matrix::fill()
{
	for (int i=0;i<zeilen;i++)
	{
		for (int k=0;k<spalten;k++)
		{
			cout<<"bitte geben Sie das Matrixelement "<<i+1<<","<<k+1<<" ein"<<endl;
			cin>>Z[i][k];
		}
	}
}

//Arithmetische Operatoren

matrix matrix::operator= (const matrix& A)
{
	
	zeilen=A.zeilen;
	spalten=A.spalten;
	
	if (Z != NULL)
	{	
	delete[] Z;					//Speicher freigeben bzw. altes Array löschen						
	}

	Z=new double* [zeilen];		// neues in richtiger größe anlegen

	for (int k = 0; k < zeilen; k++) 
	    {
	     Z[k] = new double [spalten];
	    }
	
	for (int i=0; i < zeilen; i++)
	{
		for(int k=0;k<spalten; k++)
		{
			Z[i][k]=A.Z[i][k];
		}
	}

	//memcpy (Z, A.Z, (zeilen,spalten) * sizeof(double));	
	

return A;		//ermöglicht A=B=C
}


matrix matrix:: operator+ (const matrix& A)
 {

	  if(A.zeilen != zeilen || A.spalten != spalten)
	  {
		 cout<< "Die Matrizen haben unterschiedliche groesse und koennen daher nicht addiert werden"<<endl; 
		 
	  }
	  else
	  {
		matrix ret(A);

		for (int i = 0; i < zeilen; i++) 
		{
				for (int k = 0; k < spalten; k++) 
				 { 
					 ret.Z[i][k] = Z[i][k] +A.Z[i][k] ;
				 }
		}


		 return ret;

	  }

	
  
}

matrix matrix:: operator- (const matrix& A)
 {

	 if(A.zeilen != zeilen || A.spalten != spalten)
	 {
		 cout<< "Die Matrizen haben unterschiedliche groesse und koennen daher nicht subtrahiert werden"<<endl; 
	 }
	 else
	 {
	 matrix ret(A);
	
	for (int i = 0; i < zeilen; i++) 
	{
	for (int k = 0; k < spalten; k++) 
		 { 
			 ret.Z[i][k] = Z[i][k] - A.Z[i][k] ;
		 }
	}


	 return ret;
	 }

 
}

matrix matrix:: operator* (const matrix& A)
{
	 if(zeilen != A.spalten)
	 {
		 cout<< "Die die Dimension der Zeilen der ersten Matrix stimmen nicht mit der Dimension der Spalten er zweiten Matrix überein. Sie können daher nicht multipliziert werden"<<endl; 
		
	 }

	 int i, k,j;
	 

	 matrix ret(zeilen, A.spalten);

	 for (i = 0; i < zeilen; i++)
	 {

	 for (j = 0; j < A.spalten; j++)
	 {
		double sum=0.;
		
		for (k = 0; k< spalten ; k++)
		{
			sum=Z[i][k]*A.Z[k][j] +sum;
		}
	
		ret.Z[i][j]=sum;

	 }
	 }
	 return ret;
}

matrix matrix::transpose()
{ 
	matrix B(spalten,zeilen);

	for (int i=0;i<spalten;i++)
	{
		for(int k=0;k<zeilen;k++)
		{
			B.Z[i][k]=Z[k][i];
		}
	}

return B;
}
 
Hi,

also ich hatte mir gerade mal Zeit genommen, das zu testen. Dein = Operator scheint zu funktionieren. Das Problem ist dein "+" Operator, der macht den Fehler. Wieso weist du der Matrix "ret" die Matrix A zu? Das macht eigentlich keinen Sinn. Änder es wie folgt in
C++:
matrix ret(A.zeilen, A.spalten);

dann funktioniert das. Der Fehler könnte im Copy-Konstruktor entstehen, dass habe ich noch nicht geprüft, kannst du aber für mich machen. ;)

Nun weiß ich auch warum mein Vorschlag der Operatorüberladung nicht geklappt hat bei dir. Du implementierst die Operatoren innerhalb deiner Klasse als Methode. Das ist nicht falsch, aber üblich ist es die Operatoren bis auf "=", "=+", "=-"... oder unäre Operatoren außerhalb der Klasse als Funktionen zu implementieren.

Auch würde ich dir dringend ans Herz legen den []-Operator zu überladen, das macht das Handling innerhalb der Klasse einfacher und du hast die Möglichkeit auch auf einzelne Matrix-Elemente zuzugreifen.

Grüße,
Jennesta
 
Zuletzt bearbeitet:
Hi, danke für deine Zeit.

ich werde mir mal den Copy-konstruktor genauer ansehen^^

den [ ]-Operater habe ich noch nie überladen... meine Prof sagt auch, dass das nicht nötig sei..

deswegen bin ich über den weg der "private matrix" gegangen.. also A.Z[ i ][ k ] oder so....

ich habe uach keine idee wie ich den [ ] überladen soll :-(
 
Die Frage ist warum du überhaupt dynamischen Speicher verwenden willst, wenn du auch templates verwenden kannst?

C++:
template<uint32_t M, uint32_t N>
class Matrix {
public:
	struct Row {
	private:
		float R[N];
	public:
		float& operator [] (uint32_t index) {
			assert(index < N);
			return R[index];
		}

		const float& operator [] (uint32_t index) const {
			assert(index < N);
			return R[index];
		}
	};

private:
	Row R[M];
public:
	Matrix() {
		makeIdentity();
	}

	Matrix(const Matrix& other) {
		if(this == &other)
			return;

		for(uint32_t i = 0; i < M; ++i)
			R[i] = other.R[i];
	}

	Matrix& operator = (const Matrix& other) {
		if(this == &other)
			return *this;

		for(uint32_t i = 0; i < M; ++i)
			R[i] = other.R[i];
		return *this;
	}

	Row& operator [] (uint32_t index) {
		assert(index < M);
		return R[index];
	}

	const Row& operator [] (uint32_t index) const {
		assert(index < M);
		return R[index];
	}

	void makeIdentity() {
		for(uint32_t m = 0; m < M; ++m) {
			for(uint32_t n = 0; n < N; ++n) {
				R[m][n] = (m == n) ? 1.0f : 0.0f;
			}
		}
	}

	void fill() {
		for(uint32_t m = 0; m < M; ++m) {
			for(uint32_t n = 0; n < N; ++n) {
				std::cin >> R[m][n];
			}
		}
	}
};

Und in der Verwendung:
C++:
Matrix<3, 3> m;
m[1][1] = 4;
 
also von den befehlen habe ich noch nie etwas gehört.. ich studiere eigentlich Mathematik und informatik ist nur ein modul...

zureit bin ich am gausalgorithmus werkeln..

ich möchte sowas schreiben wie: b=gaus(a);
dabei soll mir gaus aber nicht die matrix a verändern...

C++:
matrix matrix:: gauss()		//Gaussalgorithmus auf obere Dreiecksmatrix
{

	int i=0,j,k;					//indizes
	double a;					//d ist faktor für Determinante, a ist Faktor für Zeilenoperation

	for (j=0 ; j<spalten-1 ; j++)		
	{
		for (i=0;i<zeilen-1;i++)
		{

				a= -Z[i+1][j] / Z[j][j];		//faktor bestimmen
				

		for (k=0 ; k<spalten ; k++)			//Spalten index der untermatrizen
			{
				Z[j][k]=a*Z[j][k];				//zeilen= zeile schlange
				Z[i+1][k]=Z[i+1][k]+Z[j][k];
				Z[j][k]=Z[j][k]/a;
			}
	
		
		}
	}
	return *this;
}

dann müsste er als signatur sicherlich matrix a bekommen.

klappt aber dann immernoch nicht. sobald ich dann gaus(a) verwenden will sagt er: gaus ist nicht bekannt..
 
ich möchte sowas schreiben wie: b=gaus(a);
dabei soll mir gaus aber nicht die matrix a verändern...

Wenn du das so nutzen willst, darfst du die gaus-Funktion aber nicht als Methode einer Klasse sondern als eigene Funktion erstellen.

C++:
matrix gaus(const matrix &a);

Alternativ in deiner Variante wäre der Aufruf eher

C++:
b = a.gaus();
 
Zuletzt bearbeitet:
Hm.. das soll schon eine Methode der klasse sein. damit der auf die Elemente zugreifen darf...

also er soll mir wenn ich gaus(a) schreibe die matrix a selbst nicht verändern...
 
Wenn es eine Methode der Klasse sein soll schreibt man aber nicht gauss(a) sondern a.gauss().

Wenn du nicht willst dass die Werte der Klasseninstanz verändert werden gib erstens nicht deine eigene Instanz zurück und schreib zweitens nicht in deine Werte rein.
C++:
matrix matrix:: gauss()     //Gaussalgorithmus auf obere Dreiecksmatrix
{
 
    matrix b = *this;

    int i=0,j,k;                    //indizes
    double a;                   //d ist faktor für Determinante, a ist Faktor für Zeilenoperation
 
    for (j=0 ; j<spalten-1 ; j++)       
    {
        for (i=0;i<zeilen-1;i++)
        {
 
                a= -b.Z[i+1][j] / b.Z[j][j];        //faktor bestimmen
                
 
        for (k=0 ; k<spalten ; k++)         //Spalten index der untermatrizen
            {
                b.Z[j][k]=a*b.Z[j][k];              //zeilen= zeile schlange
                b.Z[i+1][k]=b.Z[i+1][k]+b.Z[j][k];
                b.Z[j][k]=b.Z[j][k]/a;
            }
    
        
        }
    }
    return b;
}

Ausserdem: Formatierung!!
C++:
                b.Z[j][k]=a*b.Z[j][k];              //zeilen= zeile schlange
                b.Z[i+1][k]=b.Z[i+1][k]+b.Z[j][k];
                b.Z[j][k]=b.Z[j][k]/a;

for (i=0;i<zeilen-1;i++)

Das willst du niemandem (inklusive dir) antun!
C++:
                b.Z[j][k] = a * b.Z[j][k];              //zeilen= zeile schlange
                b.Z[i + 1][k] = b.Z[i + 1][k] + b.Z[j][k];
                b.Z[j][k] = b.Z[j][k] / a;

for ( i = 0; i < (zeilen - 1); i++ )

Ist das Minimum an Leerschlägen das du da reingeben solltest um die Lesbarkeit zu erhöhen. Ausserdem solltest du eine gewisse Konstanz entwickeln was das Einrücken anbelangt, manchmal machst du
C++:
for(..)
   {
   }
// manchmal
for(...)
{
}

Grüsse
Cromon
 
Hi, danke für deine Ratschläge und Tipps. Ich werde sie beherzigen :)
Das was du da geschrieben hast funktioniert bei mir leider nicht.. ich denke das Problem liegt am copy-konstruktor...


C++:
matrix::matrix(const matrix& A)  //copy-konstruktor
{
	zeilen=A.zeilen;			//zeilen und spaltenübergabe
	spalten=A.spalten;

	Z=new double* [zeilen];		//Pointer auf spalten

	for (int k = 0; k < zeilen; k++) 
	 {
	     Z[k] = new double [spalten];		//zeilen anlegen
	 }
	
	memcpy (A.Z, &Z, (zeilen,spalten) * sizeof(double));			//keine fucking Ahnung, aus Vorlesung abgegeriffen. funktioniert leider nicht

}

dieses memcpy sagt mir überhaupt gar nichts...-.-
 
Zurück