User input with class methods

Pages: 12
I've come to the point where I need to collect user input and create the instance of a matrix. I've tried but I'm not sure how to do this, given all of my methods.


matrix.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#ifndef MATRIX_MATRIX_H
#define MATRIX_MATRIX_H
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;


class Matrix {

private:

   int Rows, Cols;


public:
    int **data;

    Matrix(int rows, int cols);
    ~Matrix();

    Matrix add(Matrix& m);
    Matrix subtract(Matrix& m);
    Matrix multiply(Matrix& m);
    Matrix scalar(int num);

    void setMatrix(int, int, int);
    int getMatrix (int, int) const;
    void printMatrix(Matrix);

};


#endif //MATRIX_MATRIX_H






matrix.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

#include <iostream>
#include "Matrix.h"
using namespace std;

Matrix::Matrix(int rows, int cols)() {
    Rows = rows;
    Cols= cols;
    int **table = new int *[rows];
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < rows ; ++j) {
          table[i]= new int [cols];
        }
      data = table;

    }
}

Matrix* Matrix::add(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) + m.getMatrix(i, j));
        }
    }

    return &m1;
}

Matrix* Matrix::subtract(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i,j) - m.getMatrix(i,j));
        }
    }
    return &m1;
}

Matrix* multiply(Matrix& m);


Matrix* Matrix::scalar(int num){
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) * num);
        }
    }
    return &m1;
}





int Matrix::getMatrix (int r, int c)
{
    return data [r][c];
}

void Matrix::setMatrix(int r, int c, int value)
{
    data[r][c] = value;
}

// remainder of calculations and member functions (like print)

void Matrix:: printMatrix()
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            cout << &m1 << " ";
        }
        cout << endl;
    }
}



int main() {

   cout<<" Number of Rows in Matrix 1: \n";

   cout<<" Number of Columns in Matrix 1: \n";

   cout<<" Values of Matrix 1:  \n";




    return 0;
}
Last edited on
ideally I would not, I would keep the I/O distinct from the math engine for cleaner tools. Just have getters and setters for the dimensions, or a constructor, or both, and let the calling program get that from the user and pass it down to you.

but if you must, make your i/o routines virtual so you can redo them later if you decide that cin/cout needed to be gui text boxes or network read/writes or files or something else, or even if sticking with cin/cout you decide that you want to print it a different way (more decimal places, scientific notation, something).

something then like
1
2
3
4
5
6
7
8
9
10
int main()
{
   int rows,cols;
   cin >> rows >> cols;
   Matrix x(rows,cols);
   Matrix y(2,2);
    ....
   y.setRows(rows);
   y.setCols(cols);   
}


for tightly coupled items, you can also have a setter that does both together.
for efficiency, you may want to allow the user to directly read and write to the data area (the actual matrix's numbers).
Last edited on
Thank you, there are many ways to go about it, which is overwhelming.


How will I use this input to create the new matrix object???

This is my objective:

// Prompt user for information for first matrix
// Collect input and create instance of Matrix
// Prompt user for information for second matrix
// Collect input and create second instance of Matrix

same as you would your first programs that talked to the user...
pseudo code/ logically..

in main
cout "enter rows"
cin rows
cout "enter cols"
cin cols
for(all the rows)
{
cout enter a row
for(all the cols)
cin data[row][col]
}

this is going to get old. you should learn about text file redirection into a program so you can save the inputs in a text file and send it to the program as if you typed it.
on both unix & windows, in the console
program.exe < file.txt
will do it but you need the end of lines and data to all align with the expected inputs.
alternately just set the matrix data in main without user I/O, and recompile for different problems. Whatever works for you to debug it
Last edited on
Write a stream extraction operator overload for your matrix class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::istream& operator>> (std::istream f, Matrix& M)
{
  int rows, cols;
  f >> rows >> cols;
  M.resize(rows, cols);  // <-- you need to write this method!
  for (int row = 0;  row < rows;  row++)
  for (int col = 0;  col < cols;  col++)
  {
    int value;
    f >> value;
    M.setMatrix(row, col, value);
  }
  return f;
}

Thereafter it will properly read a matrix formatted as something like:

    3 4
    1 0 0 0
    0 1 0 0
    0 0 1 0

BTW, you are doing something weird with your return values. Don’t return a pointer to a local variable! Either return a reference to this:

21
22
    Matrix& add(const Matrix& m);  // add m to *this, return *this
    Matrix& subtract(const Matrix& m);  // equivalent to: *this -= m; 

Or return a new matrix:

21
22
    Matrix add(const Matrix& m) const;  // add *this and m to get a new matrix
    Matrix subtract(const Matrix& m) const;  // equivalent to: r = *this + m; 

Notice also how the operands to the ‘add’ operation are const when appropriate.

Don’t forget to verify that things make sense:

19
20
21
22
23
24
25
26
27
28
29
30
31
32
Matrix Matrix::add(const Matrix& m) const
{
    // Matrices must match. If not, return an invalid matrix:
    if ((m.Rows <> Rows) or (m.Cols <> Cols)) return Matrix(0, 0);

    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) + m.getMatrix(i, j));
        }
    }

    return m1;
}

Don’t forget to define your destructor and delete[] all the stuff you new[]-ed in the constructor. As it is right now you are leaking memory all over the place.


BTW, getMatrix sounds to me like you are getting the entire matrix, when you really only want a single cell. I would name it int get(int row, int col) const or int getCell(int row, int col) const or something like that.

Likewise, since printMatrix is a member function (a method), it is kind of superfluous to say “print matrix” — just name it “void print() const”.


Notice how I keep adding “const” to everything. It indicates that a thing is not to be changed. That is why the “get” has a const attached to it — because “get” does not change the matrix. In contrast, “set” very explicitly does modify the matrix, so it does not get a const:

1
2
    int get(int row, int col) const;
    void set(int row, int col, int value);
1
2
3
4
5
6
7
8
9
int Matrix::get(int row, int col) const
{
  ...
}

void Matrix::set(int row, int col, int value)
{
  ...
}


More on names: “scalar” could also be properly named “multiply”. C++ will choose the correct function based on the argument value.

23
24
    Matrix multiply (const Matrix& m);  // multiply *this with Matrix m
    Matrix multiply (int k);            // multiply *this with scalar k 

Later in your code you only need call the function:

1
2
3
4
  Matrix A(3, 4);
  ...

  Matrix A7 = A.multiply(7);

This is how operator overloading works. Your algebraic functions could be named after them:

21
22
23
24
    Matrix operator + (const Matrix& m) const;  // r = *this + m;
    Matrix operator - (const Matrix& m) const;
    Matrix operator * (const Matrix& m) const;
    Matrix operator * (int k) const;
and/or
1
2
3
4
    Matrix& operator += (const Matrix& m);  // *this += m;
    Matrix& operator -= (const Matrix& m);
    Matrix& operator *= (const Matrix& m);
    Matrix& operator *= (int k);

It is easy enough to define both, where one is defined in terms of the other:

1
2
3
4
5
6
7
8
9
10
11
12
13
    Matrix& operator *= (const Matrix& m) 
    { 
      Matrix r = *this * m;
      *this = r; // you must have an assignment operator to do this!
      return *this;
    }

    Matrix operator + (const Matrix& m) const
    {
      Matrix r(m.Rows, m.Cols);
      r += m;
      return r;
    }


And, circling back to the beginning, your print method can be used with a stream insertion operator overload:

1
2
3
4
5
std::ostream& operator<< (std::ostream& f, const Matrix& m)
{
  m.print(f);  // notice that Matrix::print() must now be defined to take an  output stream as argument...
  return f;
}


Hopefully this gives you a lot of ideas to work with.
Oh, yeah, very important to define your copy constructor and assignment operator.

1
2
3
4
5
6
7
8
9
10
11
12
class Matrix {
    ...

public:

    Matrix(int Rows = 0, int Cols = 0);     // constructor + default constructor
    Matrix(const Matrix& that);             // copy constructor
    Matrix& operator= (const Matrix& that); // assignment operator
    ~Matrix();                              // destructor

    ....
};

These are all important because you are managing the data dynamic memory yourself.

I find it useful to have a private helper function or two to manage allocating and deallocating memory.
Last edited on
It would make your code so much simpler if you used a std::vector of type std::vector for data. You then don't need to bother about destructor/copy constructor/copy assignment memory allocation etc etc.
I wouldn’t even bother with the nested vector. My matrix classes invariably look something like this:

1
2
3
4
5
6
7
8
9
10
11
template <typename T = double>
struct matrix
{
  ...
protected:
  std::size_t     nrows;
  std::size_t     ncolumns;
  std::vector <T> data;

  auto index( auto r, auto c ) const { return r * ncolumns + c; }
};

The only thing that gets even close to messy is a resize.
As a starter, perhaps consider something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include <iostream>
#include <vector>
#include <exception>

class Matrix {
	using Cols = std::vector<int>;
	using Array = std::vector<Cols>;

	Array data;

public:
	const size_t rows {}, cols {};

	Matrix(size_t rows, size_t cols);
	Matrix(const Matrix& m);
	Matrix(Matrix&& m) noexcept;

	int operator()(size_t r, size_t c) const;
	int& operator()(size_t r, size_t c);

	Matrix operator+(Matrix m) const noexcept;
	Matrix operator-(Matrix m) const noexcept;
	Matrix operator*(const Matrix& m) const;
	Matrix operator*(int num) const;

	Matrix& operator+=(const Matrix& m);
	Matrix& operator-=(const Matrix& m);
	Matrix& operator*=(int num) noexcept;
};

std::ostream& operator<<(std::ostream& os, const Matrix& m) {
	for (size_t i {}; i < m.rows; ++i) {
		for (size_t j {}; j < m.cols; ++j)
			os << m(i, j) << ' ';

		os << '\n';
	}

	return os << '\n';
}

std::istream& operator>>(std::istream& is, Matrix& m) {
	for (size_t r {}; r < m.rows; ++r)
		for (size_t c {}; c < m.cols; ++c) {
			int value {};

			is >> value;
			m(r, c) =  value;
		}

	return is;
}

Matrix::Matrix(size_t r, size_t c) : rows(r), cols(c), data { Array(r, Cols(c)) } {}
Matrix::Matrix(const Matrix& m) : data(m.data), rows(m.rows), cols(m.cols) {}
Matrix::Matrix(Matrix&& m) noexcept: data(std::move(m.data)), rows(m.rows), cols(m.cols) {}

int Matrix::operator()(size_t r, size_t c) const {
	return data[r][c];
}

int& Matrix::operator()(size_t r, size_t c) {
	return data[r][c];
}

Matrix Matrix::operator+(Matrix m) const noexcept {
	return m += *this;
}

Matrix Matrix::operator-(Matrix m) const noexcept {
	return m -= *this;
}

Matrix Matrix::operator*(int num) const {
	auto m1 { *this };

	return m1 *= num;
}

Matrix& Matrix::operator+=(const Matrix& m) {
	if (m.cols == cols && m.rows == rows) {
		for (size_t i {}; i < rows; ++i)
			for (size_t j {}; j < cols; ++j)
				(*this)(i, j) += m(i, j);

		return *this;
	} else
		throw std::out_of_range("Invalid matrix size");
}

Matrix& Matrix::operator-=(const Matrix& m) {
	if (m.cols == cols && m.rows == rows) {
		for (size_t i {}; i < rows; ++i)
			for (size_t j {}; j < cols; ++j)
				(*this)(i, j) -= m(i, j);

		return *this;
	} else
		throw std::out_of_range("Invalid matrix size");
}

Matrix& Matrix::operator*=(int num) noexcept {
	for (size_t i {}; i < rows; ++i)
		for (size_t j {}; j < cols; ++j)
			(*this)(i, j) *= num;

	return *this;
}

Matrix Matrix::operator*(const Matrix& target) const {
	if (cols == target.rows) {
		Matrix output(rows, target.cols);

		for (size_t r {}; r < output.rows; ++r)
			for (size_t c {}; c < output.cols; ++c)
				for (size_t k {}; k < target.rows; ++k)
					output(r, c) += (*this)(r, k) * target(k, c);

		return output;
	} else
		throw std::out_of_range("Invalid matrix size");
};

int main() {
	size_t r {}, c {}, c3 {};

	std::cout << "Number of Rows in Matrix: ";
	std::cin >> r;

	std::cout << "Number of Columns in Matrix: ";
	std::cin >> c;

	Matrix m1(r, c), m2(r, c);

	std::cout << "Values of Matrix 1 (row/column order): ";
	std::cin >> m1;

	std::cout << "Values of Matrix 2 (row/column order): ";
	std::cin >> m2;

	std::cout << "m1 is:\n" << m1;
	std::cout << "m2 is:\n" << m2;

	std::cout << "m1 + m2 is:\n" << m1 + m2;

	std::cout << "m2 * 6 is:\n" << m2 * 6;

	std::cout << "Number of Columns in Matrix 3: ";
	std::cin >> c3;

	Matrix m3(c, c3);

	std::cout << "Values of Matrix 3 (row/column order " << c << 'x' << c3 << "): ";
	std::cin >> m3;

	std::cout << "m1 * m3 is:\n" << m1 * m3 << '\n';
}



Number of Rows in Matrix: 2
Number of Columns in Matrix: 3
Values of Matrix 1 (row/column order): 1 2 3 4 5 6
Values of Matrix 2 (row/column order): 2 3 4 5 6 7
m1 is:
1 2 3
4 5 6

m2 is:
2 3 4
5 6 7

m1 + m2 is:
3 5 7
9 11 13

m2 * 6 is:
12 18 24
30 36 42

Number of Columns in Matrix 3: 2
Values of Matrix 3 (row/column order 3x2): 3 4 5 6 7 8
m1 * m3 is:
34 40
79 94

Last edited on
Also, I don't believe anyone has pointed out yet that your #include guards are malformed.

You have it as:

1
2
3
4
5
#ifndef MATRIX_MATRIX_H
#define MATRIX_MATRIX_H
#endif //MATRIX_MATRIX_H

/// ... matrix code ... 


It should be:

1
2
3
4
5
6
#ifndef MATRIX_MATRIX_H
#define MATRIX_MATRIX_H

/// ... matrix code ...

#endif //MATRIX_MATRIX_H 


(You also should avoid putting using ...; statements in the global scope of the header file, especially since you aren't even using anything from the std namespace in your header.)
Last edited on
Thank you to everyone who replied, I should've mentioned my professor is not allowing the use of overloading operators.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <cmath>
#include "Matrix.h"
using namespace std;


Matrix::Matrix (int rows, int cols) {
    Rows = rows;
    Cols= cols;
    int **data= new int *[rows];
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < rows ; ++j) {
          data[i]= new int [cols];
        }

    }
}



Matrix* Matrix::add(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) + m.getMatrix(i, j));
        }
    }

    return &m1;
}

Matrix* Matrix::subtract(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i,j) - m.getMatrix(i,j));
        }
    }
    return &m1;
}

Matrix* multiply(Matrix& m);


Matrix* Matrix::scalar(int num){
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) * num);
        }
    }
    return &m1;
}




int Matrix::getMatrix (int r, int c) const
{
    return data [r][c];
}

void Matrix::setMatrix(int r, int c, int value)
{
    data[r][c] = value;
}


void Matrix:: printMatrix (Matrix m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            cout << &m1 << " ";
        }
        cout << endl;
    }
}



Matrix::~Matrix() {
    for (int i = 0; i < Rows; i++) {
        delete[] data[i];
    }
    }


    int main() {

        int rows1, cols1, rows2, cols2;

        cout << " Number of Rows in Matrix 1: ";
        cin >> rows1;
        cout << " Number of Columns in Matrix 1: ";
        cin >> cols1;

        Matrix m1(rows1, rows2);


        cout << " Values of Matrix 1:  \n";
        for (int r = 0; r < rows1; r++) {
            for (int c = 0; c < cols1; c++) {
                cin>>m1.data[rows1][cols1];
            }
        }

       Matrix m2 (rows2, cols2);

        cout << " Number of Rows in Matrix 2: ";
        cin >> rows2;
        cout << " Number of Columns in Matrix 2: ";
        cin >> cols2;

        cout << " Values of Matrix 1:  \n";
        for (int r = 0; r < rows2; r++) {
            for (int c = 0; c < cols2; c++) {
                cin>>m2.data[rows2][cols2];
            }
        }


m1.add(&m2);


        return 0;
    }

Last edited on
1
2
3
4
5
6
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < rows ; ++j) {
          data[i]= new int [cols];
        }

    }

You are overwriting data[0 .. rows - 1] multiple times because you are using two loops (both looping over rows, by the way).
You only need one loop.

But more importantly...
1
2
3
4
5
6
7
8
9
Matrix* Matrix::scalar(int num){
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) * num);
        }
    }
    return &m1;
}

This architecture is wrong (including add, subtract, multiply). Matrix m1 is a local variable, but you are trying to return its address. The Matrix m1 does not exist after the function returns; it's already been popped off the stack. Trying to access this matrix after the function has ended is undefined behavior. Return the full Matrix object, not a pointer to it.
Last edited on
Okay bare with me.. this is where i'm at. Any idea why the matrices are not printing?? Also I'm almost positive i'm calling my add function incorrectly, I think "m1" being in my program so many times is confusing me.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <iostream>
#include <ostream>
#include "Matrix.h"
using namespace std;

Matrix::Matrix (int rows, int cols) {
    Rows = rows;
    Cols= cols;

    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < rows ; ++j) {
          data[i]= new int [cols];
        }
    }
}



Matrix Matrix::add(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) + m.getMatrix(i, j));
        }
    }

    return m1;
}

Matrix Matrix::subtract(Matrix& m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i,j) - m.getMatrix(i,j));
        }
    }
    return m1;
}

Matrix multiply(Matrix& m);


Matrix Matrix::scalar(int num){
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            m1.setMatrix(i, j, getMatrix(i, j) * num);
        }
    }
    return m1;
}




int Matrix::getMatrix (int r, int c)
{
    return data [r][c];
}

void Matrix::setMatrix(int r, int c, int value)
{
    data[r][c] = value;
}


void Matrix:: printMatrix (Matrix m)
{
    Matrix m1 (Rows, Cols);
    for (int i = 0; i < Rows; ++i) {
        for (int j = 0; j < Cols; ++j) {
            cout << m1.data[i][j] << " ";
        }
        cout << endl;
    }
}




Matrix::~Matrix() {
    for (int i = 0; i < Rows; i++) {
        delete[] data[i];
    }
    }


    int main() {

        int rows1, cols1, rows2, cols2;

        cout << " Number of Rows in Matrix 1: ";
        cin >> rows1;
        cout << " Number of Columns in Matrix 1: ";
        cin >> cols1;

        Matrix m1(rows1,cols1);


        cout << " Values of Matrix 1: (expecting "<<rows1*cols1<<" elements) : ";
        for (int i = 0; i < rows1; i++) {
            for (int j = 0; j < cols1; j++) {
                cin>>m1.data[i][j];
                m1.getMatrix(i,j);
            }
        }

        Matrix m2 (rows2,cols2);


        cout << " Number of Rows in Matrix 2: ";
        cin >> rows2;
        cout << " Number of Columns in Matrix 2: ";
        cin >> cols2;

        cout << "Values of Matrix 2: (expecting " <<rows2*cols2<<" elements) : ";
        for (int i = 0; i < rows2; i++) {
            for (int j = 0; j < cols2; j++) {
                cin>>m2.data[i][j];
                m2.getMatrix(i,j);
            }
        }



 m1.printMatrix(m1);

 m2.printMatrix(m2);

//addition

Matrix add = m1.add(m1);


        return 0;
    }
Last edited on
Your matrix won’t get printed because you never output it. You create a completely new matrix on line 71 and try to print out elements of that new matrix without ever assigning to them on line 74.

Your routine printMatrix doesn’t need any arguments. It’s a type-bound procedure: it should just output the data member of the object from which it is called. Looking back at the rest of your thread, I’m not sure that you understand what object-oriented programming is about.

Please fix your indentation. Banning use of the tab key would help.
Last edited on
Also @Duthomas and @Seeplus, I really appreciate it.
Last edited on
my professor is not allowing the use of overloading operators.


We do get them from time to time... Why they're called "professors" almost beats all understanding....

You could say rename operator+() to be add() and operator+=() to be addto() etc and use these function names instead of using the operators in expressions. Not so elegant and not the way it's done. So you're being taught the 'wrong' way to do things.... Once you're completed the exercise, forget that way of doing it!

Last edited on
Without using overloaded operators, then possibly consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#include <iostream>
#include <vector>
#include <exception>

class Matrix {
	using Cols = std::vector<int>;
	using Array = std::vector<Cols>;

	Array data;

public:
	const size_t rows {}, cols {};

	Matrix(size_t rows, size_t cols);
	Matrix(const Matrix& m);
	Matrix(Matrix&& m) noexcept;

	int at(size_t r, size_t c) const;
	int& at(size_t r, size_t c);

	Matrix add(Matrix m) const noexcept;
	Matrix subtract(Matrix m) const noexcept;
	Matrix multiply(const Matrix& m) const;
	Matrix multiply(int num) const;

	Matrix& addto(const Matrix& m);
	Matrix& subtractto(const Matrix& m);
	Matrix& multiplyto(int num) noexcept;
};

std::ostream& output(std::ostream& os, const Matrix& m) {
	for (size_t i {}; i < m.rows; ++i) {
		for (size_t j {}; j < m.cols; ++j)
			os << m.at(i, j) << ' ';

		os << '\n';
	}

	return os << '\n';
}

std::istream& input(std::istream& is, Matrix& m) {
	for (size_t r {}; r < m.rows; ++r)
		for (size_t c {}; c < m.cols; ++c) {
			int value {};

			is >> value;
			m.at(r, c) =  value;
		}

	return is;
}

Matrix::Matrix(size_t r, size_t c) : rows(r), cols(c), data { Array(r, Cols(c)) } {}
Matrix::Matrix(const Matrix& m) : data(m.data), rows(m.rows), cols(m.cols) {}
Matrix::Matrix(Matrix&& m) noexcept: data(std::move(m.data)), rows(m.rows), cols(m.cols) {}

int Matrix::at(size_t r, size_t c) const {
	return data[r][c];
}

int& Matrix::at(size_t r, size_t c) {
	return data[r][c];
}

Matrix Matrix::add(Matrix m) const noexcept {
	return m.addto(*this);
}

Matrix Matrix::subtract(Matrix m) const noexcept {
	return m.subtractto(*this);
}

Matrix Matrix::multiply(int num) const {
	auto m1 { *this };

	return m1.multiplyto(num);
}

Matrix& Matrix::addto(const Matrix& m) {
	if (m.cols == cols && m.rows == rows) {
		for (size_t i {}; i < rows; ++i)
			for (size_t j {}; j < cols; ++j)
				at(i, j) += m.at(i, j);

		return *this;
	} else
		throw std::out_of_range("Invalid matrix size");
}

Matrix& Matrix::subtractto(const Matrix& m) {
	if (m.cols == cols && m.rows == rows) {
		for (size_t i {}; i < rows; ++i)
			for (size_t j {}; j < cols; ++j)
				at(i, j) -= m.at(i, j);

		return *this;
	} else
		throw std::out_of_range("Invalid matrix size");
}

Matrix& Matrix::multiplyto(int num) noexcept {
	for (size_t i {}; i < rows; ++i)
		for (size_t j {}; j < cols; ++j)
			at(i, j) *= num;

	return *this;
}

Matrix Matrix::multiply(const Matrix& target) const {
	if (cols == target.rows) {
		Matrix output(rows, target.cols);

		for (size_t r {}; r < output.rows; ++r)
			for (size_t c {}; c < output.cols; ++c)
				for (size_t k {}; k < target.rows; ++k)
					output.at(r, c) += at(r, k) * target.at(k, c);

		return output;
	} else
		throw std::out_of_range("Invalid matrix size");
};

int main() {
	size_t r {}, c {}, c3 {};

	std::cout << "Number of Rows in Matrix: ";
	std::cin >> r;

	std::cout << "Number of Columns in Matrix: ";
	std::cin >> c;

	Matrix m1(r, c), m2(r, c);

	std::cout << "Values of Matrix 1 (row/column order): ";
	input(std::cin, m1);

	std::cout << "Values of Matrix 2 (row/column order): ";
	input(std::cin, m2);

	std::cout << "m1 is:\n";
	output(std::cout, m1);

	std::cout << "m2 is:\n";
	output(std::cout, m2);

	std::cout << "m1 + m2 is:\n";
	output(std::cout,  m1.add(m2));

	std::cout << "m2 * 6 is:\n";
	output(std::cout, m2.multiply(6));

	std::cout << "Number of Columns in Matrix 3: ";
	std::cin >> c3;

	Matrix m3(c, c3);

	std::cout << "Values of Matrix 3 (row/column order " << c << 'x' << c3 << "): ";
	input(std::cin, m3);

	std::cout << "m1 * m3 is:\n";
	output(std::cout, m1.multiply(m3));
	std::cout << '\n';
}

Fix the print method and then add this at line 109 of your latest post:
1
2
m1.print();
return 0;

This will cause the program to simply print out the matrix that you input and then exit. Note that the compiler may complain that all the code after return 0; is never executed. That's okay, we're doing this as a test to make sure you can enter and print a matrix correctly.

The reason for this test is simple: garbage in - garbage out! If your code that inputs the matrix is buggy then there's no point trying to do math operations. Similarly, if your code that prints a matrix is bad, you'll never know if your code works. So make sure you can enter and print a matrix reliably first.
Last edited on
if you want to do it this way, then you have issues with your dynamic memory. For a starter, consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <iostream>
#include <utility>

class Matrix {
private:
	int** data {};
	size_t Rows {}, Cols {};

	void swap(Matrix& m) noexcept;

public:
	Matrix(size_t rows, size_t cols);
	~Matrix();

	Matrix(const Matrix& m) noexcept;
	Matrix(Matrix&& m) noexcept;
	Matrix& operator=(Matrix m) noexcept;

	Matrix add(Matrix m) const noexcept;
	Matrix subtract(Matrix m) const noexcept;
	Matrix scalar(int num) const;

	void setMatrix(size_t r, size_t c, int v);
	int getMatrix(size_t r, size_t) const;
	void printMatrix() const ;
	void inputMatrix();

	size_t noRows() const noexcept;
	size_t noCols() const noexcept;
};

Matrix::Matrix(size_t rows, size_t cols) : Rows(rows), Cols(cols), data(new int* [rows]) {
	for (size_t j {}; j < rows; ++j)
		data[j] = new int[cols];
}

Matrix Matrix::add(Matrix m1) const noexcept {
	if (m1.Rows == Rows && m1.Cols == Cols)
		for (size_t i {}; i < Rows; ++i)
			for (size_t j {}; j < Cols; ++j)
				m1.setMatrix(i, j, getMatrix(i, j) + m1.getMatrix(i, j));
	else
		std::cout << "Matrix sizes don't match\n";

	return m1;
}

Matrix Matrix::subtract(Matrix m1) const noexcept {
	if (m1.Rows == Rows && m1.Cols == Cols)
		for (size_t i {}; i < Rows; ++i)
			for (size_t j {}; j < Cols; ++j)
				m1.setMatrix(i, j, getMatrix(i, j) - m1.getMatrix(i, j));
	else
		std::cout << "Matrix sizes don't match\n";

	return m1;
}

Matrix Matrix::scalar(int num) const {
	Matrix m1(Rows, Cols);

	for (size_t i {}; i < Rows; ++i)
		for (size_t j {}; j < Cols; ++j)
			m1.setMatrix(i, j, getMatrix(i, j) * num);

	return m1;
}

int Matrix::getMatrix(size_t r, size_t c) const {
	return data[r][c];
}

void Matrix::setMatrix(size_t r, size_t c, int value) {
	data[r][c] = value;
}

void Matrix::printMatrix() const {
	for (size_t i {}; i < Rows; ++i) {
		for (size_t j {}; j < Cols; ++j)
			std::cout << data[i][j] << ' ';

		std::cout << '\n';
	}

	std::cout << '\n';
}

void Matrix::inputMatrix() {
	for (size_t i {}; i < Rows; ++i)
		for (size_t j {}; j < Cols; ++j) {
			int val {};

			std::cin >> val;
			data[i][j] = val;
		}
}

Matrix::~Matrix() {
	for (size_t i {}; i < Rows; ++i)
		delete[] data[i];

	delete[] data;
}

void Matrix::swap(Matrix& m) noexcept {
	std::swap(Rows, m.Rows);
	std::swap(Cols, m.Cols);
	std::swap(data, m.data);
}

Matrix::Matrix(const Matrix& m) noexcept : Matrix(m.Rows, m.Cols) {
	for (size_t i {}; i < Rows; ++i)
		for (size_t j {}; j < Cols; ++j)
			data[i][j] = m.data[i][j];
}

Matrix::Matrix(Matrix&& m) noexcept {
	swap(m);
}

Matrix& Matrix::operator=(Matrix m) noexcept{
	swap(m);

	return *this;
}

size_t Matrix::noRows() const noexcept {
	return Rows;
}

size_t Matrix::noCols() const noexcept {
	return Cols;
}

int main() {
	size_t rows1 {}, cols1 {}, rows2 {}, cols2 {};

	std::cout << "Number of Rows in Matrix 1: ";
	std::cin >> rows1;

	std::cout << "Number of Columns in Matrix 1: ";
	std::cin >> cols1;

	Matrix m1(rows1, cols1);

	std::cout << "Values of Matrix 1: (expecting " << rows1 * cols1 << " elements) : ";
	m1.inputMatrix();

	std::cout << "Number of Rows in Matrix 2: ";
	std::cin >> rows2;

	std::cout << "Number of Columns in Matrix 2: ";
	std::cin >> cols2;

	Matrix m2(rows2, cols2);

	std::cout << "Values of Matrix 2: (expecting " << rows2 * cols2 << " elements) : ";
	m2.inputMatrix();

	std::cout << "m1 is\n";
	m1.printMatrix();

	std::cout << "m2 is\n";
	m2.printMatrix();

	std::cout << "m1 added to m2\n";
	m1.add(m2).printMatrix();

	std::cout << "m2 multiply 6\n";
	m2.scalar(6).printMatrix();
}



Number of Rows in Matrix 1: 2
Number of Columns in Matrix 1: 3
Values of Matrix 1: (expecting 6 elements) : 1 2 3 4 5 6
Number of Rows in Matrix 2: 2
Number of Columns in Matrix 2: 3
Values of Matrix 2: (expecting 6 elements) : 2 3 4 5 6 7
m1 is
1 2 3
4 5 6

m2 is
2 3 4
5 6 7

m1 added to m2
3 5 7
9 11 13

m2 multiply 6
12 18 24
30 36 42

I am always fairly uncomfortable trying to change a person’s assignment too much. I much prefer to present options that will help for further learning or understanding, but that enable people to stick with the structure given in their assignment.

We all went through the Matrix::multiply() function version of stuff before we learned about operator overloading. It is a valuable lesson that shouldn’t be skipped.

I also disagree with professor bashing. I can tell stories just as well as the next guy or gal. Good or bad, professors teach what is in the curriculum, and it is very smug and very easy to bash what is being taught without really knowing anything about (or worse, not caring about) the reasons for it.

* Worse, because we are not the professor, and have no right to derail a student’s understanding of the material by saying “it’s wrong” when it is, at worst, Not The Way <I/A Professional/The Universe> Would Do It.

/end rant
Pages: 12