Alright, I'm implementing a dynamic 2-dimensional matrix class. For a basis, this is what I have so far:
template <typename Type>
class dyMatrix {
private:
Type *mat;
int lines, columns;
int length;
void assimilate (const dyMatrix<Type>& that) {
lines = that.lines;
columns = that.columns;
length = that.length;
}
public:
dyMatrix (int height, int width)
: lines(height), columns(width), mat(0)
{
length = lines * columns;
mat = new Type[length];
};
// ---
int getLines() {
return lines;
};
int getColumns() {
return columns;
};
int getLength() {
return length;
}
// ---
Type& operator() (int i, int j) {
return mat[j * columns + i];
};
Type& operator() (int i) {
return mat[i];
};
// ---
dyMatrix (const dyMatrix<Type>& that) {
this->assimilate(that);
// ---
mat = new Type[length];
for (int i = 0; i < length; i++) {
mat[i] = that.mat[i];
}
};
dyMatrix& operator= (const dyMatrix<Type>& that) {
Type *local_mat = new Type[that.length];
for (int i = 0; i < that.length; i++) {
local_mat[i] = that.mat[i];
}
// ---
this->assimilate(that);
delete[] mat;
mat = local_mat;
// ----
return *this;
};
~dyMatrix() {
delete mat;
};
};
My problem is that I've been having some specific problems when trying to read input into it. For example, I have the following main():
int main() {
int lanes, cols;
cin >> lanes >> cols;
dyMatrix<int> map(lanes, cols);
/* CONTINUE READING */
cout << endl;
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
cout << map(i, j) << ' ';
}
cout << endl;
}
}
Where it is a commented section, if I put the following lines of code:
int aux;
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
cin >> map(i, j);
}
}
or:
int aux;
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
cin >> aux;
map(i, j) = aux;
}
}
or even:
int aux;
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
cin >> aux;
map(i, j) = i + j; // !!!
}
}
...It won't work. For some reason, however, the following will:
int aux;
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
// cin >> aux;
map(i, j) = i + j; // Still the same thing as before, logically
}
}
I do not understand. What is happening here?
edit: Sorry, forgot to include my debugging procedure.
Input:
3 5
1 2 3 4 5
1 2 3 4 5
The first line has the dimensions of the matrix. The second and third lines are values written into it; After pressing Enter at the end of the third line, however, the program crashes.
It doesn't even work with this input:
3 5
1
2
3
4
5
1
2
3
4
5
It crashes right after the second 5, again.
Your indices appear the wrong way around:
Type& operator() (int i, int j) {
return mat[j * columns + i];
};
Here, i is clearly the column and j is the row. However, in your loops the arguments appear in the opposite order:
for (int i = 0; i < lanes; i++) {
for (int j = 0; j < cols; j++) {
map(i, j) = ...; // row then column
}
}
Also, the destructor should be using delete[] and not delete.
Related
when I tried to multiple two negative numbers the value it is zero in c++,
for example -5 * -3
the result is zero,
why?
this is my code
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
void Multiply(const int v_arr[], const int m_arr[][3], int signed
o_arr[], int size)
{
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
o_arr[i] = 0;
for (int k = 0; k < 3; k++)
o_arr[i] += v_arr[k] * m_arr[k][i];
}
}
//End your code here
}
int main()
{
int n;
cin >> n;
int v_array[n];
int m_array[n][3];
int signed o_array[3];
for (int i = 0; i < n; i++) {
cin >> v_array[i];
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < 3; j++) {
cin >> m_array[i][j];
}
}
//fuction
Multiply(v_array, m_array, o_array, n);
for (int j = 0; j < 3; j++) {
cout << o_array[j] << " ";
}
return 0;
}
how to fix it to get the correct result?
the input is
2
2 -3
2 -3
2 -4
Your issue is here:
for (int k = 0; k < 3; k++)
o_arr[i] += v_arr[k] * m_arr[k][i];
}
You access elements at indices 0, 1 and 2 in v_arr, but it only has 2 elements. That's Undefined Behaviour.
Assuming this is matrix*vector multiplication code, it should look like this (untested):
for (int k = 0; k < 3; k++)
o_arr[k] += v_arr[i] * m_arr[i][k];
}
Also, your loop based on j is useless. You can remove it:
void Multiply(const int v_arr[], const int m_arr[][3], int signed o_arr[], int size)
{
for(int k = 0; k < 3; k++) { //initialize output array
o_arr[k] = 0;
}
for (int i = 0; i < size; i++) {
for (int k = 0; k < 3; k++)
o_arr[k] += v_arr[i] * m_arr[i][k];
}
}
For my midterm assignment I am required to code a matrix with all details (like identify any size matrix, add (etc.) a number to matrix, add (etc.) two matrices together, transpose, determinant, print...).
I made a class called Matrix and wrote bunch of constructors and functions and overloaded operators.
#include <iostream>
#include <string>
#include <ctime>
#include<fstream>
#include<cstdlib>
#include<iomanip>
#include <cmath>
using namespace std;
class Matrix {
private:
int row;
int column;
int value;
int** matrix;
public:
Matrix(int ro, int col, int val);
Matrix(int ro, int col, char type);
~Matrix();
void print();
void resize(int ro , int col);
void operator=(const Matrix& other);
Matrix operator+(int num)const;
};
Matrix::Matrix(int ro=10, int col=10, int val=0)
:row(ro), column(col), value(val)
{
if (row <= 0 || column <= 0) {
cout << "invalid row or column value";
}
else{
matrix = new int* [row];
for (int i = 0; i < row; i++) {
matrix[i] = new int[column];
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
matrix[i][j] = value;
}
}
}
}
Matrix::Matrix(int ro, int col, char type)
:row(ro), column(col)
{
if (row <= 0 || column <= 0) {
cout << "invalid row or column value";
}
else {
matrix = new int* [row];
for (int i = 0; i < row; i++) {
matrix[i] = new int[column];
}
if (type == 'e'){
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
if (i == j) {
value = 1;
matrix[i][j] = value;
}
else {
value = 0;
matrix[i][j] = value;
}
}
}
}
srand(time(NULL));
if (type == 'r') {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
value = rand() % 256;
matrix[i][j] =value;
}
}
}
}
}
void Matrix::operator=(const Matrix& other) {
this->resize(other.row, other.column);
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
matrix[i][j] = other.matrix[i][j]; // this line throw exception:Exception thrown at 0x00A7BCF2 in matrix.exe: 0xC0000005: Access violation reading location 0xDDDDDDDD.
}
}
}
Matrix Matrix::operator+(int num) const {
Matrix model(row, column);
for (int i = 0; i < model.row; i++) {
for (int j = 0; j < model.column; j++) {
model.matrix[i][j] = matrix[i][j] + num;
}
}
return model;
}
void Matrix::print() {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
cout<< setw(6) << matrix[i][j]<< " " ;
}
cout << endl;
}
}
Matrix::~Matrix() {
for (int i = 0; i < row; i++) {
delete[] matrix[i];
}
delete[] matrix;
}
void Matrix::resize(int ro, int col){
int** copymatrix;
copymatrix = matrix;
matrix = new int* [ro];
for (int i = 0; i < ro; i++) {
matrix[i] = new int[col];
}
for (int i = 0; i < ro; i++) {
for (int j = 0; j < col; j++) {
if (i >= row || j >= column) {
matrix[i][j] = 0;
}
else {
matrix[i][j] = copymatrix[i][j];
}
}
}
row = ro;
column = col;
}
int main() {
Matrix mat1(3, 6, 2);
cout << endl;
mat1 = mat1 + 5;
mat1.print();
}
I also tried this but gives me the same error
Matrix Matrix::operator=(const Matrix& other) {
Matrix model(other.row, other.column);
for (int i = 0; i < model.row; i++) {
for (int j = 0; j < model.column; j++) {
model.matrix[i][j] = other.matrix[i][j]; //exception
}
}
return model;
}
I actually have problems with operators overloading. As I write in the main function when I use operator+ overloading it returns a matrix and after that it comes to operator= overloading and there is the problem as it returns the matrix and comes to operator= it gives me the error Exception thrown at 0x00CEBCDB in matrix.exe: 0xC0000005: Access violation reading location 0xDDDDDDDD. I think I know why but I don't know how to solve it.
This code works in CodeBlocks 17.12. It throws the error in Visual Studio 2019 (v142).
Your assignment operator doesn't assign new memory for the matrix:
void Matrix::operator=(const Matrix& other)
{
this->resize(other.row, other.column);
for (int i = 0; i < row; i++)
for (int j = 0; j < column; j++)
{
matrix[i][j] = other.matrix[i][j];
}
}
So, after it, you'll be accessing memory through an uninitialized pointer.
You need assignment operators, constructors that correctly allocate memory for your matrices. You need matching destructors, too. Look up "rule of 3".
Matrix& Matrix::operator=(const Matrix& other) {
if (this == &other) {
return *this;
}
this->resize(other.row, other.column);
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
matrix[i][j] = other.matrix[i][j];
}
}
return *this;
}
Matrix Matrix::operator+(int num) const {
for (int i = 0; i < row; i++) {
for (int j = 0; j < column; j++) {
this->matrix[i][j] += num;
}
}
return *this;
}
When Function return a matrix by finishing the scope Destructor get called and after we call assignment operator overloading on it, it can't reach the member of that matrix because it already get deleted by Destructor so it throws a exception.
I wrote this before but it did not work until i realize that we should put (&) for (=) operator if we want use this operators overloading one after the other. so now it's working well
i am working on multiplication of matrix
it is something like
m5 = m2 * m3;
cout << "m2 * m3 is : " << endl<< m5 << endl;
and this is my code
const Matrix Matrix::operator*(const Matrix &a)
{
Matrix temp(a.row,a.col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
for (int k = 0; k<a.row; k++)
{
temp.data[i][j] = temp.data[i][j] + data[i][k] * a.data[k][j];
}
}
}
return temp;
}
However, there is an error always showing at my printing function
ostream& operator<<(ostream &output, const Matrix &a)
{
for (int i = 0; i < a.row; i++)
{
for (int j = 0; j < a.col; j++)
{
output << a.data[i][j] << "\t";
}
output << "" << endl;
}
return output;
}
seems there has a problem on a.data[i][j] which i dont know what's the problem
it works fine on addition.
it is showing an error {data0x005fba90{0xfeeefeee{???}}
can anybody give any advice or suggestions or help on this situation
this is my copy constructor
Matrix::Matrix(const Matrix&m2)
{
row = m2.row;
col = m2.col;
setUp(row, col);
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = m2.data[i][j];
}
}
}
this is the set up and default
Matrix::Matrix()
{
row =0;
col = 0;
for (int i = 0; i<row; i++)
{
for (int j = 0; j<col; j++)
{
data[i][j] = 0;
}
}
}
Matrix::Matrix(int a, int b, double d[], int c)
{
row = a;
col = b;
setUp(row, col);
int counter = 0;
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
data[i][j] = d[counter];
counter++;
}
}
}
and the set up
void Matrix::setUp(int a, int b)
{
row = a;
col = b;
data = new double*[row];
for (int i = 0; i < row; i++) data[i] = new double[col];
}
Without seeing your Matrix constructor, or the class definition, it's hard to say for certain, but if you look at this expression
temp.data[i][j] + data[i][k] * a.data[k][j]
Depending on what data is, if you don't explicitly initialize the data member in the constructor when you create temp then its contents will not automatically be initialized, and the contents will be indeterminate and using it will lead to undefined behavior.
Another possible source of problems might be the lack of a copy-constructor, or a faulty copy-constructor. This is a problem since you return temp by value which invokes the copy-constructor.
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;
}
I was wondering if it was possible to move the starting point of the Origin to the bottom-left-corner of my grid.
This is the code I'm working with:
#include <iostream>
using namespace std;
char **createBoard(int n, int m); // Býr til tvívítt kvikt fylki og skilar því til baka
void initiaizeBoard(char **p, int n, int m); // Upphafsstillum allt með '.'
void printBoard(int n, int m, char **p); // Prentum út leikborðið
int main()
{
int rows, columns;
int xhnit;
int yhnit;
cin >> rows >> columns >> xhnit >> yhnit;
char **board = createBoard(rows, columns);
initiaizeBoard(board, rows, columns);
board[xhnit][yhnit] = player;
printBoard(rows, columns, board);
return 0;
}
char **createBoard(int n, int m)
{
char **p = new char*[n];
for (int i = 0; i < n; i++)
{
p[i] = new char[m];
}
return p;
}
void initiaizeBoard(char **p, int n, int m)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
p[i][j] = '.';
}
}
}
void printBoard(int n, int m, char** p)
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
cout << p[i][j];
}
cout << endl;
}
}
For the input "10 10 5 6" my output is as follows:
..........
..........
..........
..........
..........
......X...
..........
..........
..........
..........
The Origins is now set in the top left corner as you can see from the output. I've been searching on this site and the internet in general and I can't seem to figure this out.
In a way, top-left and bottom-left are just arbitrary distinctions before you print the array. The array elements don't really have a physical location before you assign them one. So, in order to move the origin you can just print the rows from first to last.
void printBoard(int n, int m, char** p)
{
for (int i = n-1; i >= 0; i--)
{
for (int j = 0; j < m; j++)
{
cout << p[i][j];
}
cout << endl;
}
}
You can treat everything the same and simply print the rows in reverse order:
void printBoard(int n, int m, char** p) {
for (int i = n-1; i > -1; i--) { // Print in reverse order!
for (int j = 0; j < m; j++) {
cout << p[i][j];
}
cout << endl;
}
}
Here is a live example: http://ideone.com/GJVw8M
I am probably misunderstanding the question but is it just the output display that needs to change?
void printBoard(int n, int m, char** p)
{
for (int i = (n-1); i >=0; i--)
{
for (int j = 0; j < m; j++)
{
cout << p[i][j];
}
cout << endl;
}
}