This is a Matrix implementation which is working now.
And I need to deallocate the memory of the *data .
But the readMatrix function is static, so I cannot delete [] the data in readMatrix.
What is the best way to do it after the readMatrix returned the *m matrix.
Matrix.cpp
#include "Matrix.h"
#include <sstream>
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
Matrix::Matrix(int i, int j) {
rows=i;
cols=j;
data = new float [i * j];
}
Matrix::Matrix(const Matrix& m) {
rows=m.rows;
cols=m.cols;
data=m.data;
}
int Matrix::numRows() {
return rows;
}
int Matrix::numCols() {
return cols;
}
float *Matrix::access(const int i, const int j) const {
return &data[(((i * cols) + j) - 1)] ;
}
std::ostream& operator<<(std::ostream &os, Matrix &m) {
int i, j;
os << m.numRows() << " " << m.numCols() <<endl;
for (i = 0; i < m.numRows(); i++) {
for (j = 0; j < m.numCols(); j++) {
os << *(m.access(i, j)) << " ";
}
os << endl;
}
return os;
}
int **Create2D(int row, int col)
{
int **p = new int* [row];
for (int j = 0; j < row; j ++)
p[j] = new int[col];
return p;
}
// Deletes an array pointed by 'p' that has 'row' number rows
void Delete2D(int **p, int row)
{
for (int j = 0; j < row; j ++)
delete [] p[j];
delete [] p;
}
Matrix Matrix::readMatrix(std::string filename)
{
int r ,c;
ifstream matrixFile(filename.c_str());
matrixFile >> r >> c;
int **p = Create2D(r, c);
Matrix* m = new Matrix(r, c);
for (int i=0; i<r; i++) {
for (int j=0; j<c; j++) {
matrixFile >> p[i][j];
*(m->access(i,j))= (float)p[i][j];
}
}
matrixFile.close();
Delete2D(p, r);
return *m;
}
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <stdlib.h>
#include <iostream>
#include <fstream>
class Matrix {
public:
Matrix(int i, int j) ;
Matrix (const Matrix& m) ;
int numRows ( ) ;
int numCols ( ) ;
float *access(const int i, const int j) const ;
friend std::ostream& operator<<(std::ostream &os, Matrix &m) ;
static Matrix readMatrix ( std::string filename ) ;
private:
Matrix() { }
// ~Matrix() { }
int rows ;
int cols ;
float *data ;
} ;
#endif // MATRIX_H
Thank you!
This here
Matrix::Matrix(const Matrix& m) {
rows=m.rows;
cols=m.cols;
data=m.data;
}
will not work well with your bare float pointer (note that it should be a float**), you end up having more instances pointing to the same data and when they go out of scope they will be deleting the same data more than once causing UB.
What you need to do in a copy constructor is to clone the data. Since you have the rows / cols it should be fairly easy.
now to your question.
This here
...
matrixFile >> p[i][j];
*(m->access(i,j))= (float)p[i][j];
...
(note that you declared access with const at the end (float *access(const int i, const int j) const), this means that the above assignment is illegal, const after the method means the instance will not be affected but you are using it to assign it a value)
seems unnecessary since you are reading one float at a time, it would be enough just to have a single float variable which you use to read the value from the file then assign your matrix that value
...
matrixFile >> floatRead;
*(m->access(i,j))= floatRead;
...
so just ditch the whole p matrix.
Alt. read in the values in the p matrix then let the Matrix instance m take ownership of it.
e.g.
...
m->attachMatrixValues(p);
...
Related
Im trying to create an operator that gives me the value for the position i,j of a certain matrix and another one that "fills" the matrix in the given positions, ive tried to put the operator that you can see in the header but it isnt working, the problem might be somewhere else but i think this it the main issue:
int main()
{
matriz a(3,3);
matrizQuad b(3);
for(size_t i=0;i<3;++i)
for(size_t j=0;j<3;++j){
a[i][j]=1;
b[i][j]=2;
}
matriz c=a+b;
cout << "a+b:\n" << c << "\n";
cout << "traco: " << b.traco() << "\n";
return 0;
} ```
Header:
#ifndef MATRIZES_H
#define MATRIZES_H
#include <iostream>
#include <vector>
#include <ostream>
#include <sstream>
using namespace std;
typedef vector<vector<double>> array;
class matriz
{
protected:
int iLargura, iComprimento;
array m;
public:
matriz(int L, int C): iLargura (L), iComprimento (C)
{
array m(L);
for (int i = 0; i<L;i++)
m[i].resize(C);
};
int nL() const {return iLargura;}
int nC() const {return iComprimento;}
vector<double>& operator[] (int i) {return m[i];}
const vector<double>& operator[] (int i) const {return m[i];}
};
class matrizQuad: public matriz
{
public:
matrizQuad (int T): matriz(T,T) {}
double traco();
};
matriz operator+(const matriz& m1, const matriz& m2);
ostream& operator<<(ostream& output, const matriz& m1);
#endif // MATRIZES_H
Body:
#include "matriz.h"
double matrizQuad::traco()
{
double dSoma = 0;
for (int i = 0;i<iLargura; i++)
for (int j = 0;i<iLargura; i++)
if (i==j)
dSoma = dSoma + m[i][j];
return dSoma;
}
matriz operator+(const matriz& m1, const matriz& m2)
{
int C1 = m1.nC();
int L1 = m1.nL();
matriz m(C1,L1);
for (int i = 0;i<C1; i++)
for (int j = 0;i<L1; i++)
m[i][j] = m1[i][j] + m2[i][j];
return m;
}
ostream& operator<<(ostream& output, const matriz& m1)
{
for(int i = 0; i< m1.nL();i++)
{
for (int j=0;j<m1.nC();j++)
output << m1[i][j] << " ";
output << "\n";
}
return output;
}
Fixing the array resize as 463035818_is_not_a_number suggested gives you a somewhat working matrix.
matriz(int L, int C): iLargura (L), iComprimento (C)
{
m.resize(L);
for (int i = 0; i<L;i++)
m[i].resize(C);
};
If you also print the matrixes a and b you get:
a:
1 1 1
1 1 1
1 1 1
b:
2 2 2
2 2 2
2 2 2
a+b:
3 0 0
3 0 0
3 0 0
So setting and printing matrixes works just fine. The error is in the operator +:
matriz operator+(const matriz& m1, const matriz& m2)
{
int C1 = m1.nC();
int L1 = m1.nL();
matriz m(C1,L1);
for (int i = 0;i<C1; i++)
for (int j = 0;i<L1; i++)
m[i][j] = m1[i][j] + m2[i][j];
return m;
}
specifically:
for (int j = 0;i<L1; i++)
I guess you copy&pasted the previous loop for i and forgot to rename all the variables.
Your class has a member
array m;
This nested vector is never resized. It has size 0.
In the constructor you declare a nested vector of same name
array m(L);
Whose inner vectors you resize in the constructor. Any subsequent access to the members inner vectors elements is out of bounds.
Do not declare another nested vector of same name in the constructor, but instead resize the member.
Note that array is rather misleading for a std::vector<std::vector<double>>. Moreover a nested vector is not an efficient 2d data structure. Anyhow, it is also not clear what your matriz does that you cannot already get from the std::vector<std::vector<double>>.
I'm just going to preface this with the fact that I'm new to C++ so it's quite possible there's just a stupid error here, but I can't find it.
I'm just trying to overload the increment operator in a friend function. Everything compiles perfectly and everything works if I explicitly call the postfix increment overload:
operator++(*test, 0);
Every element in the matrix is incremented and the program prints it out using cout perfectly. The problem is when I try to do the normal ++ increment test++; it appears as though something wrong happens with the test pointer to where when it tries to print the test object it doesn't print anything.
Any idea what's going on? I'm clueless. Here's the code I'm working with...
Compile & Run
g++ -o App App.cpp Matrix.cpp
./App
App.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
#define X 9
int main(int argc, char *argv[])
{
// Start the actual program here
Matrix* test = new Matrix(3,3);
// Row 1
test->setElement(0,0,1);
test->setElement(0,1,2);
test->setElement(0,2,3);
// Row 2
test->setElement(1,0,4);
test->setElement(1,1,5);
test->setElement(1,2,6);
// Row 3
test->setElement(2,0,7);
test->setElement(2,1,8);
test->setElement(2,2,9);
operator++(*test, 0);
//test++;
//++test;
// Print the Matrix object
cout << *test << endl;
}
Matrix.h
#ifndef MATRIX_H
#define MATRIX_H
#include <iostream>
using namespace std;
class Matrix {
friend ostream& operator<<(ostream&, const Matrix&);
friend Matrix& operator++(Matrix&); // prefix increment
friend Matrix& operator++(Matrix&, int); // postfix increment
private:
int rows;
int cols;
int** elements;
public:
// Constructors
Matrix(int);
Matrix(int,int);
Matrix(const Matrix&);
// Define setters
void setElement(int,int,int);
// Define getters
int getRowCount();
int getColCount();
int getElementAt(int,int);
void increment();
// Destructor
~Matrix();
};
#endif
Matrix.cpp
#include <iostream>
#include "Matrix.h"
using namespace std;
//===================================
// DEFINE [CON]/[DE]STRUCTORS
//===================================
// Constructor for creating square matricies
Matrix::Matrix(int _size) {
rows = _size;
cols = _size;
elements = new int*[_size];
for (int i = 0; i < _size; i++) {
elements[i] = new int[_size];
}
}
// Constructor for supporting non-square matricies
Matrix::Matrix(int _rows, int _cols) {
rows = _rows;
cols = _cols;
elements = new int*[_rows];
for (int i = 0; i < _rows; i++) {
elements[i] = new int[_cols];
}
}
// Copy constructor
Matrix::Matrix(const Matrix& mat1) {
Matrix(mat1.rows, mat1.cols);
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
elements[i][j] = mat1.elements[i][j];
}
}
}
// Destructor
Matrix::~Matrix() {
for (int i = 0; i < rows; i++) {
delete[] elements[i];
}
delete[] elements;
}
//===================================
// DEFINE SETTER FUNCTIONS
//===================================
void Matrix::setElement(int row, int col, int newElement) {
if (row > rows-1 || row < 0)
throw "Row out of index";
if (col > cols-1 || col < 0)
throw "Column out of index";
elements[row][col] = newElement;
}
//===================================
// DEFINE GETTER FUNCTIONS
//===================================
int Matrix::getRowCount() { return rows; }
int Matrix::getColCount() { return cols; }
int Matrix::getElementAt(int row, int col) {
if (row > rows-1 || row < 0)
throw "Row out of index";
if (col > cols-1 || col < 0)
throw "Column out of index";
return elements[row][col];
}
//===================================
// OVERRIDE OPERATOR FUNCTIONS
//===================================
// Print the Matrix to the output stream
ostream& operator<<(ostream& out, const Matrix& mat) {
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
out << mat.elements[i][j] << " ";
}
out << endl;
}
return out;
}
// Prefix. Increment immediately and return the object.
Matrix& operator++(Matrix& mat) {
cout << "Prefix ++ operator" << endl;
// Increment all elements in the object by 1
for (int i = 0; i < mat.rows; i++) {
for (int j = 0; j < mat.cols; j++) {
mat.elements[i][j] += 1;
}
}
return mat;
}
// Postfix. Return the current object and "save" the incremented.
Matrix& operator++(Matrix& mat, int x) {
cout << "Postfix ++ operator" << endl;
// Save the current values
Matrix* curVals = new Matrix(mat);
// Increment the object
++(mat);
// Return the unincremented values
return *curVals;
}
test++ increments the value of test, so that it will point to the memory after your Matrix object. You need to dereference the pointer to get a Matrix object, then apply the increment to that.
What you want is (*test)++ or ++*test.
I'm trying to figure out why my program fails when I run. So far when I run my program it fails on me. I debugged the error and it brings me to dbgdel.cpp. Line 32 " _ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));". I've searched for the answer to no avail, but it has something to do with my memory leak?
Here is my header:
#include <iostream>
using namespace std;
namespace project
{
#ifndef MATRIX_H
#define MATRIX_H
typedef int* IntArrayPtr;
class Matrix
{
public:
friend ostream& operator<<(ostream& out, Matrix& object);
//friend istream& operator>>(istream& in, Matrix& theArray);
//Default Constructor
Matrix();
Matrix(int max_number_rows, int max_number_cols, int intial_value);
//Destructor
~Matrix();
//Copy Constructor
Matrix(const Matrix& right_side);
//Assignment Operator
Matrix& operator=(const Matrix& right_side);
void Clear();
int Rows();
int Columns();
bool GetCell(int x,int y, int& val);
bool SetCell(int x,int y, int val);
int getNumber(int r, int c);
//void Debug(ostream& out);
private:
int initialVal;
int rows;
int cols;
IntArrayPtr *m;
};
#endif
}
My implementation file:
#include <iostream>
#include "Matrix.h"
using namespace project;
using namespace std;
namespace project
{
Matrix::Matrix()
{
typedef int* IntArrayPtr;
IntArrayPtr *m = new IntArrayPtr[1];
for(int i = 0; i < 1; i++)
m[i] = new int[1];
for(int r = 0; r < 1; r++)
for(int c = 0; c < 1;c++)
m[r][c] = 0;
}
Matrix::Matrix(int max_number_rows, int max_number_cols, int initial_value)
{
initialVal = initial_value;
rows = max_number_rows;
cols = max_number_cols;
IntArrayPtr *m = new IntArrayPtr[rows];
for(int i = 0; i < rows; i++)
m[i] = new int[cols];
for(int r = 0; r < max_number_rows; r++)
for(int c = 0; c < max_number_cols;c++)
m[r][c] = initial_value;
}
Matrix::~Matrix()
{
for(int i = 0; i <= rows; i++)
delete [] m[i];
delete [] m;
}
void Matrix::Clear()
{
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols;c++)
m[r][c] = initialVal;
}
int Matrix::Rows()
{
return rows;
}
int Matrix::Columns()
{
return cols;
}
bool Matrix::GetCell(int x,int y, int& val)
{
if(x < rows || y < cols)
return false;
else
{
val = m[x - 1][y - 1];
return true;
}
}
bool Matrix::SetCell(int x, int y, int val)
{
if(x < rows || y < cols)
return false;
else
{
m[x - 1][y - 1] = val;
return true;
}
}
int Matrix::getNumber(int r, int c)
{
return m[r][c];
}
ostream& operator<<(ostream& out, Matrix& object)
{
for(int r = 0; r < object.rows; r++)
{
for(int c = 0; c < object.cols; c++)
{
out << " " << object.m[r][c];
}
out << endl;
}
return out;
}
Matrix& Matrix::operator=(const Matrix& right_side)
{
if (this != &right_side)
{
rows = right_side.rows;
cols = right_side.cols;
delete[] m;
IntArrayPtr *m = new IntArrayPtr[rows];
for(int i = 0; i < rows; i++)
m[i] = new int[cols];
for(int r = 0; r < rows; r++)
for(int c = 0; c < cols;c++)
m[r][c] = right_side.initialVal;
}
return *this;
}
/*
void Matrix::Debug(ostream& out)
{
out << "Number of rows = " << rows << endl;
out << "Number of columns = " << cols << endl;
out << "Initializer = " << initialVal << endl;
out << "Current contents of the matrix: " << endl;
out << m << endl;
}
*/
/*
istream& operator >>(istream& in, Matrix& theArray)
{
in >>
}
void interfaceMatrix()
{
int userChoice, rows, columns, value;
cout << "Default matrix or custom(1 for default, 0 for custom): ";
cin >> userChoice;
if (userChoice == 1)
{
Matrix object;
return object;
}
else if(userChoice == 0)
{
cout << "Enter number of rows: ";
cin >> rows;
cout << "Enter number of columns: ";
cin >> columns;
cout << "Enter initial value of each element: ";
cin >> value;
if(rows <= 0 || columns <= 0)
{
cout << "Invalid input." << endl;
exit(1);
}
else
{
Matrix object(rows, columns, value);
return object;
}
}
else
{
cout << "Invalid choice." << endl;
exit(1);
}
}
*/
}
In my driver I just put Matrix test(2,2,2), so I can create a 2 x 2 array with initial value of 2 for each element. I get the above error.
You are allocating rows number of rows, but deallocating rows+1 number of rows.
Check the destructor. <= must be <.
Besides this there are a lot of other [potential] errors in your code:
you are setting the local m variable instead of setting the m data member of your class (that's why I have the convention to always precede data members by m_ to prevent this kind of confusion). This error appears both in the constructor and the assignment operator.
you use rows to allocate the matrix, but max_number_rows to initialize the matrix. Although it works correctly now, it may lead to errors if row is initialized differently later (e.g. if row is initialized with std::max(max_number_rows,1000). Your code in the assignment operator is better.
your if-test in GetCell and SetCell is incorrect. It should probably be >= instead of <
the assignment operator copies the size of the matrix, but assigns all cells an initialValue. This is not an assignment. This implementation might/will confuse the rest of the code.
the typedef of IntArrayPtr is unnecessary
two issues:
You are not allocating any value into the "m" member of your object, you are allocating into local variables named "m"
you are over deallocating by looping from i=0 to i <= rows, you want i=0 to i < rows
I am trying to define a simple class to work with 2d matrices, called Matrix2D01, and having trouble with the + operator.
I have the += operator which is working fine,
Matrix2D01& Matrix2D01::operator+=(Matrix2D01& mat2) {
int i,j;
for (i=0;i<M;i++)
for (j=0;j<N;j++) mat[i][j]+=mat2[i][j];
return *this;
}
The + operator is defined:
Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) {
Matrix2D01 result(1,1);
result=*this;
result+=mat2;
return result;
}
When i try to use the + operator, for example by
mat3=mat1+mat2;
the compiler gives an error:
../MatrixGames.cpp:17:12: error: no match for ‘operator=’ in ‘mat3 = Matrix2D01::operator+(Matrix2D01&)((* & mat2))’
If anyone can tell me what I'm doing wrong it will be greatly appreciated.
Thanks.
I also have a = operator defined,
Matrix2D01& Matrix2D01::operator=(Matrix2D01& mat2) {
if (this==&mat2) return *this;
int i,j;
for (i=0;i<M;i++) {
delete [] mat[i];
}
delete [] mat;
M=mat2.Dimensions()[0];
N=mat2.Dimensions()[1];
mat = new double* [M];
for (i=0;i<M;i++) {
mat[i]=new double [N];
}
for (i=0;i<M;i++)
for (j=0;j<M;j++)
mat[i][j]=mat2[i][j];
return *this;
}
here is a complete test case:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
#include <vector>
using namespace std;
class Matrix2D01 {
protected:
int D;
double **mat;
int M,N;
public:
Matrix2D01(int m,int n);
Matrix2D01(int m,int n,double d);
~Matrix2D01();
vector <int> Dimensions() {vector <int> d(D,M); d[1]=N; return d;}
double* operator[](int i) {return mat[i];}
Matrix2D01& operator=(Matrix2D01& mat2);
Matrix2D01& operator+=(Matrix2D01& mat2);
Matrix2D01 operator+(Matrix2D01& mat2);
};
Matrix2D01::Matrix2D01(int m, int n) {
int i,j;
D=2;
M=m;
N=n;
mat = new double* [M];
for (i=0;i<M;i++) {
mat[i]=new double [N];
}
for (i=0;i<M;i++)
for (j=0;j<M;j++)
mat[i][j]=0;
}
Matrix2D01::Matrix2D01(int m, int n,double d) {
int i,j;
D=2;
M=m;
N=n;
mat = new double* [M];
for (i=0;i<M;i++) {
mat[i]=new double [N];
}
for (i=0;i<M;i++)
for (j=0;j<M;j++)
mat[i][j]=d;
}
Matrix2D01::~Matrix2D01() {
int i;
for (i=0;i<M;i++) {
delete [] mat[i];
}
delete [] mat;
}
Matrix2D01& Matrix2D01::operator=(Matrix2D01& mat2) {
if (this==&mat2) return *this;
int i,j;
for (i=0;i<M;i++) {
delete [] mat[i];
}
delete [] mat;
M=mat2.Dimensions()[0];
N=mat2.Dimensions()[1];
mat = new double* [M];
for (i=0;i<M;i++) {
mat[i]=new double [N];
}
for (i=0;i<M;i++)
for (j=0;j<M;j++)
mat[i][j]=mat2[i][j];
return *this;
}
Matrix2D01& Matrix2D01::operator+=(Matrix2D01& mat2) {
int i,j,M2,N2;
M2=mat2.Dimensions()[0];
N2=mat2.Dimensions()[1];
if ((M!=M2)||(N!=N2)) {
cout<<"error: attempted to add non-matching matrices";
return *this;
}
for (i=0;i<M;i++)
for (j=0;j<N;j++) mat[i][j]+=mat2[i][j];
return *this;
}
Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) {
Matrix2D01 result(1,1);
result=*this;
result+=mat2;
return result;
}
int main() {
Matrix2D01 mat1(2,2,1);
Matrix2D01 mat2(2,2,2);
Matrix2D01 mat3(2,2,4);
mat3+=mat1;
mat3=mat1+mat2;
return 1;
}
Herb Sutter advocates the following canonical way to overload operator + (please read GotW, it is really well written and interesting):
Don't include operator + as a member function, instead make it a free function.
Pass one object by value and the other by const reference. This makes it possible to use move operators when you add to a temporary.
Implement in terms of operator +=:
Matrix2D01 operator+(Matrix2D01 a, const Matrix2D01 &b)
{
a += b;
return a;
}
I've posted the code of the Matrix class I had written for an assignment on Discrete Mathematics last Sem
Notice how the assignment operator and the copy constructor are implemented All you need to do is write an assignment operator (I'd recommend that you write a copy constructor as well)
#pragma once
#include <vector>
#include <istream>
#include <ostream>
class Matrix
{
private:
unsigned int rows, cols;
std::vector<std::vector<int> > matrix;
public:
// Creates a Matrix with the given dimensions and sets the default value of all the elements to 0
Matrix(unsigned int rows, unsigned int cols);
// Destructor
~Matrix();
// Converts the relation set into it's adjacency Matrix representation
static Matrix CreateFromRelationSet( std::vector<std::pair<int, int> > relationSet);
// Copy Constructor
Matrix(const Matrix& cSource);
// Assignment Operator
Matrix& operator=(const Matrix& cSource);
// Resets all the elements of the matrix to 0
void Reset();
// Resizes the matrix to the given size
void Resize(unsigned int rows, unsigned int cols);
// Returns the number of rows
unsigned int getRows();
// Returns the number of columns
unsigned int getCols();
// Returns the smallest element from the matrix
int getSmallestElement();
// Returns the greatest element from the matrix
int getGreatestElement();
// Returns true if element is found and sets the row and column
// Returns false if not found
bool getPosition(int element, int* i, int* j);
// Deletes a row from the Matrix
void DeleteRow(unsigned int row);
// Deletes a column from the Matrix
void DeleteColumn(unsigned int col);
// Returns the element at (i,j)
int& operator()(unsigned int i, unsigned j);
// Returns the element at (i,j). Use the () operators instead
int getElementAt(unsigned int i, unsigned j);
friend std::ostream& operator << (std::ostream& out, Matrix& m);
friend std::istream& operator >> (std::istream& in, Matrix& m);
Matrix operator + (Matrix M);
Matrix operator - (Matrix M);
Matrix operator * (Matrix M);
};
// For use with cin & cout
std::ostream& operator << (std::ostream& out, Matrix& m);
std::istream& operator >> (std::istream& in, Matrix& m);
#include "Matrix.h"
Matrix::Matrix(unsigned int rows, unsigned int cols)
{
this->rows = rows;
this->cols = cols;
matrix.resize(rows);
for(std::vector<int>& i: matrix)
i.resize(cols);
Reset();
}
Matrix::~Matrix()
{
}
// local helper function
int findMaxFromSet(std::vector<std::pair<int, int> > set)
{
int maxVal = 0;
for(unsigned int i = 0; i < set.size(); i ++)
{
int p = set[i].first > set[i].second ? set[i].first : set[i].second;
maxVal = maxVal > p ? maxVal : p;
}
return maxVal;
}
Matrix Matrix::CreateFromRelationSet (std::vector<std::pair<int, int> > relationSet)
{
int max = findMaxFromSet(relationSet);
Matrix M(max,max);
M.Reset();
for(auto i = relationSet.begin(); i != relationSet.end(); ++ i)
M(i->first - 1, i->second - 1) = 1;
return M;
}
void Matrix::Reset()
{
for (auto& i: matrix)
for(auto& j: i)
j = 0;
}
void Matrix::Resize(unsigned int rows, unsigned int cols)
{
matrix.resize(rows);
for(auto& i:matrix)
i.resize(cols);
}
unsigned int Matrix::getRows()
{
return rows;
}
unsigned int Matrix::getCols()
{
return cols;
}
Matrix::Matrix(const Matrix& cSource)
{
rows = cSource.rows;
cols = cSource.cols;
matrix = cSource.matrix;
}
bool Matrix::getPosition(int element, int* i, int* j)
{
for(unsigned int ii = 0; ii < getRows(); ii ++)
for(unsigned int jj = 0; jj < getCols(); jj ++)
if(matrix[ii][jj] == element)
{
*i = ii;
*j = jj;
return true;
}
return false;
}
Matrix& Matrix::operator=(const Matrix& cSource)
{
// check for self-assignment
if (this == &cSource)
return *this;
if(this->getRows() < cSource.rows)
{
this->rows = cSource.rows;
this->matrix.resize(cSource.rows);
}
if(this->getCols() < cSource.cols)
{
this->cols = cSource.cols;
for(auto& i:this->matrix)
i.resize(cSource.cols);
}
for(unsigned int i = 0; i < rows; i++)
for(unsigned int j = 0; j < cols; j++)
this->matrix[i][j] = const_cast<Matrix&>(cSource)(i,j);
return *this;
}
std::ostream& operator << (std::ostream& out, Matrix& m)
{
for(auto& i: m.matrix)
{
for(auto& j: i)
out<<j<<'\t';
out<<std::endl;
}
return out;
}
std::istream& operator >> (std::istream& in, Matrix& m)
{
for(auto& i: m.matrix)
for(auto& j: i)
in>>j;
return in;
}
Matrix Matrix::operator + (Matrix op)
{
// Find the rows and cols of the new matrix
unsigned int r = this->getRows() > op.getRows()?this->getRows():op.getRows();
unsigned int c = this->getCols() > op.getCols()?this->getCols():op.getCols();
// Create Matrices
Matrix A = *this;
Matrix B = op;
Matrix R(r,c);
// Assign values
for(unsigned int i = 0; i < A.rows; i++)
for(unsigned int j = 0; j < A.cols; j++)
R(i,j) = A(i,j) + B(i,j);
return R;
}
Matrix Matrix::operator - (Matrix op)
{
// Find the rows and cols of the new matrix
unsigned int r = this->getRows() > op.getRows()?this->getRows():op.getRows();
unsigned int c = this->getCols() > op.getCols()?this->getCols():op.getCols();
// Create Matrices
Matrix A = *this;
Matrix B = op;
Matrix R(r,c);
// Assign values
for(unsigned int i = 0; i < A.rows; i++)
for(unsigned int j = 0; j < A.cols; j++)
R(i,j) = A(i,j) - B(i,j);
return R;
}
Matrix Matrix::operator* (Matrix op)
{
Matrix A = *this;
Matrix B = op;
if(A.getCols() != B.getRows())
throw std::exception("Matrices cannot be multiplied");
Matrix M(A.getRows(), B.getCols());
for(unsigned int i=0 ; i<A.getRows() ; i++)
for(unsigned int j=0 ; j<B.getCols() ; j++)
for(unsigned int k=0 ; k<B.getRows() ; k++)
M(i,j) = M(i,j) + A(i,k) * B(k,j);
return M;
}
int& Matrix::operator()(unsigned int i, unsigned j)
{
return matrix[i][j];
}
int Matrix::getElementAt(unsigned int i, unsigned j)
{
return (*this)(i,j);
}
int Matrix::getSmallestElement()
{
int result = matrix[0][0];
for(auto i:matrix)
for(auto j : i)
if(j < result)
result = j;
return result;
}
int Matrix::getGreatestElement()
{
int result = matrix[0][0];
for(auto i:matrix)
for(auto j : i)
if(j > result)
result = j;
return result;
}
void Matrix::DeleteRow(unsigned int row)
{
matrix.erase(matrix.begin() + row);
rows --;
}
void Matrix::DeleteColumn(unsigned int col)
{
for(auto& i: matrix)
i.erase(i.begin() + col);
cols --;
}
UPDATE:
result=*this;
In your code you are trying to allocate result the value of *this using the assignment operator, but no assignment operator is defined and the compiler doesn't find a match
Writing an assignment operator overload will solve this issue.
And if you have a copy constructor you can do something like:
Matrix2D01 Matrix2D01::operator+(Matrix2D01& mat2) {
Matrix2D01 result = *this;
result+=mat2;
return result;
}
Writing Assignment Operators: http://www.learncpp.com/cpp-tutorial/912-shallow-vs-deep-copying/
And if you're interested in the details - here you go: http://www.icu-project.org/docs/papers/cpp_report/the_anatomy_of_the_assignment_operator.html
Your operands should be const references. Otherwise, you
can't use a temporary to initialize them. (In this case, the
return value of operator+ is a temporary, and thus, cannot be
bound to the non-const reference of operator=.)
If your operator+ is a member, it should be const as well.
After all, it doesn't modify the object it is called on. So:
Matrix2D01& Matrix2D01::operator=( Matrix2D01 const& mat2 );
Matrix2D01& Matrix2D01::operator+=( Matrix2D01 const& mat2 );
Matrix2D01 Matrix2D01::operator+( Matrix2D01 const& mat2 ) const;
Also, your assignment operator is broken. (Think of what will
happen, if one of the allocations fails after you've freed the
original data.) In general, if you have to test for self
assignment, the assignment operator is broken.
CPP
#include "del2.h"
Matrix::Matrix()
{
dArray = NULL;
}
bool Matrix::isValid() const
{
if (dArray == NULL)
return false;
return true;
}
Matrix::~Matrix()
{
delete [] dArray;
}
Matrix::Matrix(unsigned int nRows)
{
rows = nRows;
columns = nRows;
dArray = new double[nRows * nRows];
for (unsigned int i = 0; i < nRows; i++)
{
for (unsigned int n = 0; n < nRows; n++)
{
at(i,n) = 0;
}
}
at(0,0) = 1;
at(rows-1,columns-1) = 1;
}
Matrix::Matrix(unsigned int nRows, unsigned int nColumns)
{
dArray = new double[nRows * nColumns];
rows = nRows;
columns = nColumns;
for (unsigned int i = 0; i < nRows; i++)
for (unsigned int n = 0; n < nColumns; n++)
dArray[i * columns + n] = 0;
}
const Matrix Matrix::operator =(const Matrix & rhs)
{
columns = rhs.getColumns();
rows = rhs.getRows();
delete [] dArray;
dArray = new double[rows * columns];
for (int row = 0; row < rows; row++)
for (int column = 0; column < columns; column++)
at(row,column) = rhs.at(row,column);
return *this;
}
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint )
{
if (!classPrint.isValid())
return out;
int rows = classPrint.getRows();
int columns = classPrint.getColumns();
out << std::endl;
for (int i = 0; i < rows; i++)
{
out << "| ";
for (int n = 0; n < columns; n++)
out << classPrint.at(i,n) << " ";
out << "|" << std::endl;
}
out << endl;
return out;
}
HEADER:
#ifndef DEL2
#define DEL2
#include <iostream>
using namespace std;
class Matrix
{
private:
int rows;
int columns;
double * dArray;
public:
~Matrix();
Matrix();
explicit Matrix(unsigned int nRows);
Matrix(unsigned int nRows, unsigned int nColumns);
const Matrix operator =(const Matrix & rhs);
const double at(int row, int column) const
{ return dArray[ row*this->columns + column ]; }
double & at( int row, int column )
{ return dArray[ row*this->columns + column ]; }
const int getRows() const {return rows;}
const int getColumns() const {return columns;}
bool isValid() const;
};
std::ostream & operator <<( std::ostream & out, const Matrix & classPrint );
#endif // MATRIX
Main:
#include <iostream>
#include "del2.h"
using namespace std;
int main()
{
Matrix A;
Matrix B(10);
A = B;
cout << A;
return 0;
}
When I run this, the following happens:
The first index, matrix[0] of A, always becomes some weird number like 2.22323e-306. I don't understand why. Even when I try to set "at(0,0) = 1;" in the operator = - function after the loop, it still doesn't have 0.
The problem is here
const Matrix operator =(const Matrix & rhs);
should be
const Matrix& operator =(const Matrix & rhs);
and the definition should be
const Matrix& Matrix::operator =(const Matrix & rhs)
{
if (&rhs == this)
return *this;
Otherwwise operator= is returning a copy of the Matrix which will have dArray same as the original Matrix. Your data will be deleted when the temporary returned array goes out of scope.
Be carefull the operator = is not correct
Matrix & operator = (const Matrix & rhs){
if (&rhs != this){
// Your stuff here
}
return *this;
}
Calling delete [] on a null array is undefined. It can crash.
You must also define the copy constructor