Multiplying arrays - c++

How can I get the Matrix overloaded constructor to combine Vector a and Vector b to form a Matrix object as an outer product. And do the same for Vector c and Vector d. The problem is with overloaded constructor and being able to use that create a matrix. At the moment it can only use Vector a and Vector b when it needs to use each. The print member function needs to print the Matrix from the users input values.
#include <iostream>
using namespace std;
const int rows=3;
const int columns=3;
const int elements=3;
class Vector{
private:
double data[elements];
public:
Vector();
void read();
double get_element(int);
};
Vector::Vector(){
int i=0;
while(i<elements){data[i++]=0;}
}
void Vector::read(){
int j=0;
cout<<"Enter "<<elements<<" elements of vector "<<endl;
while(j<elements){cin>>data[j++];}
}
double Vector:: get_element(int n){
while(n<elements)
return data[n];
}
Vector a,b,c,d;
class Matrix {
private:
double data [rows*columns];
public:
Matrix(Vector &, Vector &);
void add (const Matrix &);
void mult (double);
double trace();
double norm();
void print ();
};
Matrix::Matrix(Vector &, Vector &){
int d,f;
for (d=0; d<rows; d++){
for (f=0; f<columns;f++){
data[d*f]=a.get_element(d)*b.get_element(f);
}
}
}
Matrix A (a, b);
Matrix B (c, d);
void Matrix::print(){
cout.setf(ios::showpoint|ios::fixed);
cout.precision(3);
for (int i=0; i<rows; i++) {
cout << endl;
for (int j=0; j<columns; j++) {
cout << " " << data[i*j];
}
}
}

First thing is first, get rid of the using namespace std. You don't want to import all of std into your class just to use cout and cin.
Now lets get to the basics. You have a class which is supposed to encapsulate/hold data of its own. This class can be passed around and be worked on. Each class has its own unique set of data for your vector/matrix class.
In the above, you have your classes using global variables. This is bad because every vector will have the same exact data. They all share the same variables (global)!
Thus we need to put somehow get Vector to contain its own data. We do this by putting the variable inside the vector class itself. We make it private so that it cannot be accessed outside of the class.
Next, we need a way to initialize data. We cannot give it elements anymore because elements is no longer going to be global and constant. Thus we must now dynamically allocate elements amount of doubles in the constructor and delete it in the destructor.
To prevent weird behavior for now, we disallow copying and assigning. You should REALLY take look at a tutorial on classes and encapsulation.. This answer will be pretty incomplete but should help somewhat and fix a couple things..
If you are 100% sure that vector MUST ONLY have 3 elements, nothing more, nothing less, then you may change double* data to double data[3] and remove new data[...] from the constructor and delete[] data from the destructor.
#include <iostream>
class Vector
{
private:
double* data; //will point to an array of elements.
int elements; //amount of elements this vector has.
Vector(const Vector& other); //copying not allowed.
Vector& operator = (const Vector& other); //copy assignment not allowed.
public:
Vector(int elements); //constructor that tells us how large of an array we need.
~Vector(); //destructor to delete the dynamically allocated array when done.
int size() const; //returns the amount of elements.
double get_element(int n) const;
void set_element(double value, int index);
};
//This is our constructor. It stores the amount of elements we allocated within our class.
//It also initialises data to point to the `new` array.
Vector::Vector(int elements_) : elements(elements_), data(new double[elements_]())
{
}
Vector::~Vector()
{
delete[] data; //before the class gets destroyed, we clean up our dynamically allocated array. ALWAYS!
}
double Vector::get_element(int n) const
{
return data[n];
}
void Vector::set_element(double value, int index)
{
data[index] = value;
}
int Vector::size() const
{
return elements;
}
/** We do the same for the matrix class.**/
class Matrix
{
private:
double* data;
int rows, columns; //instead of elements, we have rows and columns.
Matrix (const Matrix &other); //prevent copying.
Matrix& operator = (const Matrix &other); //prevent assignment.
public:
Matrix(const Vector &a, const Vector &b); //constructor takes TWO vectors.
~Matrix();
void add (const Matrix&);
void mult (double);
double trace();
double norm();
void print ();
};
/** Data is initialized to an array of doubles[rows * columns] **/
/** We also store the amount of rows and columns allocated **/
Matrix::Matrix(const Vector &a, const Vector &b) : data(new double[a.size() * b.size()]), rows(a.size()), columns(b.size())
{
int d, f;
for (d = 0; d < rows; d++)
{
for (f = 0; f < columns; f++)
{
data[d * f] = a.get_element(d) * b.get_element(f);
}
}
}
Matrix::~Matrix()
{
delete[] data; //Before the class is destroyed, we must delete the array.
}
void Matrix::print()
{
std::cout.setf(std::ios::showpoint | std::ios::fixed);
std::cout.precision(3);
for (int i = 0; i < rows; i++)
{
std::cout << std::endl;
for (int j = 0; j < columns; j++)
{
std::cout << " " << data[i * j];
}
}
}
int main()
{
Vector a(3); //Now we can a vector.
Vector b(3); //another vector.
Vector c(2); //notice we can choose how many elements the vector can hold.. 2 elements = a point. Nevertheless..
a.set_element(5.0d, 0);
b.set_element(10.0d, 2);
Matrix m(a, b); //Create a matrix from our two vectors.
m.print(); //Print it..
}
As said before, if you are 100% sure that all matrices are 3x3 and all vectors have 3 elements only, then the following is what the class would look like:
#include <iostream>
class Vector
{
private:
static const int elements = 3; //static. All vector instances will have the same amount of elements.
double data[elements]; //stack allocation. 3 elements only.
Vector(const Vector& other);
Vector& operator = (const Vector& other);
public:
Vector();
~Vector();
void read();
int size() const;
double get_element(int n) const;
};
Vector::Vector() : data() {} //nothing in the constructor. data is filled with 0's.
Vector::~Vector() {} //nothing to delete in the destructor..
double Vector::get_element(int n) const
{
return data[n];
}
int Vector::size() const
{
return elements;
}
class Matrix
{
private:
static const int rows = 3, columns = 3; //all matrix instances will have 3 rows, 3 columns.
double data[rows * columns];
Matrix (const Matrix &other);
Matrix& operator = (const Matrix &other);
public:
Matrix(const Vector &a, const Vector &b);
~Matrix();
void add (const Matrix&);
void mult (double);
double trace();
double norm();
void print ();
};
Matrix::Matrix(const Vector &a, const Vector &b) //nothing to allocate in the constructor.
{
for (int d = 0; d < rows; d++)
{
for (int f = 0; f < columns; f++)
{
data[d * f] = a.get_element(d) * b.get_element(f);
}
}
}
Matrix::~Matrix() {} //nothing to delete in the destructor.
void Matrix::print()
{
std::cout.setf(std::ios::showpoint | std::ios::fixed);
std::cout.precision(3);
for (int i = 0; i < rows; i++)
{
std::cout << std::endl;
for (int j = 0; j < columns; j++)
{
std::cout << " " << data[i * j];
}
}
}
int main()
{
Vector a;
Vector b;
Matrix m(a, b);
m.print();
}

Related

Addition of Matrix in C++ using OOP

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

Problem with a class setter function. Class setter function does not assign values properly

the statement below the function calling is not executed. i am at a loss, why this is so? could someone please clarify. Please consider the code below :
#include<iostream>
#include<cmath>
using namespace std;
class Matrix
{
private:
int row,col;
double *values;
public:
Matrix();
Matrix(int r, int c, double* x);
void setdim(int m, int n){row=m;col=n;}
int getrowdim() const {return row;}
int getcoldim() const {return col;}
void set_values(int i, double x);
double get_value(int i) const;
friend Matrix operator+(const Matrix &A, const Matrix &B);
};
Matrix::Matrix()
{
this->row = 0;
this->col = 0;
this->values = NULL;
}
Matrix::Matrix(int r, int c, double* x)
{
this->row = r;
this->col = c;
this->values = new double[r*c];
for (int i =0;i<r*c;i++)
{
cout<<"Enter value ["<<i<<"] ";
cin>>this->values[i];
}
}
void Matrix::set_values(int k, double x)
{
this->values[k] = x;
}
Matrix operator+(const Matrix &A, const Matrix &B)
{
int rowa = A.getrowdim();
int cola = A.getcoldim();
int rowb = B.getrowdim();
int colb = B.getcoldim();
if(rowa == rowb && cola == colb)
{
Matrix C;
C.setdim(rowa, colb);
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m );
cout<<"Returned from C.set_values()"<<endl;
// THIS STATEMENT DOES NOT GET PRINTED. PLEASE TELL THE REASON // WHY. I SUSPECT THE ERROR IS HERE
}
return C;
}
else
{
cout<<"Invalid Operation";
return A;
}
}
double Matrix::get_value(int i) const
{
return this->values[i];
}
int main()
{
Matrix A(2,2,NULL);
Matrix B(2,2,NULL);
Matrix C;
C = A+B;
return 0;
}
The statement - Returned from C.set_values() does not get printed at all .
Could someone help clarify why this is the case? Thanks a lot for the help!
Here:
Matrix C; // (1)
C.setdim(rowa, colb); // (2)
for(int i =0; i< rowa*cola ; i++)
{
cout<<"i = "<<i<<", A.get_value = "<<A.get_value(i)<<", B.get_value = "<<B.get_value(i)<<endl;
double m = A.get_value(i) + B.get_value(i);
cout<<m<<endl;
C.set_values(i, m ); // (3)
You default construct a Matrix (1). The default constructor just sets the member values to NULL. Then you adjust the size members in (2), but values is still NULL. Then, in (3) you call set_values which tries to access array elements, but there is no array.
The problem is that your Matrix has a raw owning pointer as member. When a class manages a resource you must follow the rule of 3/5. If you don't, the class is broken. Managing a resource is not trivial, and following the rule of 3/5 is just the bare minimum.
The simpler alternative that you should strive for is the rule of 0. For a class that does not manage a resource, the compiler generated special members are just right. If you replace the raw pointer member with a std::vector<double> then you do not need to worry about copying, assignment or destruction, because the compiler will generate the required methods for you.

Allocating memory in a function and returning it

int** transpose(int** matrix,int row, int column)
{
int** new_mat = new int*[column];
for(int i = 0; i < column; i++)
{
new_mat[i] = new int[row];
}
for(int i = 0; i < row; i++ )
{
for(int j = 0; j < column; j ++)
{
new_mat[j][i] = matrix[i][j];
}
}
return new_mat;
}
I have written this function but something feels wrong I couldn't decide whether should I delete new_mat somehow basically function returns this value how should I manage with memory without using any smart pointers or something?
The caller would use the returned matrix.
Moreover, it could acquire ownership. As a result, when the matrix would be no longer needed, it could delete it.
Another option, is for you, to provide another function, that will delete the matrix. The caller then, must call that function to de-allocate the dynamically allocated memory.
However, smart pointers is a nice C++ feature, and I encourage you to give them a shot.
Furthermore, since this C++, you could use a std::vector<std::vector<int>> for the type of your matrix. That way, you don't have to worry about memory management, since everything about it, will happen automatically.
To answer the question as asked, the caller would need to release the returned pointer. For every usage of operator new in the function, there needs to be a corresponding usage of operator delete in the caller. The caller would do this when the matrix returned is no longer needed i.e. anything that is deleted should not subsequently be used.
A better approach - in many respects, including no potential to forget to release memory - is to avoid using pointers directly, avoid using operator new (or variants) or operator delete directly. Instead, use a standard container, such as std::vector(std::vector<int> >. If used carefully, standard containers manage their own elements, and keep a record of their own size, so there is no possibility of memory leak (when a standard container ceases to exist, any dynamically allocated memory it uses also is released).
In principle, you should be able to simplify your function to something that is declared as
std::vector<std::vector<int> > transpose(const std::vector<std::vector<int> > &matrix);
rather than needing to pass numbers of rows and columns as separate arguments (the vectors will keep track). I'll leave implementing that function as an exercise, since you'll learn more of use that way.
You really should think about your matrix representation:
int** matrix = ...; // create matrix of 10x12
// doing quite a lot of stuff
delete[] matrix[7]; // possibly even forgotten -> memory leak
matrix[7] = new int[7];
and you now have a jagged array. Although std::vector will relieve you from all the memory management stuff, you still won't be able to prevent jagged arrays with:
std::vector<std::vector<int>> matrix = ...; // create matrix of 10x12
// doing quite a lot of stuff
matrix[7].resize(7);
Safest thing you can do is create your own class wrapping around the data; I'll be using std::vectors to hold the data, this will make the whole memory management stuff much easier:
template <typename T> // more flexibility: you can use arbitrary data types...
class Matrix // (but you don't _need_ to make a template from)
{
std::vector<std::vector<T>> data;
public:
Matrix(size_t rows, size_t columns)
: data(rows)
{
for(auto& d : data)
d.resize(columns);
}
// the nice thing about using std::vector as data container is
// that default generated move/copy constructors/assignment
// operators and destructor are fine already, so you can forget
// about rule of three or five respectively
// but you need ways to access your data:
size_t rows() { return data.size(); }
size_t columns() { return data.empty() ? 0 : data[0].size(); }
??? operator[](size_t index);
??? operator[](size_t index) const;
};
Well, the index operators... What you actually want to achieve is something that you can access the matrix just like you did with your arrays:
Matrix<int> m(10, 12);
m[7][7] = 7;
But what should we return? A reference to an inner vector would again allow to modify its size and to create a jagged array this way. Solution: A wrapper class around!
template <typename T>
class Matrix
{
// all we had so far...
template <typename Data>
class Row
{
Data& data;
friend class Matrix;
Row(std::vector<T>& data)
: data(data)
{ }
public:
// default constructed constructors/operators/destructor
// themselves and being public are fine again...
auto& operator[](size_t index) { return data[index]; }
};
auto operator[](size_t index) { return Row(data[index]); }
auto operator[](size_t index) const { return Row(data[index]); }
};
Why Row a template? Well, we need different Row types (mutable and immutable access to data) as return types for the two different index operators...
Finally: If you implement yourself, I'd reorder the private/public sections such that public comes first. This improves readability for users of your Matrix class, as they are interested in public interface only (normally) unless they intend to inherit from. But that (currently) is not a good idea here anyway as this class is not intended for, just as std::vector is not either. If you want that: make the destructor virtual:
virtual ~Matrix() = default;
If you feel more comfortable with, you could make the rule of three/five explicit:
Matrix(Matrix const& other) = default; // rule of three
Matrix& operator=(Matrix const& other) = default; // rule of three
Matrix(Matrix&& other) = default; // rule of five
Matrix& operator=(Matrix&& other) = default; // rule of five
Analogously for Row class. Be aware that if you insist on using raw arrays inside then you will have to write all of these explicitly!
Transposing matrices could then be done via a free function again:
Matrix transpose(Matrix const& m)
{
Matrix t(m.columns(), m.rows());
// loops as you had
return t;
}
You could even provide a member function that transposes the matrix itself, best: use above transpose function:
template <typename T>
class Matrix
{
public:
void transpose()
{
Matrix t(transpose(*this));
t.data.swap(data); // cleanup of previously owned data done in t's destructor...
}
If you don't want to use any smart pointers and vectors, then try like this.
matrix - is a wrapper for 2D-dynamic array with size [col][row].
#include <iostream>
#include <algorithm>
using namespace std;
class matrix
{
private:
unsigned int m_row;
unsigned int m_col;
int **m_data;
public:
matrix(unsigned int row, unsigned int col) : m_row(row), m_col(col), m_data(nullptr)
{
alloc();
}
matrix(const matrix &m) : m_row(m.get_rows_count()), m_col(m.get_cols_count()), m_data(nullptr)
{
alloc();
for(unsigned int i = 0; i < m_row; i++)
for(unsigned int j = 0; j < m_col; j++)
m_data[i][j] = m[i][j];
}
~matrix()
{
free();
}
unsigned int get_rows_count() const { return m_row; }
unsigned int get_cols_count() const { return m_col; }
const int* operator[](unsigned int ind) const
{
return m_data[ind];
}
int* operator[](unsigned int ind)
{
return m_data[ind];
}
matrix& operator=(const matrix &m)
{
free();
m_row = m.get_rows_count();
m_col = m.get_cols_count();
alloc();
for(unsigned int i = 0; i < m_row; i++)
for(unsigned int j = 0; j < m_col; j++)
m_data[i][j] = m[i][j];
return *this;
}
// you need move-operations:
//matrix(matrix&& other) = delete; // move constructor (rule of 5)
//matrix& operator=(matrix&& other); // move assignment (rule of 5)
void print()
{
for(unsigned int i = 0; i < m_row; i++)
{
for(unsigned int j = 0; j < m_col; j++)
cout << m_data[i][j] << " ";
cout << endl;
}
}
private:
void alloc()
{
if(m_data)
return;
m_data = new int*[m_row];
for(unsigned int i = 0; i < m_row; i++)
{
m_data[i] = new int[m_col];
std::fill(m_data[i], m_data[i] + m_col, 0);
}
}
void free()
{
if(!m_data)
return;
for(unsigned int i = 0; i < m_row; i++)
delete[]m_data[i];
delete[]m_data;
m_data = nullptr;
}
};
matrix transpose(const matrix matrix_in)
{
unsigned int M = matrix_in.get_rows_count();
unsigned int N = matrix_in.get_cols_count();
matrix out(N, M);
for(unsigned int i = 0; i < M; i++)
for(unsigned int j = 0; j < N; j++)
out[j][i] = matrix_in[i][j];
return out;
}
int main(int argc, char* argv[])
{
matrix m1(5, 7);
m1[0][1] = m1[0][2] = m1[0][3] = 7;
auto m2 = transpose(m1);
m1.print();
cout << endl;
m2.print();
}
In any case, it is better to free the memory in the same place where it was allocated. If you do not want to use some classes, you can do it like this:
void transpose(int **matr_in, int **matr_out, int M, int N)
{
for(int i = 0; i < M; i++)
for(int j = 0; j < N; j++)
matr_out[j][i] = matr_in[i][j];
}
int **create_matrix(int M, int N)
{
int **m = new int*[M];
for(int i = 0; i < M; i++)
m[i] = new int[N];
return m;
}
void delete_matrix(int **m, int M)
{
for(int i = 0; i < M; i++)
delete []m[i];
delete []m;
}
int main()
{
int M = 5, N = 4;
int **m1 = create_matrix(M, N);
// fill matrix m1
int **m2 = create_matrix(N, M);
transpose(m1, m2, M, N);
delete_matrix(m1, M);
delete_matrix(m2, N);
return 0;
}
you provide a function return a pointer array which holds seperated memory blocks (each represents one row). then you must also provide the free (or delete) function at the same time, and in the same module (to ensure the memory managerment functions matches exactly).
int** transpose(int** matrix, int row, int column)
{
int** new_mat = new int*[column];
...
return new_mat;
}
//when free the mat, cols is not concerned;
void free_mat(int** matrix, int rows)
{
int i;
for(i= 0; i< rows; i++)
delete[] matrix[i];
delete[] matrix;
}
//use the function as:
int** m2 = transpose(m1, rows, cols);
...
free_mat(m2, cols);
//after free_mat(), m2 still holds the address.
//so make it nullptr.
m2 = NULL;
also you can allcate one plane continuous memory block to present 2-dimention matrix:
int* mat = new int[rows * cols];
//transfer mat[iRow][iCol] to mat[iRow * cols + iCol];
return mat;

Matrix - return and pass as parameter c++

I'm trying to use clear functions to do a matrix multiplication with random generated values. Therefore I'm hoping to use a function(mat_def) to generate the matrices and another function(mat_mul) to multiply them when the matrices are sent as parameters.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
double mat_def(int n) //how to return the matrix
{
double a[n][n];
double f;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
f= rand();
cout<<f ;
a[i][j]=f;
}
}
return 0;
}
double mat_mul( int n, double a[n][n], double b[n][n]) //how to send matrix as parameter
{
return 0;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
mat_def(10);
}
Here's a nice, standard C++ Matrix template for you.
Matrix.h
#include <vector>
class Matrix
{
class InnerM
{
private:
int ydim;
double* values;
public:
InnerM(int y) : ydim(y)
{
values = new double[y];
}
double& operator[](int y)
{
return values[y];
}
};
private:
int xdim;
int ydim;
std::vector<InnerM> inner;
public:
Matrix(int x, int y) : xdim(x), ydim(y), inner(xdim, InnerM(ydim))
{
}
InnerM& operator[](int x)
{
return inner[x];
}
};
All the memory leaks are there for you but you get the idea. From here you can handle the multiplication by overiding ::operator*() in the Matrix class.
I assume your problem is to define 2-D array and then pass it to mat_mul function to multiply the matrices. And the rest will be quite simple.
Defining the 2-D array(considering memory needs are known at run time):
int rows,cols;
cin >> rows;
cin >> cols;
int **arr = new int*[rows]; // rows X cols 2D-array
for(int i = 0; i < rows; ++i) {
arr[i] = new int[cols];
}
You can define another 2-D array exactly the same way with required rows and column.
now, Passing the 2-D array to function:
void mat_mul(int **arr1, int **arr2, int m, int n, int p, int q){
//define a 2-D array to store the result
//do the multiplication operation
//you could store the result in one of the two arrays
//so that you don't have to return it
//or else the return type should be modified to return the 2-D array
}
example:
void display(int **arr, int row, int col){
for (int i=0; i<row; i++){
for(int j=0;j<col; j++){
cout << arr[i][j] << '\t';
}
cout << endl;
}
}
Delete the memory if not required anymore with the following syntax:
for(int i=0; i<rows; i++){
delete[] array[i];
}
delete[] array;
hope this will be sufficient to get your work done!
there is already an answer on how to return a 2-D array on SO. Check the link below.
https://stackoverflow.com/a/8618617/8038009
Returning the raw allocation is a sucker bet. You need to manage all of the memory allocated yourself and pass it around with the matrix size parameters.
Why suffer? Use a matrix class
template<class Type>
class Matrix{
int rows;
int cols;
std::vector<type> data;
public:
Matrix(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors.
//add a convenience method for easy access to the vector
type & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
type operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
Usage would be
Matrix<double> mat_mul(const Matrix<double> &a, const Matrix<double> &b)
{
Matrix<double> result;
// do multiplication
return result;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
Matrix<double> matA(10, 10);
matA(0,0) = 3.14; // sample assignment
matA(9,9) = 2.78;
double x = matA(0,0) * matA(9,9)
Matrix<double> matB(10, 10);
Matrix<double> matC = mat_mul(matA, matB) ;
}
More functionality, such as construction from an initializer list, can be added to the class to make your life easier. You can also specify an operator * overload for Matrix and use that in place of mat_mul if you chose. Read Operator overloading for more on that option.

Returning an object from a function

The other day I was trying to write a matrix manipulation program in C++. I first created a matrix container which works. Then I tried to write a function for transposing matrices. That's when I got into trouble. Using the function causes my program to crash.
struct imat //matrix of integer numbers
{
friend int size(imat,int);
protected:
const int nrows; const int ncols; //ncols = number of columns, nrows = number of rows
int* mat; //internal array that holds the data
public:
imat(const int m, const int n): nrows(m), ncols(n) //constructor
{
mat = new int[m*n]; //creates an array of size nrows*ncols
for (int k=0; k<m*n; k++) mat[k]=0; //zeros all the elements
}
imat(const imat& src): nrows(src.nrows), ncols(src.ncols) //copy constructor
{for (int k=0; k<nrows*ncols; k++) mat[k]=src.mat[k];} //copies the contents of src to this matrix
imat& operator=(const imat& rhs) //assignment operator
{
if (nrows!=rhs.nrows||ncols!=rhs.ncols) throw(1); //lhs and rhs must have the same dimensions
for (int k=0; k<nrows*ncols; k++) mat[k]=rhs.mat[k]; //copies the contents of rhs to this matrix (lhs)
return *this; //return this matrix as output (lhs)
}
int& operator()(int i, int j) {return mat[(i-1)*ncols+(j-1)];} //A(i,j)=mat[(i-1)*ncols+(j-1)] (stores the matrix in the 1D array 'mat')
~imat() {delete[] mat;}
};
int size(imat mat, int dim) //gets matrix dimensions
{
if (dim==1) return mat.nrows; //dimension 1 is number of rows
if (dim==2) return mat.ncols; //dimernsion 2 is number of columns
return 0; //returns 0 if dimesion number is invalid
}
imat trans(imat A)
{
int m=size(A,1); //number of rows
int n=size(A,2); //numbers of columns
imat B(n,m); //creates an n*m matrix
for (int i=1; i<=m; i++)
for (int j=1; j<=n; j++)
B(j,i)=A(i,j); //sets the components of B to the components of the transpose of A
return B;
}
I tried the following main functions, but none of them works:
1)
int main()
{
imat A(2,3);
A(1,1)=11;
A(1,2)=12;
A(1,3)=13;
A(2,1)=21;
A(2,2)=22;
A(2,3)=23;
imat B = trans(A);
return 0;
}
2)
int main()
{
imat A(2,3);
A(1,1)=11;
A(1,2)=12;
A(1,3)=13;
A(2,1)=21;
A(2,2)=22;
A(2,3)=23;
imat B(3,2)
B = trans(A);
return 0;
}
My guess is that it has something to do with the destruction of objects at the end of a function scope, though I'm not sure. Please explain to me in simple language what the problem is and how I can fix it.
You forgot to allocate memory for your dynamic array in the copy constructor. You just started assigning to mat[...], even though mat was left uninitialized.