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 function T 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 toMatrix<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 function T 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 toMatrix<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:

    http://www.c-plusplus.net/forum/viewtopic.php?t=58906



  • 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


Anmelden zum Antworten