0

In the code example I have described with comments my problem. I want to transpose a matrix from the method transpos(). This works but I have no idea how to pass the transposed matrix to the original object. The transposed matrix exists only in the method.

#include <iostream>
#include <string.h>
using namespace std;

class Matrix
{
private:
    int Zeile, Spalte;
    double** werte;

public:
    Matrix();
    Matrix(int zeilen, int spalten);
    ~Matrix();
    Matrix(const Matrix& m);                  // Copy-Konstruktór
    int setze_element(int zeile, int spalte, double Wert_setzen);
    Matrix transpos();
    friend ostream& operator << (ostream& stream, Matrix& m);
    Matrix operator = (const Matrix& m);    // Zuweisungsoperator assignment operator
};

Matrix Matrix::operator= (const Matrix& M) // assigment
{
    werte = M.werte;
    return *this;
}

Matrix::Matrix(const Matrix& M) //Copy
{
    Zeile = M.Zeile;
    Spalte = M.Spalte;
    werte = M.werte;
}

Matrix::Matrix(int zeilen, int spalten)
{
    this->Spalte = spalten;
    this->Zeile = zeilen;

    werte = new double* [Spalte];
    for (int r = 0; r < Zeile; r++)
    {
        werte[r - 1] = new double[Spalte];
    }

    double init_mit = 0;

    for (int r = 0; r < Zeile; r++)
    {
        for (int c = 0; c < Spalte; c++)
        {
            //cout << "Enter ..."; //cin >> d;
            werte[r - 1][c - 1] = init_mit;
            cout << werte[r - 1][c - 1] << "\t";
        }
        cout << endl;
    }
}

Matrix::Matrix()
{
    Zeile = Spalte = 0;
    werte = NULL;       //Null-pointer
}

Matrix::~Matrix()
{
}

int Matrix::setze_element(int zeile, int spalte, double Wert_setzen)
{
    this->Zeile;
    this->Spalte;

    if (zeile < this->Zeile && spalte < this->Spalte)
    {
        werte[zeile - 1][spalte - 1] = Wert_setzen;
        return 1;
    }
    else
    {
        cout << "Wert Ausserhalb der Matrix. Abbruch!" << endl;
        return 0;
    }
}

Matrix Matrix::transpos()   // r = row = zeile / c = col = Spalte
{
    int MT_zeile, MT_spalte = 0;
    MT_zeile = Spalte;
    MT_spalte = Zeile;
    cout << "Shows transpose Matrix by default." << endl;
    Matrix MT(MT_zeile, MT_spalte);         // init the new Matrix(3/5)  original matrix is (5/3)


    for (int r = 0; r < Zeile; r++)
    {
        for (int c = 0; c < Spalte; c++)
        {
            MT.werte[c - 1][r - 1] = werte[r - 1][c - 1];       // works well 
        }
    }
    cout << endl;
    // i dont know how i give the transpose matrix back, the matrix is only here in the methode 
    return MT;
}

ostream& operator << (ostream& stream, Matrix& m)
{
    for (int r = 0; r < m.Zeile; r++) {
        for (int c = 0; c < m.Spalte; c++)
        {
            stream << m.werte[r - 1][c - 1] << "\t";
        }
        stream << endl;
    }
    return stream;
}

int main()
{
    Matrix M(5, 3); // will show on consle the init matrix by default 
    cout << endl;
    cout << "Transpose starts here." << endl;       //transpose starts here 
    M.setze_element(0, 2, 5);       // i set a element in row 1 and col 3 to the value of 5 to see if the transpose works 
    cout << "Element is set to value 5." << endl;
    cout << M << endl;
    M.transpos();               // the given method for transpose 
    cout << "Now should show the transpose matrix with the object values." << endl;
    cout << M;                      // print the original matrix not the transpos, not what i need 
    cout << endl;
    return 0;
}

I try to return the pointer of the object or the object itself.

Eric
  • 13
  • 3

1 Answers1

0

You already do:

// i dont know how i give the transpose matrix back, the matrix is only here in the methode 
return MT;

What you need to change is the usage:

M = M.transpos();

.tranpos() returns the transposed matrix. The M = part assigns it. Be wary, though, if you didn't follow the rule of 3, this will expose existing issues in your code.

Alternatively, you could make it so that transpose modifies the object it is called on, rather than returning the transposed matrix.

*this = MT;
return MT; 

But, again, this will expose issues due to you not having a proper assignment operator (rule of three).

Jeffrey
  • 11,063
  • 1
  • 21
  • 42
  • After picking either of the fixes above, go read: https://stackoverflow.com/questions/4172722/what-is-the-rule-of-three – Jeffrey May 20 '23 at 13:30
  • I understand. The solution works and now reveals the problem that I can't display the matrix with my ostream method anymore, because the rows and columns of the transposed matrix are not passed along. So to say an incomplete matrix is displayed and an exception is thrown in the IDE. If I transfer the object MT with a copy constructor to the original object M would that be a solution? – Eric May 20 '23 at 13:39
  • @Eric The first thing you need to do is fix the rule of three problems you have. Even if you manage to avoid rule of three problems in this particular case you are going to get exactly the same problem further down the road. If your class cannot be safely copied and/or assigned then it should be considered bugged. – john May 20 '23 at 13:42
  • @Eric Looking at the posted code, you have neither a copy constructor nor an assignment operator. This class needs both. – john May 20 '23 at 13:45
  • @john I have a copy constructor and some assignment operator but I cut those out of the code. I thought they were not necessary for the explanation or solution of the problem. My Bad. – Eric May 20 '23 at 13:54
  • @Eric OK, well they are in fact vital. If you have bugs in either of those it might explain why you are having problems. – john May 20 '23 at 13:55
  • @john Okay I thought they were right but that can also be a misconception. – Eric May 20 '23 at 14:04
  • @john so i edit the code and add the copy constructor and assignment operator – Eric May 20 '23 at 14:16
  • @Eric No, neither of those are correct, so that explains your problems. The copy constructor must allocate new memory, just like your other constructors, and copy the elements over. The assignment operator should reallocate memory (if the matrix size changes) and again copy the elements over. – john May 20 '23 at 14:21
  • @Eric There are other bugs as well, Look at this from one of your constructors`for (int r = 0; r < Zeile; r++) { werte[r - 1] = new double[Spalte]; }`. Why `r - 1`? When `r` is zero `r - 1` is minus one. That cannot be right. It should be `werte[r] = new double[Spalte];` – john May 20 '23 at 14:26
  • @Eric Same error here `werte[r - 1][c - 1] = init_mit;`, why `- 1`? Again it should be `werte[r][c] = init_mit;` – john May 20 '23 at 14:28
  • @Eric A different error here `werte = new double* [Spalte];` that should be `werte = new double* [Zeile];` – john May 20 '23 at 14:29
  • @Eric There do seem to be a lot of bugs. It might be worth while starting over. – john May 20 '23 at 14:31
  • @john when i dont write `werte[r - 1][c - 1] = init_mit;` than i got 2 warnings. "Severity Code Description Project File Line Suppression state. Warning C6386 Buffer overflow when writing to "values": the writable size is "column*4" bytes, but "8" bytes can be written. Severity Code Description Project File Line Suppression state Warning C6385 Reading invalid data from "werte": the readable size is "column*4" bytes, but "8" bytes can be read." – Eric May 20 '23 at 14:33
  • @john yes thats right i should start from beginning. – Eric May 20 '23 at 14:37
  • @Eric I suspect that might be a consequence of earlier bugs. When you have an array it's never correct to access the `-1` element of that array. Arrays start at `0`. – john May 20 '23 at 14:45