Arbitrary matrix dimension in matrix class - c++

The task is as follows: Describe the class "matrix of numbers" with component data: the dimensions of the matrix, a pointer to the elements. Overload operations: << (matrix output to the screen), + (addition of matrices), unary ¬– (change the sign of each element), / = (divide each element by a number). I performed it, and performed it correctly, but you need to set the matrix dimension from the keyboard, and as you can see, it is set in advance for me [3] [3]. It sounds pretty simple, but something I'm really dumb. Thanks in advance for your help. Here is the code:
#include "pch.h"
#include <iostream>
using namespace std;
class Matrix
{
public:
Matrix()
{
int Table[3][3];
}
int Table[3][3];
void Create()
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
Table[i][j] = 10;
}
};
ostream& operator <<(ostream& t, Matrix a)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
t << a.Table[i][j] << " ";
t << "\n";
}
return t;
}
Matrix& operator /=(Matrix& a, int num)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] /= num;
return a;
}
Matrix& operator -(Matrix& a, int empty)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] = -a.Table[i][j];
return a;
}
Matrix& operator +(Matrix& a, Matrix b)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
int main()
{
int u;
setlocale(LC_ALL, "Russian");
Matrix Example;
Example.Create();
Matrix Example1;
Example1.Create();
cout << Example;
cout << Example1;
cout << "Сумма матриц: "<<endl;
cout << Example + Example1;
Example - 1;
Example1 - 1;
cout<< Example + Example1;
cout << "На сколько вы хотите её поделить?\n";
cin >> u;
Example /= u;
Example1 /= u;
cout << Example;
cout << Example1;
}`

You need to dynamically create the matrix.
In order to this you need to use pointers(*). Change int table[3][3]
double table**;
An example of how it could be implemented (note that I use matrix instead of table)
class Matrix {
private:
double** matrix;
int col;
int row;
public:
Matrix(){};
void Create(int row, int col);
};
void Matrix::Create(int row_, int col_){
double val = 0.0;
col = col_; // initalize private members
row = row_;
matrix = new double*[row]; // Create a new array of size row_
for(int i = 0; i < row; i++)
{
matrix[i] = new double[col]; // Create new cols of size col (inside array of row)
}
for(int i = 0; i < row; i++)
{
for(int j = 0; j < col; j++)
{
matrix[i][j] = val;
val = val + 1.0;
}
}
}
I tried to reuse your design for simplicity, but I really suggest that you try to specify the dimensions of the matrix in a constructor instead and maybe even construct the matrix in it as well.
Something like this:
Matrix(int row_, int col_) : row(row_), col(col_) {*/ create matrix here /*};
You can skip the "create matrix here" part and use your own Create() if you want to.

You need dynamic memory allocation for that. I won't fiddle around with pointers (new / delete) unless you are explicitly told to. As a beginner you should probably use the standard template library (STL) tools:
#include <vector> and use std::vector<std::vector<int>> Table instead of int Table[3][3]. Then write a constructor like this:
Matrix(std::size_t rows, std::size_t cols)
{
Table.resize(rows);
for (unsigned int i = 0; i < Table.size(); ++i)
Table[i].resize(cols);
}
You can additionally store the dimension of the matrix, but there is no need to do it since you can get the information from the vectors. Replace the hardcoded dimensions in all loops by the corresponding dynamic sizes (stored or extracted from the vectors). For example:
Matrix& operator +(Matrix& a, Matrix b)
{
unsigned int rows = a.Table.size();
unsigned int cols = a.Table[0].size();
for (unsigned int i = 0; i < rows; i++)
for (unsigned int j = 0; j < cols; j++)
a.Table[i][j] += b.Table[i][j];
return a;
}
However, this vector of vectors is not really effective. Better would be a single vector but I guess for a beginner it is okay.
Greetings

Related

Can someone explain me, why my code is not working?

I am completely new in C++ and I have to solve a task for college, where I have to make a struct Matrix and fill it with random integers. I marked the line with a "!" where the error appears.
It is the error C2131(Visual C++ Compiler). It says "expression did not evaluate to a constant".
struct Matrix{
int rows;
int columns;
Matrix(int r, int c){
rows = r, columns = c;
}
int produceMatrix(){
int matrix[rows][columns]; "!"
for(int i = 0; i != rows; i++){
for(int j = 0; j != columns; j++){
matrix[i][j] = rand() %10 +1;
}
}
return 0;
}
int showMatrix(){
for(int i = 0; i != rows; i++){
for(int j = 0; j != columns; j++){
cout << matrix[i][j]<< endl;
}
}
}
};
int main()
{
srand(time(0));
Matrix a(3, 4);
}
If you are planning to create your matrix with rows and columns values only known at runtime, you are better off using std::vector<std::vector<int>> to hold your data, as the static array you use needs to know its size at compile time. But if all your sizes are known at compile time and you just want flexibility of creating different matrix sizes, you can use template, for example:
#include <iostream>
#include <ctime>
template <int ROWS, int COLUMNS>
struct Matrix
{
int rows = ROWS;
int columns = COLUMNS;
int matrix[ROWS][COLUMNS] = {};
void produceMatrix()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
matrix[i][j] = rand() % 10 + 1;
}
}
}
void showMatrix()
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < columns; j++)
{
std::cout << matrix[i][j] << "\t";
}
std::cout << std::endl;
}
}
};
int main()
{
srand(time(0));
Matrix<3,4> a;
a.produceMatrix();
a.showMatrix();
}
https://ideone.com/rCLxSn
4 10 5 5
3 8 3 6
2 4 9 10
One thing is that you cannot make variable-length arrays this way.
Another thing is that if you create a variable within a function (like you were doing here with int matrix in produceMatrix()), it is then not visible in another function.
Therefore, the array containing the elements of the matrix should be declared in your struct there, where you have declared rows and columns.
To store the elements of your matrix, you can use one-dimensional array of length equal to rows*columns.
Now, you need some kind of dynamic array to be able to make it of the length not known in the compilation time.
One solution is to use a pointer and define an array with new operator in the constructor. However, if you use new, then you have to use delete at some point to deallocate memory, which here means that the destructor is needed. Another problem would be with copying of your matrices.
Another, simpler solution is to use std::vector, a container provided by c++ standard library. Here's how to do it with std::vector (you need to add #include<vector> to your file):
struct Matrix{
int rows;
int columns;
vector<int> matrix;
Matrix(int r, int c){
rows = r, columns = c;
matrix = vector<int>(c*r);
}
int produceMatrix(){
for(int i = 0; i < matrix.size(); i++){
matrix[i] = rand() %10 +1;
}
return 0;
}
int showMatrix(){
for(int i = 1; i <= matrix.size(); i++){
cout << matrix[i-1];
if(i%columns == 0) cout << endl;
else cout << " ";
}
return 0;
}
};
As many people commented, please go through a good C++ book to learn about arrays, classes, structs etc. As for your code, the following might produce what I think you want:
#include <iostream>
#include <vector>
struct Matrix
{
int rows;
int columns;
std::vector<std::vector<int>> matrix;
Matrix(int r, int c): rows(r), columns(c)
{
matrix.resize(r);
for(int i = 0; i < r; i++)
matrix[i].resize(c);
}
int produceMatrix()
{
for(int i = 0; i != rows; i++)
for(int j = 0; j != columns; j++)
matrix[i][j] = rand() %10 +1;
return 0;
}
int showMatrix()
{
for(int i = 0; i != rows; i++)
{
for(int j = 0; j != columns; j++)
std::cout << matrix[i][j]<<" ";
}
std::cout<<'\n';
}
};
int main()
{
srand(time(0));
Matrix a(3, 4);
a.produceMatrix();
a.showMatrix();
}

implementing Matrix class addition operator overloading weird output

I'm trying to implement a matrix class and overloading the + and = operators.
The problem is I'm getting weird output when I add two matrices as in this picture.
adding two matrices output console
#include <iostream>
#include <iomanip>
using namespace std;
class Matrix
{
int **p, m, n;
public:
Matrix(int row, int col)
{
m = row;
n = col;
p = new int*[m];
for (int i = 0; i < m; i++)
p[i] = new int[n];
}
Matrix (Matrix & x)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
p[i][j]=x.p[i][j];
}
}
}
~Matrix()
{
for (int i = 0; i < m; i++)
delete [] p[i];
delete [] p;
}
void accept()
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
cin >> p[i][j];
}
}
}
void display()
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
cout << setw(10)<<left <<p[i][j] <<" | ";
}
cout << "\n--------------------------------------"<<endl;
}
}
Matrix& operator +(const Matrix & m2)
{
Matrix r(m, n);
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
r.p[i][j] = p[i][j] + m2.p[i][j];
}
}
return r;
}
Matrix& operator= (const Matrix & eq)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < n; j++)
{
p[i][j]=eq.p[i][j];
}
}
return *this;
}
friend Matrix operator * (Matrix, Matrix);
};
Matrix operator* (Matrix a , Matrix b)
{
Matrix B(1,1);
if(a.n == b.m)
{
Matrix T(a.m, b.n);
for(int i = 0; i < a.m; i++)
{
for(int k = 0; k < b.n; k++)
{
T.p[i][k] = 0;
for(int j = 0; j < a.n; j++)
{
T.p[i][k]+= a.p[i][j] * b.p[j][k];
}
}
}
B = T;
}
return B;
}
int main()
{
cout << "Enter Matrix 1 (3x2):"<<endl;
Matrix m1(3,2);
m1.accept();
m1.display();
cout << "Enter Matrix 2 (3x2):"<<endl;
Matrix m2(3,2);
m2.accept();
m2.display();
Matrix m3(3,2);
m3=m1+m2;
cout <<endl<< "matrix1 + matix2 is:\n "<<endl;
m3.display();
}
Any ideas how to fix that? I would be grateful for your help and advices with improving it because probably there will be some mistakes.
I use CodeBlocks IDE.
The problem is that your operator + returns a local variable Matrix as a reference; this is undefined behavior. It should be returned by value, not by reference.
Make sure that your Matrix class has a copy constructor that takes a const input, i.e.
Matrix (const Matrix & x)
and that it initializes the array before writing into it. Move the initialization code (the two loops with allocation) into a separate private function, and call it from the default constructor and from the copy constructor.

C++ replacing matrix values with sub-matrix values

I have a University assignment whereby I have a 1D array, containing 262144 values. I've created a matrix class which places these values into an object with the datasource being the double* list of 262144 values.
I need to be able to obtain a sub-matrix (which I'm able to do) from ANOTHER set of 262144 values (which I've also placed into a matrix object).
However, I'm having serious trouble and I've been trying so hard for the last 3 days to try and replace original matrix values from a sub-matrix. I've tried passing by reference, creating Matrix*'s. I've tried everything we've been taught and even researched a few more methods, all of which I haven't understood. I'll throw my code in here to see if anyone can explain a method to me which will be able to do this.
Matrix::Matrix()
{
"Matrix::Matrix() is invoked";
}
Matrix::Matrix(const Matrix& m)
{
"Matrix::Matrix(const Matrix&) is invoked";
_M = m._M;
_N = m._N;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = m._data[i];
}
}
Matrix::Matrix(int sizeR, int sizeC, double *input_data)
{
"Matrix::Matrix(int sizeR, int sizeC, double *input_data is invoked";
_M = sizeR;
_N = sizeC;
_data = new double[_M*_N];
for (int i = 0; i < _M*_N; i++)
{
_data[i] = input_data[i];
}
}
Matrix Matrix::get_Block(int start_row, int end_row, int start_coloumn, int end_coloumn)
{
int rows = (end_row - start_row);
int columns = (end_coloumn - start_coloumn);
int ctr = 0;
double *temp_Data = new double[rows*columns];
for (int x = start_row; x < (rows + start_row); x++)
{
for (int y = start_coloumn; y < (columns + start_coloumn); y++)
{
temp_Data[ctr] = get(x, y);
ctr++;
}
}
Matrix block(rows, columns, temp_Data);
delete[] temp_Data;
return block;
}
Matrix Matrix::operator+(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] + other._data[x];
}
return temp;
}
Matrix Matrix::operator*(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] * other._data[x];
}
return temp;
}
Matrix Matrix::operator-(const Matrix & other)
{
Matrix temp;
temp._M = other._M;
temp._N = other._N;
temp._data = new double[temp._M*temp._N];
for (int x = 0; x < (temp._M*temp._N); x++)
{
temp._data[x] = this->_data[x] - other._data[x];
}
return temp;
}
void Matrix::replace_Block(Matrix& noisy, Matrix& shuffled,int k, int j, int i)
{
int val_to_replace = 0;
for (int i = 0; i < 3 * 3; i++)
{
val_to_replace = shuffled.get(i, j);
noisy.set(i, j, val_to_replace);
}
}
void Matrix::set_Block(Matrix block, Matrix& Noisy, int start_row, int end_row)
{
int ctr = 0;
int ctr2 = 0;
int ctr3 = 0;
for (int i = 0; i < 3; i++)
{
Noisy._data[(start_row*_M)+i+4] = block.get(i, ctr);
ctr++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 3] = block.get(j, ctr2);
ctr2++;
}
for (int j = 0; j < 3; j++)
{
Noisy._data[((start_row + 1)*_M) + j + 2] = block.get(j, ctr3);
ctr3++;
}
}
double Matrix::get_Sum(Matrix m)
{
double total = 0;
short row = m.get_M();
short column = m.get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m.get(j,i);
}
}
return total;
}
double Matrix::get_Sum(Matrix* m)
{
double total = 0;
short row = m->get_M();
short column = m->get_N();
for (int j = 0; j < row; j++)
{
for (int i = 0; i < column; i++)
{
total += m->get(i, j);
}
}
return total;
}
double Matrix::get(int i, int j)
{
return _data[(i * _M) + j];
}
void Matrix::write_Block(int i, int j)
{
for (int ctr = 0; ctr < i; ctr++)
{
for (int ctr2 = 0; ctr2 < j; ctr2++)
{
std::cout << " " << this->get(ctr,ctr2);
}
std::cout << std::endl;
}
}
void Matrix::set(int i, int j, double val)
{
this->_data[(i*_M) + j] = val;
}
void Matrix::set_N(int N)
{
_N = N;
}
void Matrix::set_M(int M)
{
_M = M;
}
int Matrix::get_N()
{
return _N;
}
int Matrix::get_M()
{
return _M;
}
Matrix::~Matrix()
{
"Matrix::~Matrix() is invoked";
delete[] _data;
}
If it would be helpful to see main() I can supply that too, however all it really contains is the creation of the matrix objects using overloaded constructors.
explanation
Answer is only 4 years late . . .
Anyway. Maybe it will help somebody else. The secret is to use a std::valarray. With that it is utmost simple to work on a matrix. And, many many functions are available.
All the functions that you want to implement are already available.
And you sub-matrix coy can be a one liner . . .
Please see example code:
#include <iostream>
#include <algorithm>
#include <numeric>
#include <valarray>
#include <iomanip>
constexpr size_t NRows = 6;
constexpr size_t NCols = 8;
constexpr size_t SubNRows = 2;
constexpr size_t SubNCols = 3;
void debugPrint(std::valarray<int> &v, size_t nrows = NRows, size_t ncols = NCols)
{
for (int r = 0; r < nrows; ++r) {
for (int c = 0; c < ncols; ++c)
std::cout << std::setw(3) << v[r*ncols+c] << ' ';
std::cout << '\n';
}
std::cout << '\n';
}
int main()
{
std::valarray<int> v1(NRows * NCols); // Define array with given size
std::iota(std::begin(v1),std::end(v1),0); // Fill the array with consecutive nunbers
debugPrint (v1); // Print the result
std::cout << "\nSum = " << v1.sum() << "\n\n"; // Print the sum of all values in matrix
std::valarray<int> v2(v1); // Create a 2nd matrix as a copy to the first
v2 += 100; // Add 100 to each value in the matrix
debugPrint(v2);
std::valarray<int> v3(NCols); // Get one column
v3 = v1[std::slice(2,NRows,NCols)];
debugPrint(v3,NRows,1);
std::valarray<int> subV2(SubNRows*SubNCols); // So, now the sub array
subV2 = v2[std::gslice(12,{SubNRows, SubNCols},{NCols,1})]; // Slice it out
debugPrint(subV2, SubNRows, SubNCols);
v1[std::gslice(25,{SubNRows, SubNCols},{NCols,1})] = subV2; // And copy to the first array
debugPrint (v1);
return 0;
}

Memory hack to transpose matrix corrupts stack, C++

I need to implement a matrix transpose procedure in C++.
The problem is the signature, the function has to be called like this:
transpose(in_mat[0][0], n, m, out_mat[0][0])
where n and m are the dimensions.
All values are doubles, both the matrices and the dimensions.
Since the code is automatically generated, I can't fix this.
My workaround looks like this:
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer= &in_mat;
double* out_pointer= &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
It works fine.
I've constructed a test case with two matrices of different width and height. One is filled with random numbers, the other is filled with zeros. Then the transpose procedure is called and the two matrices are compared.
The functionality is correct.
But it corrupts the stack. When run in Visual Studio 2015 there is a warning
Run-Time Check Failure #2 - Stack around the variable 'in_mat' was corrupted.
What did I do wrong ? Why is the stack corrupted ?
Code after the invocation of transpose works correctly.
EDIT:
Here is the complete setup:
#include <random>
#include <iostream>
void transpose(double& in_mat, const double _n, const double _m, double& out_mat)
{
int n = _n, m = _m;
double* in_pointer = &in_mat;
double* out_pointer = &out_mat;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
*(out_pointer+(j*n+i)) = *(in_pointer+(i*m + j));
}
}
}
int main()
{
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
double n = 5;
double m = 4;
transpose(in_mat[0][0], n, m, out_mat[0][0]);
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (in_mat[i][j] - out_mat[j][i]>0.0001) {
std::cout << "code is broken" << std::endl; //never reached
}
}
}
std::cout << "finished" << std::endl;
}
Your subscripts (or loop limits) were backwards where you initialized the matrices.
You have
double in_mat[5][4];
double out_mat[4][5];// assign matrix
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 5; j++) {
in_mat[i][j] = std::rand();
out_mat[j][i] = 0;
}
}
When j==4 you are writing beyond the end of out_mat

Transpose a 2d dynamic matrix

I want to create a transpose function for dynamic 2d arrays. I want the functions to have as parameters the 2d array and the rows and columns. I ve decided to use double pointer. However i m a bit confused about how i gonna call the function from main. So i ve got the above code
#include<iostream>
using namespace std;
void transposeMatrix(double **mat, int rows, int columns)
{
mat = new double*[rows];
for (int i = 0; i < rows; ++i)
{
mat[i] = new double[columns];
}
double temp;
for (int i = 0; i<rows; i++)
{
for (int j = i+1; j<columns; j++)
{
temp=mat[i][j];
mat[i][j]=mat[j][i];
mat[j][i]=temp;
}
}
cout<< "\n";
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
cout << mat[i][j] << " \t";
}
cout << "\n";
}
}
int main()
{
int rows = 10;
int columns = 10;
double mat[rows][columns];
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
mat[i][j] = j;
}
}
for (int i = 0; i<rows; i++)
{
for (int j = 0; j<columns; j++)
{
cout << mat[i][j] << " \t";
}
cout << "\n";
}
//mat = new double[50][1];
transposeMatrix(mat, 10, 10);
system("pause");
return 0;
}
Any idea?
You're very close. You're calling the function correctly and the function's parameter list is correct. First, remove this section from the transpose function:
mat = new double*[rows];
for (int i = 0; i < rows; ++i)
mat[i] = new double[columns];
}
Now make sure all your brackets match up. (There was one missing.)
You can't define a static array (one that looks like this: x[y][z]) with non-constant variables as the size arguments. (I.e. y and z must be constants.) But actually, you're passing a dynamic array to the transpose function anyway, and rows and columns don't have to be constants to do that. So, in main, define a dynamic array like this:
double** mat = new double*[rows];
for (int i = 0; i < rows; i++)
mat[i] = new double[columns];
After that, your code should work. But you could also make it better by putting your matrix display code in a function. Then, instead of cutting and pasting it everywhere, all you have to do is call the function! It's an important habit to get into. Have fun!
There are a couple of major issues with your code.
The biggest one is that a double[10][10] is not convertible to a double** pointer.
You also have a memory leak (mat) in your transposeMatrix() implementation.
I recommend that you separate the concerns of printing a matrix and transposing a matrix. Perhaps a separate methods on a (templated) matrix class.
And now, having said that...
Why write one when a perfectly good implementation already exists?
Example:
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/io.hpp>
int main ()
{
using namespace boost::numeric::ublas;
matrix<double> m(3, 3);
for (unsigned i = 0; i < m.size1(); ++i)
{
for (unsigned j = 0; j < m.size2(); ++j)
{
m(i, j) = 3 * i + j;
}
}
std::cout << m << std::endl;
std::cout << trans(m) << std::endl;
}
Output:
[3,3]((0,1,2),(3,4,5),(6,7,8))
[3,3]((0,3,6),(1,4,7),(2,5,8))
double ** transpose(double **matrix, int rows, int columns){
double ** trans;
trans=new double *[columns];
for(int i=0;i<columns;i++){
trans[i]=new double[rows];
for(int j=0;j<rows;j++)
trans[i][j]=matrix[j][i];
}
return trans;
for(int i=0;i<columns;i++)
delete[] trans[i];
delete[] trans;
}
Here is the code for transpose of the matrix.