Problem mit Templates und einer Rekursion...
-
Habe vor acht Tagen die Aufgabe bekommen, in etwa folgendes zu programmieren (als eine von zwei Aufgaben):
/* Name: Matrix Copyright: nope Author: Christian Wenzel Date: 05.05.04 12:22 Description: Template für Matrizen Bearbeitung der zweiten Aufgabe des ersten Zettels */ #include <iostream> #include <cstdlib> #include <math.h> template <class T, int S, int Z> class Matrix; // sichtbar machen für die Skalare template <class T> class Skalar{ private: T value; // Wert des Skalars public: /** Konstruktor */ inline Skalar(T v): value(v){}; /** weist zufälligen Integerwert zwischen 1 und 5 zu */ inline void init(){value = rand()%5+1;}; /** liefert Kopie des gespeicherten Wert */ inline T get_Value(){return T(value);}; /** Ausgabe des Werts*/ inline void print(){std::cout << value << std::endl;}; /** Zuweisen eines Skalars */ inline void operator= (const Skalar<T> & a){value = T(a.value);} //Copy-Konstruktor aufrufen }; // Definition der Klasse Matrix template <class T, int S, int Z> // S für Spalten und Z für Zeilen class Matrix{ template <class A, int B, int C> friend class Matrix; // für Transponierung und Matrixmul wichtig private: T entry[S][Z]; // erster Index gibt Spalte, zweiter Zeile int spalten; int zeilen; public: /** Konstruktor*/ inline Matrix(): spalten(S), zeilen(Z){}; /** initialisieren der Matrix mit Zufalls-Ints*/ inline void init() { for (int i=0;i < S;i++) for (int j=0;j < Z;j++) entry[i][j] = rand()%5; } /** gibt Matrix aus*/ inline void print() { for (int j=0;j < Z;j++) { for (int i=0;i < S;i++) std::cout << entry[i][j] << " "; std::cout << std::endl; } } /** Zuweisung einer Matrix*/ void operator= (const Matrix<T,S,Z> &); /** Hilfsmethode, gibt das Skalarprodukt des i-ten Zeilenvektors * der aufrufenden Matrix und dem j-ten Spaltenvektors der zweiten * Matrix zurück*/ T skal_mul(Matrix<T,Z,S> &, int i, int j); /** Addition einer Matrix, Ergebnis zurückgeben*/ Matrix <T,S,Z> operator+ (const Matrix<T,S,Z> &) const; /** Addition einer Matrix, Ergebnis in Matrix ablegen*/ void operator+= (const Matrix<T,S,Z> &); /** Subtraktion einer Matrix, Ergebnis zurückgeben*/ Matrix <T,S,Z> operator- (const Matrix<T,S,Z> &) const; /** Subtraktion einer Matrix, Ergebnis in Matrix ablegen*/ void operator-= (const Matrix<T,S,Z> &); /** Multiplikation einer Matrix, Ergebnis zurückgeben*/ Matrix <T,Z,Z> operator* (Matrix<T,Z,S> &); /** Matrixmultiplikation, Ergebnis wird aufrufender Matrix * zugewiesen; beide Matrizen müssen hierfür quadratisch sein*/ void operator*= (Matrix<T,S,S> &); /** Multiplikation einer Matrix mit einem Skalar*/ Matrix <T,S,Z> operator* (Skalar<T> &) const; /** Multiplikation einer Matrix mit einem Skalar * Ergebnis sich selbst zuweisend*/ void operator*= (Skalar<T> &); /*versuch*/ T rekdet(T ** array, int size); /** liefert die Transponierte der aufrufenden Matrix zurück*/ Matrix <T,Z,S> trans() const; /** transponiert die aufrufende Matrix, * nur für quadratische Matrizen*/ void trans_this(); /** berechnet die Frobenius-Norm der aufrufenden Matrix*/ double norm() const; /** berechnet die Determinante der aufrufenden Matrix*/ T det(); }; /** berechnet rekursiv die Determinante des übergebenen 2-dimensionalen Arrays*/ template <class T, int S, int Z> T Matrix<T,S,Z>::rekdet(T ** array, int size) { if (size==1) return array[0][0]; T ** tmp = new T[size-1][size-1]; T ret; for (int i=0;i < size-1;i++)// Laplace-Entwicklung nach der ersten (nullten) Zeile { for (int j=0;j < size-1;j++)// rüberkopieren der Werte { // bilden der Untermatrix for(int k=0;k < size-1;k++) { if (j<i) // bin VOR i-ter Spalte tmp[j][k] = array[j][k+1]; // erste Zeile wird ausgelassen if (j>i) // bin HINTER i-ter Spalte tmp[j][k] = array[j+1][k+1]; } } if (i==0) ret = array[0][0]*rekdet(tmp,size-1); if ((i%2==0)&&(i!=0)) ret += array[i][0]*rekdet(tmp, size-1); // gerade wird addiert else ret -= array[i][0]*rekdet(tmp, size-1); // ungerade wird subtrahiert } delete ** tmp; delete * tmp; delete tmp; return ret; }; // Implementierung des Skalarprodukts template <class T, int S, int Z> T Matrix<T,S,Z>::skal_mul(Matrix<T,Z,S> & B, int i, int j) { T ret; ret = entry[0][i]*B.entry[j][0]; for (int k=1;k < S;k++) ret += entry[k][i]*B.entry[j][k]; return ret; } // Implementierung des + Operators template <class T, int S, int Z> Matrix<T,S,Z> Matrix<T,S,Z>::operator+ (const Matrix<T,S,Z> & a) const { Matrix <T,S,Z> ret; for (int i=0;i < S;i++) { for (int j=0;j < Z;j++) ret.entry[i][j] = entry[i][j] + a.entry [i][j]; } return ret; } // Implementierung des += Operators template <class T, int S, int Z> void Matrix<T,S,Z>::operator+= (const Matrix<T,S,Z> & a) { *this = *this + a; } // Implementierung des Zuweisungsoperators für Matrix template <class T, int S, int Z> void Matrix<T,S,Z>::operator= (const Matrix<T,S,Z> & a) { for (int i=0;i < S;i++) for (int j=0;j < Z;j++) entry[i][j] = T(a.entry[i][j]); // Copy-Konstruktor } // Implementierung des - Operators template <class T, int S, int Z> Matrix<T,S,Z> Matrix<T,S,Z>::operator- (const Matrix<T,S,Z> & a) const { Matrix <T,S,Z> ret; for (int i=0;i < S;i++) { for (int j=0;j < Z;j++) ret.entry[i][j] = entry[i][j] - a.entry [i][j]; } return ret; } // Implementierung des -= Operators template <class T, int S, int Z> void Matrix<T,S,Z>::operator-= (const Matrix<T,S,Z> & a) { *this = *this - a; } // Implementierung der Matrixmultiplikation template <class T, int S, int Z> Matrix<T,Z,Z> Matrix<T,S,Z>::operator* (Matrix<T,Z,S> & a) { Matrix <T,Z,Z> ret; for (int i=0;i < Z;i++) for (int j=0;j < Z;j++) // für jeden Eintrag der Ergebnismatrix mache: { ret.entry[i][j] = skal_mul(a, j, i); } return ret; } // Implementierung der Matrixmultiplikation, wobei Ergebnis // der aufrufenden Matrix zugewiesen wird template <class T, int S, int Z> void Matrix<T,S,Z>::operator*= (Matrix<T,S,S> & A) { *this = *this * A; } // Implementierung der Multiplikation eines Skalars mit einer Matrix template <class T, int S, int Z> Matrix<T,S,Z> Matrix<T,S,Z>::operator* (Skalar<T> & a) const { Matrix<T,S,Z> ret; for (int i=0;i < S;i++) for (int j=0;j < Z;j++) { ret.entry[i][j] = entry[i][j] * a.get_Value(); } return ret; } // Implementierung der Multiplikation eines Skalars mit einer Matrix // Ergebnis wird der Matrix selbst zugewiesen template <class T, int S, int Z> void Matrix<T,S,Z>::operator*= (Skalar<T> & a) { *this = *this * a; } // Implementierung der Transponierung einer quadratische Matrix // Ergebnis wird als neue Matrix zurück gegeben template <class T, int S, int Z> Matrix <T,Z,S> Matrix<T,S,Z>::trans()const { Matrix<T,Z,S> ret; for (int i=0;i < S;i++) for (int j=0;j < Z;j++) ret.entry[j][i] = entry [i][j]; return ret; } // Implementierung der Transponierung der aufrufenden Matrix template <class T, int S, int Z> void Matrix<T,S,Z>::trans_this() { if (S==Z) *this = trans(); } // Implementierung der Norm template <class T, int S, int Z> double Matrix<T,S,Z>::norm()const { double ret = (double)entry[0][0]*(double)entry[0][0]; for (int i=1;i < S;i++) for (int j=1;j < Z;j++) ret+= (double)entry[i][j]*(double)entry[i][j]; ret = sqrt(ret); return ret; } // Implementierung dee Determinantenaufrufs template <class T, int S, int Z> T Matrix<T,S,Z>::det() { if (S==Z) { return rekdet (entry, S); } std::cout << "Matrix nicht quadratisch!" << std::endl; }; int main() { int z; typedef Skalar<int> mysc; typedef Matrix<int,2,2> myma; myma m1; m1.init(); m1.print(); std::cout << std::endl; std::cout << m1.det(); std::cin >> z; return 0; }
Nunja, das Problem ist nun, daß ich folgende Fehlermeldungen nicht los werde:
-I"F:\Programmierung\C++\Dev-Cpp\include" -L"F:\Programmierung\C++\Dev-Cpp\lib"
G:/Quellcode/Matrix.cpp: In member functionT Matrix<T, S, Z>::det() [with T = int, int S = 2, int Z = 2]': G:/Quellcode/Matrix.cpp:403: instantiated from here G:/Quellcode/Matrix.cpp:352: no matching function for call to
Matrix<int, 2,
2>::rekdet(int[2][2], int)'
G:/Quellcode/Matrix.cpp:161: candidates are: T Matrix<T, S, Z>::rekdet(T**,
int) [with T = int, int S = 2, int Z = 2]Ausführung beendet
Da ich bis vor acht Tagen C++ nur vom Hörensagen her kannte, bin ich mit den Compilermeldungen und den Feinheiten noch nicht so vertraut.
Bis auf die Determinantenberechnung funzt alles, aber daran beiße ich mir echt die Zähne aus
Wär echt dufte, wenn mir einer sagen kann, woran es liegt, und evtl wie ich dafür sorgen kann, daß es funktioniert.Bis dann denn!
McTrevor
-
template <class T, int S, int Z> // S für Spalten und Z für Zeilen class Matrix{ template <class A, int B, int C> friend class Matrix; // für Transponierung und Matrixmul wichtig private: T entry[S][Z]; // erster Index gibt Spalte, zweiter Zeile int spalten; int zeilen; public: T rekdet(T ** array, int size); T det(); }; template <class T, int S, int Z> T Matrix<T,S,Z>::rekdet(T ** array, int size) { if (size==1) return array[0][0]; T ** tmp = new T[size-1][size-1]; T ret; for (int i=0;i < size-1;i++)// Laplace-Entwicklung nach der ersten (nullten) Zeile { for (int j=0;j < size-1;j++)// rüberkopieren der Werte { // bilden der Untermatrix for(int k=0;k < size-1;k++) { if (j<i) // bin VOR i-ter Spalte tmp[j][k] = array[j][k+1]; // erste Zeile wird ausgelassen if (j>i) // bin HINTER i-ter Spalte tmp[j][k] = array[j+1][k+1]; } } if (i==0) ret = array[0][0]*rekdet(tmp,size-1); if ((i%2==0)&&(i!=0)) ret += array[i][0]*rekdet(tmp, size-1); // gerade wird addiert else ret -= array[i][0]*rekdet(tmp, size-1); // ungerade wird subtrahiert } delete ** tmp; delete * tmp; delete tmp; return ret; }; template <class T, int S, int Z> T Matrix<T,S,Z>::det() { if (S==Z) { return rekdet (entry, S); } std::cout << "Matrix nicht quadratisch!" << std::endl; }; int main() { int z; typedef Skalar<int> mysc; typedef Matrix<int,2,2> myma; myma m1; m1.init(); m1.print(); std::cout << std::endl; std::cout << m1.det(); std::cin >> z; return 0; }
Kommt schon.... da muss doch einer den Fehler finden
Hier nochmla die Fehlermeldung:
Compiler: Default compiler
Führt g++.exe... aus
g++.exe "G:\Quellcode\Matrix.cpp" -o "G:\Quellcode\Matrix.exe" -I"F:\Programmierung\C++\Dev-Cpp\include\c++" -I"F:\Programmierung\C++\Dev-Cpp\include\c++\mingw32" -I"F:\Programmierung\C++\Dev-Cpp\include\c++\backward" -I"F:\Programmierung\C++\Dev-Cpp\include" -L"F:\Programmierung\C++\Dev-Cpp\lib"
G:/Quellcode/Matrix.cpp: In member functionT Matrix<T, S, Z>::det() [with T = int, int S = 2, int Z = 2]': G:/Quellcode/Matrix.cpp:403: instantiated from here G:/Quellcode/Matrix.cpp:352: no matching function for call to
Matrix<int, 2,
2>::rekdet(int[2][2], int)'
G:/Quellcode/Matrix.cpp:161: candidates are: T Matrix<T, S, Z>::rekdet(T**,
int) [with T = int, int S = 2, int Z = 2]Ausführung beendet
Bis dann denn!
McTrevor
-
hey McTrevor, das kann man doch wohl noch weiter reduzieren. Zieh alles raus, solange bis die Fehlermeldung noch kommt.
-
#include <iostream> #include <cstdlib> #include <math.h> template <class T, int S, int Z> // S für Spalten und Z für Zeilen class Matrix{ template <class A, int B, int C> friend class Matrix; // für Transponierung und Matrixmul wichtig private: T entry[S][Z]; // erster Index gibt Spalte, zweiter Zeile int spalten; int zeilen; public: T rekdet(T ** array, int size); T det(); }; template <class T, int S, int Z> T Matrix<T,S,Z>::rekdet(T ** array, int size) { if (size==1) return array[0][0]; T ** tmp = new T[size-1][size-1]; return rekdet(tmp, size-1); }; template <class T, int S, int Z> T Matrix<T,S,Z>::det() { if (S==Z) { return rekdet (entry, S); } std::cout << "Matrix nicht quadratisch!" << std::endl; }; int main() { int z; typedef Matrix<int,2,2> myma; myma m1; std::cout << std::endl; std::cout << m1.det(); std::cin >> z; return 0; }
wohlgemerkt macht diese Programmfragment jetzt nichts sinnvolles mehr und läßt sich mit derselben Fehlermeldung wie oben nicht kompilieren.
Bis dann denn!
McTrevor
-
Ich glaube so ist es minimaler. Ob die Rekursion drin ist oder nicht ist doch egal.
#include <iostream> template <class T, int S, int Z> class Matrix { public: T entry[S][Z]; void rekdet(T** array) { } }; int main() { Matrix<int,2,2> m1; m1.rekdet(m1.entry); }
-
ich glaube hier solltest du die lösung finden:
-
ist der Funktionsaufruf und die Übergabe des 2-dimensionalen arrays.
Bis dann denn!
McTrevor
-
was hat der compiler hieran zu meckern?
template <class T, int S, int Z> T Matrix<T,S,Z>::det() { if (S==Z) { T ** tmp = new *T[S]; //parse error before `*' token for (int i=0;i < S;i++) tmp[i] = new T[S]; for (int i=0;i < S;i++) for (int j=0;j < S;j++) tmp[i][j] = T(entry[i][j]); T ret = rekdet (tmp, S); for (int i=0;i < S;i++) delete tmp[i]; delete [] tmp; return rekdet (tmp, S); } std::cout << "Matrix nicht quadratisch!" << std::endl; };
so langsam bin ich mit den Nerven am Ende... Hilfe
Bis dann denn!
McTrevor
-
T ** tmp = new *T[S];
wird zu
T** tmp = new T* [ S ];
was auch immer
-
Danke!!!
das wars... jetzt muss ich nur noch rausfinden, warum die Funktion nicht das macht, was sie soll...Bis dann denn!
McTrevor