Mehrdimensionale Arrays; dynamischer Speicher;



  • Hallo Leute,

    ich soll eine Klasse implementieren, die ein (MxN)-Matrix modelliert. Die Matrixelemente sollen im dynamischen Speicher abgelegt werden.

    Das UML-Klassendiagramm, den Konstruktor und manche Methoden konnte ich implementieren. Ich scheitere momentan an dieser Methode :

    bool setElementAt(int m,int n,double value)
    

    Setzt das Matrixelement an der angegebenen Zeile und Spalte auf einen neuen Wert.
    (Dazu soll ich die Methode

    getArrayIndex(int m, int n)
    

    benutzen).

    Ich bekomme andauernd folgende Fehlermeldung :

    -extended initializer only available...
    -invalid types...

    Zu den Attributen der Klasse:

    int m_rows, m_cols, m_size;
    double* m_pArray;
    

    //Konstruktor :

    CMatrix::CMatrix(int M, int N)
    {
       if(M && N ==0) 
       {
         m_rows =2; m_cols=2;
       }
       else 
         m_rows = M; m_cols=N; m_size = m_rows*m_cols;
    
         m_pArray = new double [m_size];
    

    //Destruktor:

    CMatrix::~Matrix()
    delete [] m_pArray;
    

    //getArrayIndex

    int CMatrix::getArrayIndex(int m ,int n)
    {
       double i=0;
       if(//zusicherungen)
       {
         i=(m-1)*n+n-1; return i;
       }
       else if(//zusicherungen)
       {
         return -1;
       } 
        return 0;
    

    //setElementAt

    bool CMatrix::setElementAt(int m, int n, double value)
    {
        double index = getArrayIndex(m,n);
        if(//zusicherung)
        {
           return false;
        }
        else
           m_pArray[index] = {value}; return true; //Fehler
    

    Ich hoffe ich konnte mein Problem gut schildern ­čśĽ falls noch fragen sind, kann ich vllt ein Bild hochladen oder so :S..Vielen Dank schonmal !



  • In deiner getArrayIndex warum ist i von Typ double? Du gibst ein int zur├╝ck.
    Bei setElementAt index ist ein double aber getArrayIndex gibt ein int zur├╝ck.
    "m_pArray[index]" index ist vom Typ double.
    Solltes auf das Problem jetzt selber kommen ­čśâ



  • ­čÖä ups xD

    okay ich hab jetzt folgendes:

    int index = getArrayIndex(m,n);
    

    jetzt wird

    m_pArray[index]={value};
    

    gelbfarbig,
    der Compiler schreibt :

    - warning: extended initalizer lists only available with -std=c++0x or -std=gnu++0x[enabled by default]

    liegt es daran das

    index
    

    variabel ist?

    Ich danke dir schonmal sehr ­čÖé



  • Also hier sind ein paar komische Sachen im Code

    if(M && N ==0)
    

    Du willst sicher ausdr├╝cken "Wenn M und N null sind":

    if(M == 0 && N == 0)
    

    Per impliziter Konvertierung von int nach bool funktioniert das sicher, was ist aber, wenn du auf einen anderen Wert pr├╝fen willst? Dann geht das nicht mehr. Besser immer richtig schreiben.

    Aber: Warum pr├╝ftst du ├╝berhaupt auf 0 und gibst den Variablen Standardwerte? Warum nicht gleich Default-Parameter und eine Exception bei m<=0 && n<=0?

    CMatrix::~Matrix()
    delete [] m_pArray;
    

    Bei Schleifen und if kannst du zwar die geschweiften Klammern weglassen, aber bei Funktionen geht das nicht.

    Anonymous123 hat ja schon einen Fehler geschrieben:

    double i=0;
    

    Deine Daten sind zwar doubles, der Index aber nicht. Ein sinnvoller Datentype w├Ąre beispielsweise std::size_t. Den musst du dann auch als R├╝ckgabetyp von getArrayIndex angeben.

    W├Ąhrend dem Schreiben ist noch eine Antwort reingekommen:

    m_pArray[index]={value};
    

    Wieso hast du die geschweiften Klammern? Mach die weg, dann sollte es klappen



  • Okay, stimmt statt

    if(M && N ==0)
    

    kann/sollte ich schreiben:

    if (m<=0 && n<=0)
    

    Laut dem UML-Klassendiagramm wird m_rows und m_cols mit 2 initialisiert.
    Ich dachte, dass ich das im Konstruktor definieren muss.

    Oh, tut mir leid, in Wirklichkeit gibt es diese Klammer :S.

    Ich habe leider nicht so einen gro├čen Spielraum.
    Das ist eine Aufgabe von der Uni und ich muss mich an das Klassendiagramm halten :/. size_t kenne ich noch gar nicht, f├╝r was steht dieser Datentyp?

    Mh, irgendwie dachte ich die geh├Âren dahin, hast recht ohne die Klammern funktionierts ­čÖé

    Ich schau mal ob noch weitere Probleme auftreten, ich muss das Projekt eh heute noch fertigstellen, also bitte den Thread nicht schlie├čen.

    Vielen Dank f├╝r Eure hilfe ­čÖé



  • ...



  • CMatrix(int M = 2, int N = 2)
    

    Wenn nichts angegeben, sollen M und N 2 sein. (Beachte: Kein CMatrix:: davor, das muss n├Ąmlich in die Klassendefinition)



  • Okay, hab ich so ├╝bernommen patrick246 ­čśë

    Ich sa├č noch bis sp├Ąt Abends an meinem Programm.
    Bei meinem Programm stimmt nur ne Kleinigkeit noch nicht.

    In der main habe ich folgende Schleife :

    int M, N;
    	M = 4; N = 3;
    	matrix.getDimension(M,N);
    	int m =1;
    	int v =0;
    
    	for(int n=1; m<=M ;n++)
    	{
    		matrix.setElementAt(m,n,v);
    		abs(v);
    		v++;
    
    		if (v % 2 != 0) {v = v *-1;}
    
    		if(n==N)
    		{
    			n = 0; m++;
    		}
    
    	}
    

    Eigentlich soll ich ein Matrix-Feld von :

    0 -1 2
    -3 4 -5
    6 -7 8
    -9 10 -11

    aufbauen. Raus kommt jedoch :

    0 -1 0
    -1 -1 -1
    0 -1 0
    -1 0 -1

    und ich wei├č einfach nicht wieso ­čśĽ

    An setElementAt hat sich nichts ver├Ąndert ­čś×

    Ich Danke euch f├╝r Eure Hilfe ­čśĽ



  • 1. Was macht getDimension? Dem Namen nach sollte sie die Dimensionen der Matrix zur├╝ckgeben, stattdessen nimmt sie Werte entgegen.

    2. Eine NxM-Matrix kannst du mit folgender Schleife durchlaufen, angenommen die erste Position ist (0|0) und die letzte Position ist (N-1|M-1):

    int counter = 0;
    for(int n = 0; n < N; ++n)
    {
        for(int m = 0; m < M; ++m)
        {
            if((counter % 2) == 0)
                matrix.setElementAt(n, m, counter);
            else
                matrix.setElementAt(n, m, -counter);
        }
    }
    

    3. getArrayIndex

    std::size_t getArrayIndex(std::size_t y, std::size_t x)
    {
        return y * m_breite + x;
    }
    

    4. setElementAt

    void setElementAt(std::size_t y, std::size_t x, double value)
    {
        m_data[getArrayIndex(y,x)] = value;
    }
    

    Stimmen die letzten beiden ungef├Ąhr mit deinem Code ├╝berein?



  • Quadknick schrieb:

    CMatrix::CMatrix(int M, int N)
    {
       if(M && N ==0) 
       {
         m_rows =2; m_cols=2;
       }
       else 
         m_rows = M; m_cols=N; m_size = m_rows*m_cols;
    
         m_pArray = new double [m_size];
    

    der else Zweig sieht auch sehr ungesund aus



  • int CMatrix::getArrayIndex(int m ,int n)
    {
       double i=0;
       if(//zusicherungen)
       {
         i=(m-1)*n+n-1; return i; // <====== *n muss *m_cols heissen!
       }
       else if(//zusicherungen)
       {
         return -1;
       } 
        return 0;
    

    Und 1-basierte Indexe sind selten ne gute Idee.



  • Hey Leute,

    ich war am Dienstag im Labor und da haben wir den Fehler schnell gefunden.
    Hustbaer du hast recht! n muss m_cols heissen.

    Desweiteren habe ich die main-Schleife folgendermassen umprogrammiert :

    int z=1; int v=0; int M,N; M=4, N =3;
    matrix.getDimension(M,N);
    for(int m=1; m<M; m++)
    {
       for(int n=1;n<=N;n++)
       {
          matrix.setElementat(m,n,z*v);
          v++;
          z *= -1; 
       }
    }
    
    matrix.print();
    

    Nun habe ich wie folgt ein neues Problem.
    Wir sollten der CMatrix Klasse weitere Methoden hinzuf├╝gen
    und dabei

    enum
    

    benutzen.

    enum INI_MODE{INIT_ZEROS, INIT_UNIT,INIT_RAND}
    

    Die zugef├╝gten Methoden lauten :

    CMatrix(int dm, INI_MODE mode = INIT_ZEROS);
    void operator *= (float rop);
    CMatrix& operator = (const CMatrix& rop)const;
    CMatrix operator + (const CMatrix& rop)const;
    CMatrix operator * (const CMatrix& rop)const;
    friend ostream& operator << (ostream& lop, const CMatrix& rop);
    

    Ich habe schon einige implementiert und h├Ąnge nun bei dem Zuweisungsoperator ­čśĽ

    Daf├╝r sollten wir uns an ein Aktivit├Ątsdiagramm halten :

    ..............................Start :

    [Speichergr├Â├če der
    Operanden stimmt nicht......(Anzeige einer Meldung)
    ├╝berein]....................(Freigeben des alten Speicherplatzes)
    ............................(Allokieren von Speicher der Gr├Â├če des
    .............................rechten Operanden)
    ............................(aktualisieren des Attributs der Speichergr├Â├če)

    [Speichergr├Â├če der
    Operanden stimmt............(if schleife erf├╝llt)
    ├╝berein]

    [Anzahl von Zeilen oder
    Spalten stimmt nicht bei.....(aktualisieren der Attribute f├╝r
    beiden Operanden ├╝berein]....Zeilen - und Spaltenzahl)

    [Anzahl von Zeilen oder
    Spalten stimmt nicht bei.....(if Schleife erf├╝llt)
    beiden Operanden ├╝berein]

    .............................(Kopieren der Matrix-Elemente
    .............................des rechten Operanden in das Array
    .............................des linken Operanden)
    .............................(Der linke Operand gibt sich selbst zur├╝ck)

    ............................ Ende:

    Mein Code sind folgenderma├čen aus :

    CMatrix& CMatrix ::operator = (const CMatrix& rop)const
    {
    	int m_cols2 = rop.m_cols;
    	int m_rows2 = rop.m_rows;
    	int m_size2 = m_cols2 * m_rows2;
    
    	double* m_Array;
    	m_Array = new double [m_size2];
    
    	if (m_size2 == rop.m_size)
    	{
    		if (m_cols2 == rop.m_cols && m_rows2 == rop.m_rows)
    		{
    			int v = rop.getArrayIndex(rop.m_rows, rop.m_cols);
    			int z = rop.getArrayIndex(m_rows2, m_cols2);
    
    				for(int m = 1; m<=rop.m_rows; m++)
    				{
    					for(int n=1; n<=rop.m_cols ;n++)
    					{
    						m_pArray[v] = m_Array[z];
    
    					}
    
    				}
    
    		}
    
    	}
    	else if (m_size2 != rop.m_size )
    	{
    		cout << "veraendere Groesse der Matrix!"<<endl;
    		delete [] m_Array;
    		m_Array = new double [rop.m_size];
    
    		if (m_cols2 != rop.m_cols && m_rows2 != rop.m_rows)
    		{
    			m_cols2 = rop.m_cols;
    			m_rows2 = rop.m_rows;
    
    			int v = rop.getArrayIndex(rop.m_rows, rop.m_cols);
    			int z = rop.getArrayIndex(m_rows2, m_cols2);
    
    			for(int m = 1; m<=rop.m_rows; m++)
    			{
    				for(int n=1; n<=rop.m_cols ;n++)
    				{
    
    					m_pArray[v] = m_Array[z];
    				}
    
    			}
    		}
    
    	}
    
    }
    

    Ich glaube ich hab ein Problem mit der Vorstellung welcher operand rechts und welcher Links steht ­čśĽ das im Parameter ├╝bergebene Objekt ist das der rechte
    oder der Linke Operand? ­čśĽ
    Zu dem erhalte ich den Fehler no return..aber einen der Zeiger zur├╝ckzugeben funktioniert nicht :S

    wei├č jemand einen Rat?

    Vielen Dank und tut mir leid, dass ich wieder mit was neuem beginne :S



  • // links |   rechts
       x     +     y;
       x.operator+(y); // Die obere Variante ist nur die faule, sch├Ânere Schreibweise.
    

    Offensichtlich ist der Operand rechts vom Operator der Parameter. Und der Operand links vom Operator ist das Objekt, das ver├Ąndert wird. ­čśë

    Logischerweise willst du das ver├Ąnderte Objekt zur├╝ckgeben, f├╝r den Fall, dass andere Funktionen sofort mit dem ver├Ąnderten Objekt weiterarbeiten k├Ânnen, also return *this;



  • + als Operator zu w├Ąhlen, war nat├╝rlich doof. Denk dir einfach = statt + in meinem Beispiel. ­čśâ


Log in to reply