# dynamically allocating a 2D array

## Recommended Posts

How can I dynamically allocate a 2D array? (the dimensions are gained in runtime)

##### Share on other sites
In what language?

Sorry, C++.

##### Share on other sites
There is boost::multi_array.

##### Share on other sites
Is there a way to do it just by using the standard template library?

I have two matrices that I need to multiply. The matrices's dimensions are known in run-time so I use a pointer.

e.g: If it's a 2x2 matrix I do:
p /*a pointer*/ = new int[x*y];

and I do things like this to access the values:
*(p + (i * y) + j)

But it gets too complicated to multiply the matrices.

It would be nice if there was a constant expression thing, like C++0x is going to have. Is there such thing in C++?

If not, I would like to use a 2D array, dynamically allocated. Can I do this? Or do I have to use boost?

Here is my class by the way:

&lt;matrix.h&gt;#ifndef MATRIX_H#define MATRIX_H#include &lt;iostream&gt;#include &lt;ostream&gt;#include &lt;string&gt;#include &lt;sstream&gt;#include &lt;vector&gt;enum TYPE { ADD = 0, SUBTRACT, MULTIPLY };class Matrix{public:	Matrix(int x, int y);	Matrix(Matrix &m);	~Matrix();	void Init();	void Display() const;	Matrix& operator = (const Matrix &m);		Matrix& operator += (const Matrix &m);	Matrix& operator -= (const Matrix &m);	Matrix& operator *= (const Matrix &m);	//**************** PUBLIC STATIC MEMBER FUNCTIONS ********************************	// create a new matrix by adding/subtracting/multiplying 2 matrices	static Matrix* CreateMatrix(const Matrix &a, const Matrix &b, int type);	// free memory occupied by CreateMatrix()	static int ReleaseMatrix(Matrix *m);	// returns true if an addition, subtraction or multiplication can be done	static bool Can_Add_Subtract_Multiply(const Matrix &a, const Matrix &b, int type);private:	//set the values of the newly created matrix (called by CreateMatrix()	static void Matrix::setValues(Matrix *pMatrix, const Matrix &a, const Matrix &b, int type);	/***********************************************************************************************/		/* if the matrix has been given values through init() and assignment operator it's true		it is required for the matrix to be displayed in Display() */	bool isInitialized; 	int x, y;	int *p; // pointer to the matrix};#endif // MATRIX_H

matrix.cpp
#include "matrix.h"Matrix::Matrix(int x, int y): x(x), y(y), isInitialized(false){	if( x && y)		p = new int[x * y];	else		exit(1);}Matrix::~Matrix(){	delete p;}void Matrix::Init(){	isInitialized = true;	int num;	for(int i = 0; i < x; ++i)	{		for(int j = 0; j < y; ++j)		{			std::cout << "Enter number " << i+1 << ", " << j+1 << ": ";			std::cin >> num;			*(p + (i * y) + j) = num;		}	}	std::cout << "\n";}void Matrix::Display() const{	if(isInitialized)	{		std::cout << "Matrix:\n";		for(int i = 0; i < x; ++i)		{			for(int j = 0; j < y; ++j)			{				std::cout << " " << *(p + (i * y) + j);				if(j != y - 1)					std::cout << "\t";							}			std::cout << "\n";		}			}	else		std::cout << "You must initialize the matrix before displaying it.";		std::cout << "\n";}Matrix& Matrix::operator =(const Matrix &m) // assignment operator{	if(this != &m)	{		isInitialized = true; // set it as initialized		x = m.x;		y = m.y;		delete p; // free the memory that p points to		p = new int[x * y]; // allocate memory		for(int i = 0; i < x * y; ++i) // get the values			*(p + i) = *(m.p + i);	}	return *this;}Matrix& Matrix::operator +=(const Matrix &m){		if(x == m.x && y == m.y)	{		isInitialized = true;		for(int i = 0; i < x; ++i)		{			for(int j = 0; j < y; ++j)			{				*(p + (i * y) + j) += *(m.p + (i * y) + j);			}		}	}	return *this;}Matrix& Matrix::operator -=(const Matrix &m){	if(x == m.x && y == m.y)	{		isInitialized = true;		for(int i = 0; i < x; ++i)		{			for(int j = 0; j < y; ++j)			{				*(p + (i * y) + j) -= *(m.p + (i * y) + j);			}		}	}	return *this;}Matrix& Matrix::operator *=(const Matrix &m){	if(x == m.x && y == m.y)	{		isInitialized = true;		for(int i = 0; i < x; ++i)		{			for(int j = 0; j < y; ++j)			{				*(p + (i * y) + j) *= *(m.p + (i * y) + j);			}		}	}	return *this;}Matrix* Matrix::CreateMatrix(const Matrix &a, const Matrix &b, int type){	switch(type)	{	case ADD:	case SUBTRACT:		if(Can_Add_Subtract_Multiply(a, b, type) )		{			Matrix *pMatrix = new Matrix(a.x, a.y); // create a new matrix			setValues(pMatrix, a, b, type); // give it values			pMatrix->isInitialized = true; // set is as initialized			return pMatrix;		}		break;	case MULTIPLY:		if(Can_Add_Subtract_Multiply(a, b, type) )		{			Matrix *pMatrix = new Matrix(a.x, b.y);			setValues(pMatrix, a, b, type);			pMatrix->isInitialized = true;			return pMatrix;		}		break;	default:		return NULL;	}}int Matrix::ReleaseMatrix(Matrix *m){	if(!m) // if NULL		return -1;	else	{		delete m;		m = NULL;		return 0;	}}bool Matrix::Can_Add_Subtract_Multiply(const Matrix &a, const Matrix &b, int type){	switch(type)	{	case ADD:	case SUBTRACT:		return(a.x == b.x && a.y == b.y);	case MULTIPLY:		return(a.y == b.x);	default:		return false;	}}void Matrix::setValues(Matrix *pMatrix, const Matrix &a, const Matrix &b, int type){	switch(type)	{	case ADD:		for(int i = 0; i < a.x * a.y; ++i)			*(pMatrix->p + i) = (*(a.p + i)) + (*(b.p + i));		break;	case SUBTRACT:		for(int i = 0; i < a.x * a.y; ++i)			*(pMatrix->p + i) = (*(a.p + i)) - (*(b.p + i));		break;		/*				4 1    5 2 4  ===     24   11  18		5 2    4 3 2 ===      33   16  24		*/	case MULTIPLY:		/*arghhhh*/	}}

##### Share on other sites
Quote:
 Original post by sheep19and I do things like this to access the values:*(p + (i * y) + j)But it gets too complicated to multiply the matrices.
Why not wrap it up in a function?
value_type get(size_type i, size_type j){    return p[(i * y) + j];}

##### Share on other sites
I think you are vastly overcomplicating it by including too much in a single class. Build small blocks - and use them to make bigger things. Here we use std::vector to make an array2d class, then use that to make our matrix.
template<class T>class array2d{public:    array2d(unsigned w, unsigned h)    :        storage(w * h),        width_(w)    {    }    unsigned width() const { return width_; }    unsigned height() const { return storage.size() / width_; }    T &operator()(unsigned x, unsigned y)    {        return storage[index(x,y)];    }    const T &operator()(unsigned x, unsigned y) const    {        return storage[index(x,y)]);    }private:    std::vector<T> storage;    unsigned width_;    unsigned index(unsigned x, unsigned y)    {        return (y * width_) + x;    }};class Matrix{public:    Matrix(unsigned w, unsigned h)    :         storage(w,h)    {    }    T &operator()(unsigned x, unsigned y)    {        return storage(x,y);    }    const T &operator()(unsigned x, unsigned y) const    {        return storage(x,y);    }private:    array2d<int> storage;};Matrix operator+(const Matrix &a, const Matrix &b){     // check that dimensions are sane          // implement code     // use result(x,y) = a(x,y) + b(x,y)}// more functions...

Note how we don't need to implement destructors or assignment operators, because we make use of std::vector which does this for us.

I would advise against functions like Can_Add_Subtract_Multiply() and setValues() - they are too complicated. It is easier to write separate functions for each case.

Also, I would advised against having a "uninitialised" state. I can only see bad things coming from this.

Calling exit() when passed invalid arguments is a very poor decision IMO. Better to use assert() or an exception (probably an exception if the dimensions are created at run time).

##### Share on other sites
Thanks for the advice. I'm going to use a double pointer.

int **pp = new int[x];for(int i = 0; i < x; ++i)   *(pp + i) = new int[y];

But first I'll make a class and use templates.

Thanks for the help!

/*looking for template tutorials */

##### Share on other sites
You don't need to use a double pointer. Doing so will unnecessarily fragment memory. However, should you for some reason decide to do that then consider using std::vector< std::vector<int> >, rather than deal with manual memory management. Mixing the math functionality with the memory management complicates your class.

Don't abuse pointer arithmetic. It is considerably harder to read than regular array indexing:
for(int i = 0; i < x; ++i)   pp[i] = new int[y];

##### Share on other sites
How would I do it using a vector?

vector < vector<int> > vec;vec.push_back(vector<int>); //getting an errorit works if I create a 1D vector and push it back.

##### Share on other sites
I imagine something like this:
class Matrix{   Matrix(unsigned w, unsigned h)   :       storage(w,std::vector<int>(h))   {   }private:   std::vector<std::vector<int> > storage;};

##### Share on other sites
Thank you! I'll give it a shot tomorrow, it's almost midnight :O

##### Share on other sites
A vector of vector is not a 2D array.
You can do a vector of n*m elements, or better use boost multi_array which wraps that nicely.

##### Share on other sites
Quote:
 Original post by sheep19I have two matrices that I need to multiply. The matrices's dimensions are known in run-time

Why aren't the dimensions known at compile time, what do these matrices represent?

##### Share on other sites
In past (long long days ago) I made an C program to to do matrix operation in this way. I can share you my full code.

although its written it would compile in C and you can group all these functions in a Matrix Class.

Here I've not used structure you can use.

You can copy paste this code and it would compile.

#include <stdio.h>int  mat_get(int** m, int row, int col, int i, int j);void mat_set(int** m, int row, int col, int i, int j, int val);void mat_fill(int** m, int row, int col, int num);void mat_fill_zero(int** m, int row, int col);void mat_identity(int** m, int row, int col);void mat_add(int** m, int** n, int** res, int row, int col);void mat_sub(int** m, int** n, int** res, int row, int col);void mat_printf(int** m, int row, int col);void mat_scanf(int** m, int row, int col);int  mat_mult(int** m, int** n, int** res, int r1, int c1, int r2, int c2);void mat_mult_scaler(int** m, int** res, int r, int c, int num);void mat_transpose(int** m, int** res, int r, int c);int main(){	int x[6], y[2][3], z[2][3], a[2][3];	int m[2][3] = {{3, -1, -2},{2, -2, -1}};	int n[3][3] = {{4, 2, 0}, {3, 0, 2}, {1, 1, 0}};	int t[3][2];	mat_fill_zero(&y, 2, 3);	mat_fill(&y, 2, 3, 4);	mat_fill(&z, 2, 3, 5);	mat_scanf(&z, 2, 3);	mat_add(&y, &z, &a, 2, 3);	mat_printf(&a, 2, 3);	printf("\n---------------\n\n");	mat_mult(&m, &n, &a, 2, 3, 3, 3);	mat_printf(&a, 2, 3);	mat_mult_scaler(&a, &a, 2, 3, 2);	printf("\n---------------\n\n");	mat_printf(&a, 2, 3);	mat_transpose(&a, &t, 2, 3);	printf("\n---------------\n\n");	mat_printf(&t, 3, 2);  return 0;}/** get an element of i, j location of a matrix	e.g. mat_get(m, row, col, i, j) can be used to get the [i][j] element of the matrix	you must provide the size e.g. row and column of that matrix through row and col params*/int  mat_get(int** m, int row, int col, int i, int j){	return ((int)*(m + ((i*col)+j)));}/**	same as mat_get() used for changing element of that location*/void mat_set(int** m, int row, int col, int i, int j, int val){	*(m + ((i*col)+j)) = val;}/**	makes all elements of a 2d array Zero*/void mat_fill_zero(int** m, int row, int col){	mat_fill(m, row, col, 0);}/**	Identity Matrix*/void mat_identity(int** m, int row, int col){	mat_fill(m, row, col, 1);}/**	fills the matrix with the provided integer*/void mat_fill(int** m, int row, int col, int num){	int i=0, j=0;	for(i=0;i<row;i++){		for(j=0;j<col;j++){			mat_set(m, row, col, i, j, num);		}	}}/**	add two matrixes*/void mat_add(int** m, int** n, int** res, int row, int col){	int i=0, j=0, num;	for(i=0;i<row;i++){		for(j=0;j<col;j++){			num = mat_get(m, row, col, i, j) + mat_get(n, row, col, i, j);			mat_set(res, row, col, i, j, num);		}	}}/**	subtract two matrixes*/void mat_sub(int** m, int** n, int** res, int row, int col){	int i=0, j=0, num;	for(i=0;i<row;i++){		for(j=0;j<col;j++){			num = mat_get(m, row, col, i, j) - mat_get(n, row, col, i, j);			mat_set(res, row, col, i, j, num);		}	}}/**	prints Elements of a matrix*/void mat_printf(int** m, int row, int col){	int i=0, j=0;	for(;i<row;i++){		for(j=0;j<col;j++){			printf("%4d", mat_get(m, row, col, i, j));			if(j != col-1){				printf(" |");			}		}		printf("\n");	}}/**	gets elements of a matrix by scanf*/void mat_scanf(int** m, int row, int col){	int i=0, j=0, num;	for(;i<row;i++){		printf("Row [%d]\n", i);		for(j=0;j<col;j++){			printf("\telement [%d][%d]:\t", i, j);			scanf("%d", &num);			mat_set(m, row, col, i, j, num);		}		printf("\n");	}}/**	Matrix Multiplication*/int mat_mult(int** m, int** n, int** res, int r1, int c1, int r2, int c2){	int i=0, j=0, num, r=0;	if(r2 != c1)return 0;	for(;i<r1;i++){		for(j=0;j<c2;j++){			num=0;			r=0;			while(r <= r1){				num += mat_get(m, r1, c1, i, r)*mat_get(n, r2, c2, r, j);				r++;			}			mat_set(res, r1, c2, i, j, num);		}	}	return 1;}/**	Multiply a matrix with a scaler number*/void mat_mult_scaler(int** m, int** res, int r, int c, int num){	int i=0, j=0;	for(;i<r;i++){		for(j=0;j<c;j++){			mat_set(res, r, c, i, j, mat_get(m, r, c, i, j)*num);		}	}}/**	transpose of a matrix*/void mat_transpose(int** m, int** res, int r, int c){	int i=0, j=0;	for(;i<c;i++){		for(j=0;j<r;j++){			mat_set(res, c, r, i, j, mat_get(m, r, c, j, i));		}	}}

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628359
• Total Posts
2982259

• 10
• 9
• 13
• 24
• 11