PDA

Visualizza la versione completa : c++ problema con template e matrici


Bibibea
18-09-2013, 17:28
Ciao, ho bisogno di qualche persona gentile che mi dia una mano. devo presentare un progetto per domani e mi sta fumando il cervello perchè mi rendo conto di avere molte lacune... devo utilizzare una classe template per vari calcoli (trasposta, inversa, determinante) da effettuare su matrici di qualsiasi tipo(int, float, complessi ecc...)
Il codice che ho scritto fin'ora è questo ma credo che molte cose siano sbagliato, date le mie tante insicurezze! inoltre non riesco ad andare avanti per la definizione della funzione inversa Help me please! :cry:



#ifndef MATRICETEMPLATE
#define MATRICETEMPLATE

/*definisco la classe template Matrice*/
template <class T, int R, int C> class Matrice
{
private:
T mat[R][C]; //array bidimensionale (matrice2D) di tipo T
int Righe,Colonne; //variabili di tipo int
void Zero(void); //funzione che inizializza gli elementi di mat a T(0)
Matrice *TMP; //puntatore a un'istanza della classe Matrice
public:
Matrice(void); //costruttore
~Matrice(void); //distruttore
//dichiarazioni delle funzioni
int SonoZero(void);
int SonoQuadrata(void);
void MettiValori(int,int,T);
int operator==(Matrice&);
int operator!=(Matrice&);
Matrice& operator=(Matrice&);
Matrice& operator+(Matrice&);
Matrice& operator-(Matrice&);
Matrice& operator*(Matrice&);
Matrice& operator/(Matrice&);
Matrice& Trasposta(void);
Matrice& Inversa(void);
};

/*definisco il costruttore*/
template <class T, int R, int C> Matrice<T,R,C>::Matrice(void)
{
Righe = R; //Righe ha la stesso valore di R
Colonne = C; //Colonne ha lo stesso valore di C
TMP = 0;
Zero(); //richiamo la funzione Zero() che inizializza gli elementi di mat a 0
}

/*definisco il distruttore*/
template <class T, int R, int C> Matrice<T,R,C>::~Matrice(void)
{
//se TMP punta a qualcosa
if(TMP != 0) {
//libero la memoria
delete TMP;
TMP = 0;
}
}

/*definisco il metodo SonoQuadrata() che ritorna vero se Righe e Colonne sono uguali e falso altrimenti*/
template <class T, int R, int C> int Matrice<T,R,C>::SonoQuadrata(void)
{
if(R == C) return(1);
return(0);
}

/*definisco il metodo Zero() che inizializza mat a zero*/
template <class T, int R, int C> void Matrice<T,R,C>::Zero(void)
{
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
mat[i][j] = (T)0;
}

/*definisco il metodo SonoZero() che restituisce falso al primo elemento non nullo che trova e vero altrimenti*/
template <class T, int R, int C> int Matrice<T,R,C>::SonoZero(void)
{
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
if(mat[i][j] != (T)0) return(0);

return(1);
}

/*definisco il metodo MettiValori per la matrice*/
template <class T, int R, int C> void Matrice<T,R,C>::MettiValori(int r, int c, T V)
{
mat[r][c] = V;
}

/*definisco l'operatore di assegnamento = per matrici*/
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::operator=(Matrice& MI)
{
//la dimensione delle due matrici deve essere la stessa altrimenti non posso operare
if(MI.Righe != Righe || MI.Colonne != Colonne)
{
throw 1;
} else {
//se la dimensione è la stessa posso assegnare il valore degli elementi a MI scorrendo gli elementi uno per uno
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
MI.mat[i][j] = (T) mat[i][j];
}
return *this;
}

/*definisco l'operatore ==*/
template <class T, int R, int C> int Matrice<T,R,C>::operator==(Matrice& MI)
{
//se il numero di righe o di colonne non sono uguali le matrici non sono uguali
if(MI.Righe != Righe || MI.Colonne != Colonne)
{
return (0);
//se invece sono della stessa dimensione vado a controllare gli elementi
} else {
//se ciclando trovo un elemento diverso fra le due matrici l'if è verificato e si esce
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
if(MI.mat[i][j] != (T) mat[i][j])
return (0);
}
//se arrivo alla fine del for, cioè se l'if non si verifica mai, arrivo alla prossima istruzione, cioè le matrici sono uguali
return (1);
}

/*definisco l'operatore !=*/
template <class T, int R, int C> int Matrice<T,R,C>::operator!=(Matrice& MI)
{
//se il numero di righe o di colonne sono diversi le matrici sono diverse
if(MI.Righe != Righe || MI.Colonne != Colonne)
{
return (1);
//se invece sono della stessa dimensione vado a controllare gli elementi
} else {
//se ciclando trovo un elemento diverso fra le due matrici l'if è verificato e si esce
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
if(MI.mat[i][j] != (T) mat[i][j])
return (1);
}
//se arrivo alla fine del for, cioè se l'if non si verifica mai, arrivo alla prossima istruzione, cioè le matrici sono uguali
return (0);
}


/*definisco l'operatore +, (una funzione di overloading di operatore può prendere in input due parametri che corrispondono ai due operandi sui quali si opera, si pensi

ad esempio agli operatori aritmetici. Se come in questo caso, l'overloading avviene tramite funzione membro, *this (l'oggetto chiamante) è considerato primo parametro

implicito dell'operatore per cui queste funzioni di sovraccarico possono accettare solo un parametro. Ovvero quando scriverò matrice1+matrice2, matrice1 è l'oggetto

chiamante. matrice1+matrice2 equivale a matrice1.operator+(matrice2) )*/
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::operator+(Matrice& MI)
{
//la dimensione delle due matrici deve essere la stessa altrimenti non posso operare
if(MI.Righe != Righe || MI.Colonne != Colonne)
{
throw 1;
} else {
//se la dimensione è la stessa posso operare, quindi se TMP punta a qualcosa
if(TMP != 0)
{
//libero la memoria
delete TMP;
//alloco nuovo spazio per contenere un oggetto di Matrice
TMP = new Matrice();
}
//e effettuo la sottrazione, elemento per elemento, tra le due matrici
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
//infine salvo la nuova matrice-somma in mat di TMP
TMP->mat[i][j] = (T) mat[i][j] + MI.mat[i][j];
}
}

/*definisco l'operatore -, anche qui il primo parametro è implicito*/
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::operator-(Matrice& MI)
{
//la dimensione delle due matrici deve essere la stessa altrimenti non posso operare
if(MI.Righe != Righe || MI.Colonne != Colonne)
{
throw 1;
} else {
//se la dimensione è la stessa posso operare, quindi se TMP punta a qualcosa
if(TMP != 0)
{
//libero la memoria
delete TMP;
//alloco nuovo spazio per contenere un oggetto di Matrice
TMP = new Matrice();
}
//e effettuo la sottrazione, elemento per elemento, tra le due matrici
for(int i=0; i < R ; i++)
for(int j=0; j < C; j++)
//infine salvo la nuova matrice-differenza in mat di TMP
TMP->mat[i][j] = (T) mat[i][j] - MI.mat[i][j];
}
}

/*definisco l'operatore *, anche qui il primo parametro è implicito */
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::operator*(Matrice& MI)
{
//la dimensione delle colonne della prima matrice deve essere uguale alla dimensione delle righe della seconda altrimenti non posso operare
if(MI.Righe != Colonne)
{
throw 2;
} else {
//se la dimensione è la stessa posso operare, quindi se TMP punta a qualcosa
if(TMP != 0)
{
//libero la memoria
delete TMP;
//alloco nuovo spazio per contenere un oggetto di Matrice
TMP = new Matrice();
}
//mi servono 3 for, uno che mi si sposta sulle righe della prima matrice
for(int i=0; i < R ; i++)
//uno che mi si sposta sulle colonne della seconda matrice
for(int j=0; j < MI.C ; j++)
{
//e l'ultimo per effettuare il prodotto elemento per elemento fra riga delle prima matrice e colonna della seconda
T somma = (T) 0;
for(int k=0; k < C ; k++)
{
somma = somma + (T) mat[i][k] * MI.mat[k][j];
}
//alla fine di ogni ciclo dell'ultimo for salvo i dati su mat di TMP
TMP->mat[i][j] = somma;
}
}
}

/*definisco la funzione trasposta*/
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::Trasposta(void)
{
if(TMP != 0)
{
//libero la memoria
delete TMP;
//alloco nuovo spazio per contenere un oggetto di Matrice
TMP = new Matrice();
}
//scorro elemento per elemento la matrice in input e li salvo in mat di TMP trasponendoli
for(int i=0; i < R ; i++)
for(int j=0; j < C ; j++)
TMP->mat[j][i] = (T) mat[i][j];
}

/*definisco la funzione inversa*/
template <class T, int R, int C> Matrice<T,R,C>& Matrice<T,R,C>::Inversa(void)
{
//se la matrice non è quadrata o il determinante è nullo non posso calcolare l'inversa
if( (!(this.SonoQuadrata())) || ( (int)this.Det() == 0 )
throw 3;
else
{

Loading