Template matrix with char* consol stop responding when using operator= - c++

i need some help. This is my first that hugh program in c++ (pointers are nightmare). I tried everything and i can't find what i did wrong.
class aghMatrix {
private:
T ** matrix;
int n;
int m;
public:
aghMatrix() : n(0), m(0) {};
aghMatrix(int _n, int _m);
aghMatrix(const aghMatrix& other);
~aghMatrix();
void setItem(int n, int m, T item);
void setItems (T * wsk);
void setItems(int r, int c ...);
void setAll();
void getALL();
bool couldbeadded(char * word, char sign);
bool equals (T first, T second);
T operator()(int a, int b);
aghMatrix<T> & operator+(const aghMatrix<T> & other);
aghMatrix<T> & operator*(const aghMatrix<T> & other);
aghMatrix<T> & operator= ( const aghMatrix<T> & other);
bool operator== (const aghMatrix<T> & other);
bool operator!= (const aghMatrix<T> & other);
};
Test :
char* cpt[] = {"to", "jest", "tablica", "wyrazow", "o", "rozmiarze", "jedenascie", "ktore", "beda", "elementami", "macierzy"};
aghMatrix<char*> cpm3(3, 1);
aghMatrix<char*> cpm4;
cpm3.setItems(cpt+3);
cpm4 = cpm3; // here my consol stop responding.
Constructors :
//default
aghMatrix() : n(0), m(0) {};
//with param
template <class T>
aghMatrix<T>::aghMatrix(int _n, int _m)
{
n = _n;
m = _m;
matrix = new T * [n];
for (int i = 0; i < n; i ++)
{
matrix[i] = new T[m];
}
}
setitems:
template <class T>
void aghMatrix<T>::setItems (T * wsk)
{
int licznik = 0;
for(int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
matrix[i][j] = wsk[licznik];
licznik ++;
}
}
}
Operator= for char*
template <>
aghMatrix<char*> & aghMatrix<char*>::operator= ( const aghMatrix<char*> & other)
{
if ( & other != this)
{
if ( (other.n == n) && (other.m == m) && (this->matrix != 0))
{
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
for(int ii = 0; ii < strlen(other.matrix[i][j]); ii++)
{
matrix[i][j][ii] = other.matrix[i][j][ii];
}
}
}
}
else
{
if(this->matrix)
{
for (int i = 0; i < n; i ++)
{
for (int j = 0; j < m; j ++)
{
delete [] matrix[i][j];
}
delete [] matrix[i];
}
delete [] matrix;
n = 0;
m = 0;
matrix = NULL;
}
n = other.n;
m = other.m;
matrix = new char **[n];
for(int i = 0; i < n; i ++)
{
matrix[i] = new char*[m];
}
for(int i = 0; i < n; i ++)
{
for(int j = 0; j < m; j ++)
{
matrix[i][j] = new char[strlen(other.matrix[i][j])];
for(int ii = 0; ii < strlen(other.matrix[i][j]); ii ++)
{
matrix[i][j][ii] = other.matrix[i][j][ii];;
}
}
}
}
}
return *this;
}
I tried everything and still i'm getting this problem with console (it looks like i'm using somewhere uninitialized memory or sth). I cant solve this problem alone is alone can anybody help me?
EIDT: One more thing : The error shows when the program comes to end and after i change destructor :
Now looks like this :
template
aghMatrix<T>::~aghMatrix()
{
if (matrix)
{
for (int i = 0; i < n; i ++)
{
delete [] matrix[i];
}
delete [] matrix;
matrix = NULL;;
n = 0;
m = 0;
}
}
the previous version of destructor :
template <class T>
aghMatrix<T>::~aghMatrix()
{
if (matrix =! 0)
{
for (int i = 0; i < n; i ++)
{
delete [] matrix[i];
}
delete [] matrix;
matrix = 0;
}
}
maybe here is the reason of error?
EDIT:---------------------
I found the reason of my error here it is:
when i create
aghMatrix<char*> cpm3(3, 1);
cpm4 = cpm3; //destructor create a problem
but when i do something like this:
aghMatrix<char*>cpm3(3,2); //or somekind of other number than '1'
cpm4 = cpm3; // everything works fine
any ideas?

Related

0xC0000005: Access violation reading location 0xFDFDFDED

So I wrote this:
Matrix.h:
#pragma once
class Matrix
{
private:
int m, n;
double** M = nullptr;
public:
Matrix();
Matrix(int,int);
Matrix(const Matrix&);
~Matrix();
void set_m(int);
void set_n(int);
int get_m() const;
int get_n() const;
void setM(double**,int,int);
double** getM() const;
void show();
Matrix operator*(Matrix&) const;
};
Matrix.cpp:
#include "Matrix.h"
#include<iostream>
using namespace std;
/*
*/
Matrix::Matrix()
{
set_n(1);
set_m(1);
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(int m_,int n_)
{
set_n(n_);
set_m(m_);
delete[] M;
M = new double *[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = 1.0;
}
Matrix::Matrix(const Matrix& M_)
{
set_n(M_.get_n());
set_m(M_.get_m());
delete[] M;
M = new double*[get_m()];
for (int i = 0; i < m; i++) {
M[i] = new double[get_n()];
}
for (int i = 0; i < m; i++)
for (int j = 0; j < n; j++) M[i][j] = M_.getM()[i][j];
}
void Matrix::set_m(int m_) {
if (m_ > 0)
m = m_;
else
m = 1;
}
void Matrix::set_n(int n_) {
if (n_ > 0)
n = n_;
else
n = 1;
}
double** Matrix::getM() const {
return M;
}
Matrix Matrix::operator*(Matrix &M_) const
{
if (get_n() != M_.get_m()) {
if (get_m() != M_.get_n()) return Matrix();
else {
Matrix T(*this);
return M_*T;
}
}
else {
//n = m
Matrix R(get_m(), M_.get_n());
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < M_.get_n(); j++) {
double res = 0;
for (int k = 0; k < get_n(); k++) {
res += getM()[i][k] * M_.getM()[k][j];
}
R.getM()[i][j] = res;
}
}
return R;
}
}
int Matrix::get_m() const {
return m;
}
int Matrix::get_n() const {
return n;
}
void Matrix::setM(double** M_, int m_, int n_) {
set_m(m_);
set_n(n_);
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
M = new double*[m_];
for (int i = 0; i < m; i++) {
M[i] = new double[n_];
}
for (int i = 0; i < m_; i++)
for (int j = 0; j < n_; j++) M[i][j] = M_[i][j];
}
void Matrix::show() {
for (int i = 0; i < get_m(); i++) {
for (int j = 0; j < get_n(); j++) {
cout << getM()[i][j]<<" ";
}
cout << endl;
}
}
Matrix::~Matrix()
{
for (int i = 0; i < get_m(); i++) {
delete M[i];
}
delete[] M;
}
It crashes at void Matrix::setM(...) when I try to delete M[i] for i = 1; it doe perfectly fine for i=0; but crashes later and I do not have a rational explanation why does it do that. I can see the debugger showing me that the memory cannot be read even before it actually crashing but I do not understand how to fix it. Thanks in advance!
You are setting your m before deleting your array based on the old value of m and end up deleting your old array using the new value of m. You should first delete your array, then set mm, and then create your new array.

Debug Assertion Failed error

I'm trying to overload the + operator for a project that I'm doing but this keeps on happening. I think the reason is that the object I created is getting deleted when the operator is getting invoked. Not sure how to fix it though. Here's part of my code:
Matrix Matrix::operator+ (const Matrix& m) const
{
//something wrong here
Matrix sum(rows, cols);
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
sum.element[i][j] = this->element[i][j] + m.element[i][j];
}
}
return sum;
}
Additional Information
Matrix::Matrix(int r, int c)
{
rows = r;
cols = c;
element = new int *[c];
for (int i = 0; i < c; i++)
{
element[i] = new int[r];
}
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
element[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& m)
{
this->element = m.element;
}
Matrix::~Matrix()
{
//freeing up the arrays
for (int i = 0; i < cols; i++)
{
delete[] element[i];
element[i] = NULL;
}
delete[] element;
element = NULL;
}
Matrix& Matrix::operator= (const Matrix& m)
{
//problem if rows and cols are longer in the new matrix
//need to create a temp matrix to expand to new one
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
{
this->element[i][j] = m.element[i][j];
}
}
return *this;
}
int* Matrix::operator[] (int n)
{
return element[n];
}
The specific error I am getting is:
Debug Assertion Failed!
Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)
In line 52 which I did this:
Matrix total = mat + m;
Where mat and m are both object matrices
I'm guessing the problem is caused by this:
Matrix::Matrix(const Matrix& m)
{
this->element = m.element;
}
That is an invalid copy constructor for two reasons. First, you're not initializing rows or cols. Second, you'll now have two Matrix objects pointing to the same memory - both of which will delete it on destruction:
{
Matrix m1(3, 5);
Matrix m2 = m1;
} // BOOM!
You need to do a deep copy here:
Matrix::Matrix(const Matrix& m)
: rows(m.rows), cols(m.cols)
{
element = new int *[cols];
for (int i = 0; i < cols; ++i) {
element[i] = new int[rows];
for (int j = 0; j < rows; ++j) {
element[i][j] = m.element[i][j];
}
}
}

Matrix - reading from file

I got problem using function to read matrix from file...
my class looks like this:
#include<iostream>
#include<cmath>
#include<string>
#include<fstream>
using namespace std;
class Matrix
{
public:
Matrix(int, int);
Matrix(const Matrix& copyMatrix);
~Matrix();
Matrix(const char *sciezka);
Matrix& wypelnij(string);
friend ostream& operator<< (ostream&, Matrix&);
Matrix& operator+= (const Matrix&);
Matrix& operator-= (const Matrix&);
Matrix& operator*= (const Matrix&);
Matrix& operator= (const Matrix&);
friend Matrix operator* (const Matrix & left, const Matrix & right);
friend Matrix operator+ (const Matrix & left, const Matrix & right);
friend Matrix operator- (const Matrix & left, const Matrix & right);
class AllocError{};
class OpenError{};
class IncorrectSize{};
private:
double **macierz;
unsigned int wiersze, kolumny;
};
constructors:
Matrix::Matrix(int x = 1, int y = 1): wiersze(x), kolumny(y)
{
if (wiersze < 1 || kolumny < 1)
{
throw AllocError();
}
macierz = new double*[wiersze];
for (unsigned i = 0; i < wiersze; i++)
{
macierz[i] = new double[kolumny];
for (unsigned j = 0; j < kolumny; j++)
{
macierz[i][j] = 0;
}
}
}
Matrix::Matrix(const Matrix& copyMatrix)
{
wiersze=copyMatrix.wiersze;
kolumny=copyMatrix.kolumny;
macierz = new double*[wiersze];
for (unsigned i = 0; i < wiersze; i++)
{
macierz[i] = new double[kolumny];
for (unsigned j = 0; j < kolumny; j++)
{
macierz[i][j] = copyMatrix.macierz[i][j];
}
}
}
and finally the function
Matrix::Matrix(const char *sciezka)
{
ifstream plik(sciezka);
if (plik.good() != true)
{
throw OpenError();
}
unsigned w, k;
plik >> w >> k;
if (w < 1 || k < 1) throw AllocError();
double **temp = new double*[w];
double *pamiec = new double[w * k];
for (unsigned i = 0; i < w; i++)
{
temp[i] = pamiec + (i * k);
}
for (unsigned i = 0; i < w; i++)
{
for (unsigned j = 0; j < k; j++)
{
plik >> temp[i][j];
}
}
wiersze=w;
kolumny=k;
macierz=temp;
//for (unsigned i = 0; i < w; i++) //IT WORKS TOO
// {
// macierz[i] = temp[i];
// }
for (unsigned i = 0; i < w; i++)
{
for (unsigned j = 0; j < k; j++)
{
macierz[i][j] = temp[i][j];
}
}
plik.close();
//delete [] *temp;
//delete [] temp;
}
It works just fine when I dont use delete at the end of the funtion, when I do, some numbers are wrong. If I dont it crashes after finishing all calculations Matrix A("text.txt") Matrix B(5,5) Fill.B("B") Matrix C(5,5)
C=A+B etc...
#edit
I just made it work changing the end of the F to:
wiersze=w;
kolumny=k;
//macierz=temp;
macierz = new double*[w];
for (unsigned i = 0; i < w; i++)
{
macierz[i] = new double[k];
for (unsigned j = 0; j < k; j++)
{
macierz[i][j] = temp[i][j];
}
}
plik.close();
delete [] *temp;
delete [] temp;
}
is there any easier way to read from file? I dont really like this code
For deleting the matrix you should follow the reverse order of allocation, following should do :
for (unsigned i = 0; i < w; i++)
{
delete [] macierz[i] ;
}
delete [] macierz ;

operator[] overloading for a const reference two-dimension pointer

To overload an "+" operator for const matrix, I use the "[]"
Matrix const operator+(const Matrix & mat1, const Matrix & mat2)
{
Matrix sum(mat1);
if (sum.height != mat2.height || sum.width != mat2.width)
cout << "Dimension error!";
else {
for (int i = 0; i < sum.height; i++)
for (int j = 0; j < sum.width; j++)
sum[i][j] = mat2[i][j];
}
return sum;
}
So, I define the overloading for []
(const int*)& operator[] (int i) const {
return (*this).ele[i + 1];
}
But the IDE report the error
"Error IntelliSense: a reference of type "const int *&" (not const-qualified) cannot be initialized with a value of type "int *"
How to solve this error? I have tried many times TAT.
And this is the entire code:
#define NULL 0
#include<iostream>
using namespace std;
class Matrix {
private:
int width, height;
int **ele;
public:
Matrix();
Matrix(int**);
Matrix(int, int);
Matrix(const Matrix&);
Matrix operator= (const Matrix&);
friend const Matrix operator+ (const Matrix&, const Matrix&);
friend const Matrix operator- (const Matrix&, const Matrix&);
(int*)& operator[] (int i) {
return (*this).ele[i + 1];
}
(const int*)& operator[] (int i) const {
return (*this).ele[i + 1];
}
};
Matrix::Matrix() {
width = 0; height = 0;
ele = NULL;
}
Matrix::Matrix(const Matrix& mat) {
Matrix(mat.height, mat.width);
for (int i = 0; i < height; i++)
for (int j = 0; j < width; j++) {
(*this)[i][j] = mat[i][j];
}
}
Matrix::Matrix(int** e) {
(*this).height = e[0][0];
(*this).width = e[0][1];
for (int i = 1; i < height; i++)
for (int j = 0; j < width; j++) {
(*this).ele[i][j] = e[i][j];
}
}
Matrix::Matrix(int height, int width) {
(*this).width = width;
(*this).height = height;
ele = new int*[height + 1];
ele[0] = new int[2];
ele[0][0] = height; ele[0][1] = width;
for (int i = 1; i < height + 1; i++)
{
ele[i] = new int[width];
}
for (int i = 1; i < height; i++)
for (int j = 0; j < width; j++) {
ele[i][j] = 0;
}
}
inline Matrix Matrix::operator=(const Matrix & mat)
{
Matrix tempMat(mat);
return tempMat;
}
Matrix const operator+(const Matrix & mat1, const Matrix & mat2)
{
Matrix sum(mat1);
if (sum.height != mat2.height || sum.width != mat2.width)
cout << "Dimension error!";
else {
for (int i = 0; i < sum.height; i++)
for (int j = 0; j < sum.width; j++)
sum[i][j] = mat2[i][j];
}
return sum;
}
Matrix const operator-(const Matrix & mat1, const Matrix & mat2)
{
Matrix diff(mat1);
if (diff.height != mat2.height || diff.width != mat2.width)
cout << "Demension error!";
else {
for (int i = 0; i < diff.height; i++)
for (int j = 0; j < diff.width; j++)
diff[i][j] = mat2[i][j];
}
return diff;
}
I have found your code compiled (g++ version 4.6.3) when removed parentheses from overloaded operators signature, like user remyabel said.
So try
int* operator[] (int i) {
return (*this).ele[i + 1];
}
const int* operator[] (int i) const {
return (*this).ele[i + 1];
}
instead of
(int*)& operator[] (int i) {
return (*this).ele[i + 1];
}
(const int*)& operator[] (int i) const {
return (*this).ele[i + 1];
}

How to create a function to change a value in a 2D dynamic array

I've been tasked with creating a class for a two dimensional dynamic array and I am stuck at a part where I need to create a member function which I can call upon to change a specific position in the 2D array to a value of my choosing.
class TwoD
{
public:
void setRowCol(int numRow, int numCol, double value);
TwoD();
TwoD(int row, int col);
void fillArray();
void outputArray();
private:
double** dArray = new double* [MaxRow];
int MaxRow;
int MaxCol;
};
TwoD::TwoD()
{
MaxCol = 3;
MaxRow = 3;
for (int i = 0; i < 3; i++)
{
dArray[i] = new double[3];
}
}
void TwoD::setRowCol(int numRow, int numCol, double value)
{
dArray[numRow][numCol] = value;
}
So the part I am having trouble with is the last part with the function setRowCol. I think that the problem is that it's not passing a 'deep' copy of the array but rather the original array itself.
Make the MaxRow as static variable & initialize it to appropriate value(3) before using it to create dArray.
Without std::vector, and using double**, you may have something like:
class TwoD
{
public:
TwoD(int row, int col) : maxRow(row), maxCol(col) {
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol] {};
}
}
~TwoD() {
Delete();
}
TwoD(const TwoD& rhs) : maxRow(rhs.maxRow), maxCol(rhs.maxCol) {
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol];
for (int j = 0; j != maxCol; ++j) {
dArray[i][j] = rhs.dArray[i][j];
}
}
}
TwoD& operator = (const TwoD& rhs) {
if (&rhs == this) {
return *this;
}
Delete();
maxRow = rhs.maxRow;
maxCol = rhs.maxCol;
dArray = new double* [maxRow];
for (int i = 0; i != maxRow; ++i) {
dArray[i] = new double[maxCol];
for (int j = 0; j != maxCol; ++j) {
dArray[i][j] = rhs.dArray[i][j];
}
}
}
void setRowCol(int numRow, int numCol, double value) {
dArray[numRow][numCol] = value;
}
private:
void Delete() {
for (int i = 0; i != maxRow; ++i) {
delete [] dArray[i];
}
delete [] dArray;
}
private:
double** dArray;
int maxRow;
int maxCol;
};