I want to pass the result object to another display function,but for some reason its not working. cmd stops working
I tried using different aproaches but none seems to be working..
Basically I ahbe to add two matrices using a function and return type should be of an object. I want to print the result of this addition, not in this function but using another function.
#include<iostream>
using namespace::std;
class Matrix{
private:
int row,column; //dimensions row x column
int **matrix; //pointer to a pointer to int
void allocarray(){ //method to llocate array matrix and the matrix[i] arrays
matrix=new int*[row];
for(int i=0;i<row;i++){
matrix[i]=new int[column];
}
}
public:
Matrix(int rowsize, int columnsize); //default constructor
Matrix(); //user defined constructor
~Matrix(); //destructor
void input();
Matrix Add(Matrix);
void display(Matrix);
};
Matrix Matrix::Add(Matrix m2)
{
Matrix result(3,3);
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
result.matrix[i][j]=this->matrix[i][j]+m2.matrix[i][j];
}
}
return *this;
}
void Matrix::display(Matrix m)
{
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
cout<<m.matrix[i][j];
}
cout<<endl;
}
}
Matrix::Matrix( int rowsize, int columnsize):row(rowsize),column(columnsize) //dynamivally allocate
{
allocarray();
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
matrix[i][j]=0; //initilze all values to 0
}
}
}
Matrix::~Matrix() //destructor
{
for( int i=0;i<row;i++)
{
delete [] matrix[i];
}
delete [] matrix;
}
void Matrix::input()
{
cout<<"enter the elements for the matrix"<<endl;
for(int i=0;i<row;i++)
{
for(int j=0;j<column;j++)
cin>>matrix[i][j];
cout<<"\n"; //check it after performing functions!
}
}
int main()
{
Matrix obj1(3,3),obj2(3,3),res(3,3);
cout<<"enter elements for matrix one";
obj1.input();
cout<<"enter elements for matrix two";
obj2.input();
cout<<"addition of two matrices";
res=obj1.Add(obj2);
obj1.display(res);
return 0;
}
so here's the code for copy constructor
Matrix::Matrix(const Matrix &m):row(m.row),column(m.column)
{
allocarray();
for(int i=0;i<row<i++)
{
for(int j=0;j<column;j++)
{
matrix[i][j]=m.matrix[i][j];
}
}
}
Your class doesn't define a copy constructor or an assignment operator. But any attempt to pass a matrix to a function or return a matrix from a function copies the matrix. Your code fails because the destructor is freeing memory that is still in use. When writing classes that manually manage memory you must follow the rule of three. Do this and your program will work.
Also as Patato said you need to add return result; to Matrix::Add, but that will also fail unless you follow the rule of three.
EDIT: changed the link to point to the Stack Overflow page on the rule of three, which is much more helpful than the Wikipedia page.
EDIT: here's an example copy constructor for this class, it's fairly similar to the regular constructor
Matrix::Matrix(const Matrix& rhs):row(rhs.row),column(rhs.column)
{
allocarray();
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
matrix[i][j]=rhs.matrix[i][j];
}
}
}
using reference is good, and your add function does not return the add result
so it looks like this
Matrix Matrix::Add(Matrix &m2)
{
Matrix result(3,3);
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
result.matrix[i][j]=this->matrix[i][j]+m2.matrix[i][j];
}
}
return result;
}
but it is still not very good, after this function the result will be deleted
You could either pass a reference to the function (and return one too):
Matrix& Add(Matrix&);
or write a copy constructor, so that you can use the actual matrix later.
Also, you shouldn't be returning the matrix you're adding to, but the result:
Matrix& Matrix::Add(Matrix &m2)
{
Matrix *result = new Matrix(3,3);
for(int i=0;i<row;i++)
{
for( int j=0;j<column;j++)
{
result->matrix[i][j]=this->matrix[i][j]+m2.matrix[i][j];
}
}
return *result;
}
Related
the following code is not giving the correct output. Matrix data is displaying perfectly, but after the addition of two objects M1 and M2, it did not display the correct output. If I use setData to input data in the matrix, data is stored perfectly, but the addition is not performing correctly. kindly suggest to me how can I correct this logical error?
#include <iostream>
#include <string.h>
using namespace std;
class Matrix{
private:
void Allocate();
int noOfRows;
int noOfColumns;
int **data;
public:
Matrix(int noOfRows, int noOfColumns);
void setData();
void displayData();
~Matrix();
Matrix (const Matrix &ref);
Matrix operator + (const Matrix &m);
void operator = (const Matrix &M );
Matrix& operator = (int x);
};
Matrix::Matrix(int inr=0, int inc=0){
noOfRows=inr; noOfColumns=inc;
Allocate();
}
Matrix::Matrix (const Matrix &ref){
Allocate();
for(int r=0;r<ref.noOfRows;r++)
for(int c=0;c<ref.noOfColumns;c++)
data[r][c]=ref.data[r][c];
}
void Matrix :: operator = (const Matrix &M ) {
Allocate();
noOfRows = M.noOfRows;
noOfColumns = M.noOfColumns;
data=M.data;
}
Matrix& Matrix :: operator = (int x){
Allocate();
for(int r=0;r<noOfRows;r++)
for(int c=0;c<noOfColumns;c++)
data[r][c]=x;
return *this;
}
void Matrix::Allocate(){
data=new int*[noOfRows];
for(int i=0;i<noOfRows;i++)
data[i]=new int[noOfColumns]();
}
void Matrix::setData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++){
cout<<"Enter ...";cin>>data[r][c];
}
cout<<endl;
}
}
Matrix Matrix::operator + (const Matrix &m){
Matrix ms(m.noOfRows,m.noOfColumns);
for (int i=0; i<m.noOfRows; i++)
for (int j=0; j<m.noOfColumns; j++)
ms.data[i][j] = data[i][j]+m.data[i][j];
return ms;
}
void Matrix::displayData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++)
cout<<data[r][c]<<"\t";
cout<<endl;
}
}
Matrix::~Matrix(){
for (int i = 0; i < noOfRows; ++i)
delete[] data[i];
delete [] data;
}
int main(){
Matrix M3(2,2);M3=0;
Matrix M1(2,2);M1=1;
Matrix M2(2,2);M2=2;
//M1.setData();M2.setData();M3.setData();
cout<<"\n Matrix A = "<<endl;
M1.displayData();
cout<<"\n Matrix B = "<<endl;
M2.displayData();
cout<<"\n Matrix C = "<<endl;
M3 = M1;
M3.displayData();
cout<<"\n Sum of Matrix = "<<endl;
M3 = M1 + M2;
M3.displayData();
return 0;
}
Output is here for detail
Copy constructor and assignment operator were both broken. Let's take a quick stroll to see what went wrong
Matrix::Matrix (const Matrix &ref){
// noOfRows and noOfColumns have not been initialized. Their values are unknown so
// the rest of this function is a crapshoot. Could do anything.
Allocate();
for(int r=0;r<ref.noOfRows;r++)
for(int c=0;c<ref.noOfColumns;c++)
data[r][c]=ref.data[r][c];
}
// An assignment operator is expected to return Matrix &
void Matrix :: operator = (const Matrix &M ) {
// noOfRows and noOfColumns have not been updated. Could be wrong, resulting in
// allocate allocating the wrong amount of storage. Moot point since this
// allocation is never used. See below.
Allocate();
noOfRows = M.noOfRows;
noOfColumns = M.noOfColumns;
data=M.data; // both instances share M's data. This will fail sooner or later
// If the program lives long enough, both instances will go out
// of scope and double delete the allocation.
// Also leaks allocation pointed at by `data`.
}
I was in a hurry so I didn't put much thought into fixing the assignment operator and just used the Copy and Swap Idiom. It's very possible that there is a more efficient solution, but copy and swap is usually fast enough and almost impossible to get wrong. Makes a great starting point and benchmarking will tell you if it's a problem.
Matrix::Matrix(const Matrix &ref):
noOfRows(ref.noOfRows),
noOfColumns(ref.noOfColumns) // initialize row and columns
{
Allocate(); // now safe to use
for (int r = 0; r < ref.noOfRows; r++)
for (int c = 0; c < ref.noOfColumns; c++)
data[r][c] = ref.data[r][c];
}
Matrix& Matrix::operator =(Matrix M) // correct return type, and does the heavy
// lifting with the copy constructor
{
std::swap(noOfRows, M.noOfRows);
std::swap(noOfColumns, M.noOfColumns);
std::swap(data, M.data);
return *this;
}
The following code gives me the wrong output. actually, it is not doing sum, it actually copies the 2nd object to the M3 object instead of calculating the sum. I think I have some logical errors in + operator overloading. Does anybody have any idea or any other suggestion? it displays the output actually which is called in the copy constructor function cout<data[r][c]<<"\t";. but it did not display output when I use M3.displayData().
#include <iostream>
#include <string.h>
using namespace std;
class Matrix{
private:
int noOfRows;
int noOfColumns;
int **data;
public:
Matrix(int noOfRows, int noOfColumns);
void displayData();
~Matrix();
Matrix (const Matrix &ref);
Matrix operator + (Matrix m);
Matrix& operator=(Matrix m) {
std::swap(m.noOfRows, noOfRows);
std::swap(m.noOfColumns, noOfColumns);
std::swap(m.data, data);
return *this; }
};
Matrix::Matrix(int inr=0, int inc=0){
noOfRows=inr; noOfColumns=inc;
data=new int*[noOfColumns];
for(int i=0;i<noOfRows;i++)
data[i]=new int[noOfColumns];
int d;
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++){
cout<<"Enter ...";cin>>d;
data[r][c]=d;
}
cout<<endl;
}
}
Matrix::Matrix (const Matrix &ref){
this->data=new int*[ref.noOfColumns];
for(int i=0;i<ref.noOfRows;i++)
this->data[i]=new int[ref.noOfRows];
for(int r=0;r<ref.noOfRows;r++){
for(int c=0;c<ref.noOfColumns;c++){
this->data[r][c]=ref.data[r][c];
cout<<this->data[r][c]<<"\t";
}
cout<<endl;
}
}
Matrix Matrix::operator + (Matrix m){
Matrix ms(m.noOfRows,m.noOfColumns);
ms=0;
for (int i=0; i<m.noOfRows; i++)
for (int j=0; j<m.noOfColumns; j++){
ms.data[i][j] = data[i][j]+m.data[i][j];
return ms;
}
}
void Matrix::displayData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++)
cout<<data[r][c]<<"\t";
cout<<endl;
}
}
Matrix::~Matrix(){
delete[] data;
}
int main(){
Matrix M1(2,2),M2(2,2);
cout<<"\n Matrix A="<<endl;
M1.displayData();
cout<<"\n Matrix B="<<endl;
M2.displayData();
cout<<"\n Sum of Matrix="<<endl;
Matrix M3=M1+M2;
M3.displayData();
return 0;
}
I'm not a matrix specialist, but I understood that matrix summation required both matrixes to be of the same size, and each elements to be summed up.
So you need to fully redefine operator+ (to avoid introducing exceptions here, I'd taken a permissive mathematical view, taking the max size of both matrixes and considering elements out of bounds to be 0):
Matrix Matrix::operator + (Matrix m){
Matrix ms(max(noOfRows,m.noOfRows), max(noOfColumns+m.noOfColumns));
for (int i=0; i<ms.noOfRows; i++)
for (int j=0; j<ms.noOfColumns; j++)
ms.data[i][j] = (i<noOfRows&&j<noOfColumns ? data[i][j]:0.0)
+ (i<m.noOfRows&&j<m.noOfColumns ? m.data[i][j]:0.0);
return ms;
}
By the way, it'll be safer to use the signature Matrix operator + (const Matrix& m) const, to avoid that a typo could accidentally change the value of the matrix, and avoid an unnecessary copy of the matrix argument.
Then, you must make Sum() a free standing function instead of a member function, if you want to call it like you do in main().
The problem is that you have declared Sum as a friend function of class Matrix while defined it as a member function.
To solve the mentioned error just remove the Matrix:: qualification while defining it as shown below:
//----v-------------------------->removed `Matrix::` from here
Matrix Sum(Matrix m1,Matrix m2){
Matrix m;
m=m1+m2;
return m;
}
Also, the program may have other logical errors. You can refer to the rule of three for more information about them or ask a separate question if that doesn't help.
The following code gives me the wrong output. actually, it is not doing sum, it actually copies the 2nd object to the M3 object instead of calculating the sum. I think I have some logical errors in + operator overloading. Does anybody have any idea or any other suggestion? it displays the output actually which is called in the copy constructor function cout<data[r][c]<<"\t";. but it did not display output when I use M3.displayData().
#include
#include <string.h>
using namespace std;
class Matrix{
private:
int noOfRows;
int noOfColumns;
int **data;
public:
Matrix(int noOfRows, int noOfColumns);
void displayData();
~Matrix();
Matrix (const Matrix &ref);
Matrix operator + (Matrix m);
Matrix& operator=(Matrix m) {
std::swap(m.noOfRows, noOfRows);
std::swap(m.noOfColumns, noOfColumns);
std::swap(m.data, data);
return *this; }
};
Matrix::Matrix(int inr=0, int inc=0){
noOfRows=inr; noOfColumns=inc;
data=new int*[noOfColumns];
for(int i=0;i<noOfRows;i++)
data[i]=new int[noOfColumns];
int d;
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++){
cout<<"Enter ...";cin>>d;
data[r][c]=d;
}
cout<<endl;
}
}
Matrix::Matrix (const Matrix &ref){
this->data=new int*[ref.noOfColumns];
for(int i=0;i<ref.noOfRows;i++)
this->data[i]=new int[ref.noOfRows];
for(int r=0;r<ref.noOfRows;r++){
for(int c=0;c<ref.noOfColumns;c++){
this->data[r][c]=ref.data[r][c];
cout<<this->data[r][c]<<"\t";
}
cout<<endl;
}
}
Matrix Matrix::operator + (Matrix m){
Matrix ms(m.noOfRows,m.noOfColumns);
ms=0;
for (int i=0; i<m.noOfRows; i++)
for (int j=0; j<m.noOfColumns; j++){
ms.data[i][j] = data[i][j]+m.data[i][j];
return ms;
}
}
void Matrix::displayData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++)
cout<<data[r][c]<<"\t";
cout<<endl;
}
}
Matrix::~Matrix(){
delete[] data;
}
int main(){
Matrix M1(2,2),M2(2,2);
cout<<"\n Matrix A="<<endl;
M1.displayData();
cout<<"\n Matrix B="<<endl;
M2.displayData();
cout<<"\n Sum of Matrix="<<endl;
Matrix M3=M1+M2;
M3.displayData();
return 0;
}
There are at least four issues with your code:
The Matrix copy constructor fails to copy the noOfRows and noOfColumns values.
You erroneously allocated the row pointers by using noOfColumns as the number of rows.
In the Matrix operator +, you are returning the Matrix inside the for loop, when you should be returning it after the loop is completed.
Your destructor fails to delete[] all the row and column data.
To fix the first two issues, since there is a lot of common code between the Matrix default constructor and the copy constructor, you could create an Allocate member function to allocate the memory:
class Matrix
{
private:
void Allocate();
//... other members
public:
Matrix operator + (const Matrix& m);
// other members...
};
Matrix::Matrix(int inr=0, int inc=0) : noOfRows(inr), noOfColumns(inc)
{
Allocate();
// Input code removed...
}
Matrix::Matrix (const Matrix &ref) : noOfRows(ref.noOfRows), noOfColumns(ref.noOfColumns)
{
Allocate();
for(int r=0; r < ref.noOfRows; r++)
{
for(int c=0; c < ref.noOfColumns; c++)
data[r][c] = ref.data[r][c];
}
}
void Matrix::Allocate()
{
data=new int*[noOfRows];
for(int i=0;i < noOfRows; i++)
data[i]=new int[noOfColumns]();
}
For operator +, you should pass the Matrix by const reference, not by value (this is in addition to fixing the mistake of returning the Matrix prematurely):
Matrix Matrix::operator + (const Matrix& m)
{
Matrix ms(m.noOfRows,m.noOfColumns);
for (int i=0; i<m.noOfRows; i++)
{
for (int j=0; j<m.noOfColumns; j++)
ms.data[i][j] = data[i][j]+m.data[i][j];
}
return ms;
}
The last issue (the destructor) only removes the row pointers, but does not remove the data allocated for each row. The fix is below:
Matrix::~Matrix()
{
for (int i = 0; i < noOfRows; ++i)
delete[] data[i];
delete [] data;
}
Other issues:
Put more space between operators. Your current code squishes everything together, making it hard to read. For example:
for(int c=0;c<ref.noOfColumns;c++) could be:
for (int c=0; c < ref.noOfColumns; c++)
Excessive and unnecessary usage of this->.
If Matrix::operator + exists, it makes sense for Matrix::operator += to also exist. For the latter, operator + would simply be implemented in terms of operator +=, making operator + one or two lines of code.
A probably better method of allocating the memory is illustrated by this answer, since only two allocations are done, the memory allocated is contiguous, and less memory fragmentation will occur.
I have matrix class, and two constructors- one which have arguments (rows,cols,number), for example matrix c(4,4,4) will create 4x4 matrix and fill it with number 4.
Second constructor is reading matrix from txt file, and if I print it in constructor everything works fine, but I wanted to overload ostream << operator to print matrix in main function. This operator works for first constructor but doesn't work for the second one, it prints random numbers in infinity loop.
Here's my code, thanks for any advice and help.
ostream & operator <<(ostream &o, const matrix &m)
{
for(int r=0; r<m.rows;r++)
{
for(int c=0; c<m.cols;c++)
{
o<<m.mat[r][c]<<" ";
}
o<<endl;
}
return o;
}
matrix::matrix(const char* file_name)
{
int rows=0;
int cols=0;
FILE *fp;
fp=fopen(file_name,"rb");
fseek(fp,0,SEEK_SET);
fscanf(fp,"%d",&rows);
fscanf(fp,"%d",&cols);
mat=new double*[rows];
for(int i=0;i<rows;i++)
{
mat[i]=new double[cols];
}
for(int k=0;k<rows;k++)
{
for(int j=0;j<cols;j++)
{
fscanf(fp,"%lf",&mat[k][j]);
//cout<<mat[k][j]; it works.
}
cout<<endl;
}
}
EDIT: added first constructor:
matrix::matrix(int r, int c, double n)
{
rows=r;
cols=c;
mat= new double*[rows];
for(int i=0;i<rows;i++)
{
mat[i]=new double[cols];}
for(int k=0;k<rows;k++)
{
for(int j=0;j<cols;j++)
{
mat[k][j]=n;}
}
}
It seems like your "not-working" constructor has an error indeed. That's because you have defined rows and cols as local variables, so the members rows and cols of the matrix object are not set.
Try removing those local definitions, so that the rows and cols referenced are actually your object's data members. Remove the lines:
int rows=0;
int cols=0;
Or replace them with:
rows = cols = 0;
I have a class named Matrix that contains one field that is stored dynamic. And a method named Multiply() that has to return the result of multiplying 2 Matrix. Problem is that I defined a destructor and when I return, variable which stores the resultant Matrix get some random values, I guess it happens because new variable have the same address as temporary Matrix. How can I return it correctly?
class Matrix{
double **val;
int rows,cols,errorCode;
public:
Matrix();
Matrix(int);
Matrix(int, int);
~Matrix();
void Print();
void Read();
void Realoc(int, int );
void Assign(int,int,double);
Matrix Multiply(Matrix&);
void Multiply(double);
};
Matrix Matrix::Multiply(Matrix &a){
if(cols != a.rows){
Matrix b;
b.errorCode=112; //That means matrices are not compatible;
cout<<"WARNING! Error "<<errorCode<<" has occurred. "<<endl;
return b;
}
else{
//Making a new matrix where we save computed values;
Matrix b;
b.Realoc(rows,a.cols);
//Computing values;
double p;
for(int i=0;i<rows;i++){
for(int j=0;j<a.cols;j++){
p=0;
for(int k=0;k<cols;k++){p += val[i][k]*a.val[k][j];}
b.Assign(i+1,j+1,p);
}
}
return b;
}
}
int main(){
Matrix a,b(2,2);
b.Assign(1,1,0);
b.Assign(1,2,3);
b.Assign(2,1,5);
b.Assign(2,2,5);
b.Print();
a.Read();
cout<<endl;
cout<<"'a' multiplied by 'b' is: "<<endl;
Matrix m;
m = a.Multiply(b);
m.Print();
cout<<endl;
return 0;
}
Some ideas?
P.S. I made copy constructor but it do not do any good result.
Here is a copy constructor I made.
Matrix::Matrix(Matrix &a){
rows = a.rows;
cols = a.cols;
errorCode = 0;
val = new double*[rows];
for(int i = 0;i<rows;i++){
val[i] = new double[cols];
}
for(int i=0;i<rows;i++){
for(int j=0;j<cols;j++){
val[i][j] = a.val[i][j];
}
}
}
And destructor:
Matrix::~Matrix(){
for(int i=0;i<rows;i++){
delete[] val[i];
}
delete[] val;
}
This:
m = a.Multiply(b);
Is calling the assignment operator and not the copy constructor as m has already been default constructed. The default assignment operator is not going to be good enough as you are dealing with dynamic memory allocation. You will need to implement you own assignment operator. I suggest you take a look at What is The Rule of Three?
I would also suggest you just use a 2d std::vector like std::vector<std::vector<double>> as with it the defaults provided by the compiler would work for you. As you said it is a requirement to use a double** you will need to implement the constructors and assignment operator yourself.