Matrix - reading from file - c++

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 ;

Related

Understanding the code to write an overload function (new int[] in matrix operations)

yesterday our lecturer got us this code below without any meaningful explanation. We are struggling to understand how it works.
class Matrix {
static int mem;
int rows, cols;
int* ptr;
public:
Matrix(int l = 10, int k = 10) :rows(l), cols(k) {
ptr = new int[rows * cols];
mem += (rows * cols) * sizeof(int);
}
Matrix(const Matrix& x) :rows(x.rows), cols(x.cols) {
ptr = new int[rows * cols];
int* tmp = ptr; // HERE
mem += (rows * cols) * sizeof(int);
for (int i = 0; i < x.rows * x.cols; i++) {
ptr[i] = x.ptr[i];
}
}
~Matrix() {
mem -= (rows * cols) * sizeof(int);
delete[] ptr;
}
friend istream& operator>>(istream& input, Matrix& x) {
int* tmp = x.ptr;
for (int i = 0; i < x.rows; i++) {
for (int j = 0; j < x.cols; j++) {
input >> *tmp; tmp++;
}
}
return input;
}
friend ostream& operator<<(ostream& output, Matrix& x) {
int* tmp = x.ptr;
for (int i = 0; i < x.rows; i++) {
for (int j = 0; j < x.cols; j++) {
output << *tmp << " "; tmp++;
}
output << endl;
}
return output;
}
friend Matrix operator+(const Matrix& x, const Matrix& y) {
Matrix tmp(x.rows,x.cols);
if (x.rows != y.rows || x.cols != y.cols) {
return tmp;
}
else {
for (int i = 0; i < x.rows * x.cols; i++) {
tmp.ptr[i] = x.ptr[i] + y.ptr[i];
}
return tmp;
}
}
Matrix operator=(const Matrix& x) {
if (x.rows != x.cols) {
delete[] ptr;
rows = x.rows;
cols = x.cols;
ptr = new int[rows * cols];
mem += (rows * cols) * sizeof(int);
}
for (int i = 0; i < x.rows * x.cols; i++) {
ptr[i] = x.ptr[i];
}
return *this;
}
friend Matrix operator*(const Matrix& x, const Matrix& y) {...}
};
Based on this chunk of code we have to overload '*' operator that would multiply two matrices together (ex. C = A * B).
And when it's fairly easy to do with 2D arrays, I just can't wrap my head around the way it's working right now, so any help would be more than appreciated.
Thanks for your time!

How to write a friend (operator) method in a template?

So I'm trying to overload the operator + in a template class.
the code compiles and runs but crashes at the use of the operator +.
tried so many things, I think it's a syntax problem? any advice would be appreciated!
The operator = is overloaded and works.
Matrix.h
template <int row, int col, class T = int>
class Matrix
{
int rows;
int cols;
T** mat;
public:
Matrix(int defVal = 0) {
rows = row;
cols = col;
memory();
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = defVal;
}
~Matrix() {
del();
}
Matrix(const Matrix& other) {
*this = other;
}
const Matrix& operator=(const Matrix& other) {
if (&other != this)
{
rows = other.rows;
cols = other.cols;
del();
memory();
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = other.mat[i][j];
}
return *this;
}
friend ostream& operator<<(ostream& os, const Matrix& m) {
for (int i = 0; i < m.cols; i++)
{
for (int j = 0; j < m.rows; j++)
os << m.mat[i][j] << " ";
os << endl;
}
return os;
}
friend Matrix operator+(const Matrix& other, T num) {
Matrix temp = other;
for (int i = 0; i < temp.rows; i++)
for (int j = 0; j < temp.cols; j++)
temp.mat[i][j] += num;
return temp;
}
void memory(){
mat = new T * [rows];
for (int i = 0; i < rows; i++)
mat[i] = new T[cols];
}
void del(){
for (int i = 0; i < rows; i++)
delete[] mat[i];
delete[] mat;
}
};
main.cpp
int main() {
Matrix<4, 4> mat;
std::cout << mat << std::endl;
Matrix<4, 4> identity(1);
std::cout << identity + 3 << std::endl; //crashes here
return 0;
}
if you need other parts of the code let me know! Thanks in advance!
Your copy constructor and assignment looks suspicious, you del after changing rows and cols, without initialising anything.
I expect it should be
Matrix(const Matrix& other) : rows(0), cols(0), mat(nullptr) {
*this = other;
}
const Matrix& operator=(const Matrix& other) {
if (&other != this)
{
del(); // clean up first
rows = other.rows;
cols = other.cols;
memory();
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = other.mat[i][j];
}
return *this;
}
As an aside, I wouldn't use dynamic allocation here at all, and instead
template <typename T, size_t rows, size_t cols>
class Matrix
{
std::array<std::array<T, cols>, rows> mat;
public:
Matrix(T defVal = {}) {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = defVal;
}
friend std::ostream& operator<<(std::ostream& os, const Matrix& m) {
for (int i = 0; i < cols; i++)
{
for (int j = 0; j < rows; j++)
os << m.mat[i][j] << " ";
os << std::endl;
}
return os;
}
friend Matrix operator+(Matrix other, T num) {
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
other.mat[i][j] += num;
return other;
}
// No need for any special members
};

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

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?

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];
}
}
}

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];
}