I took a programming class at university this semester, just out of curiosity. We're doing C++ and I enjoyed it a lot, but the last two weeks have been rather steep for me and heres what troubles my mind:
I'm given a class interface as follows:
class GameOfLife(int rows, int cols);
public:
GameOfLife();
void clear();
void set(int row, int col, int value);
void set(int row, int col, const char* values);
int get(int row, int col);
void print();
void advance();
};
First thing im being asked to do is to implement the constructor so that it allocates memory for a board with the amount of rows and cols passed in the argument. I thought i understood constructors but with this one I'm pretty lost.
After i declared int rows and cols in the private section i thought about something along the lines of
GameOfLife::GameOfLife(int x, int y){
rows = x;
cols = y;
board = new int* [rows];
But neither do i know how to handle the second dimension of the board without the compiler yelling at me nor do i know how to test if new memory is actually allocated properly.
Any help? :(
Thanks in advance!
In addition to thumbmunkey's correct answer, note that just because the external interface stipulates a 2D array doesn't mean the internal interface has to match.
You could have:
int* board = new int[rows * cols];
Where then instead of get() returning:
return board[x][y];
it would instead be:
return board[x * rows + y];
Sometimes one array is easier to think about than two. Sometimes it's not. Depends on how you want to do it (or if it's stipulated that you have to use one method or the other).
You have to allocate the column array for each row:
for(int i=0; i<rows; i++)
board[i] = new int [cols];
If the allocation fails (eg. when you're out of memory), you will get an exception.
What you are doing right now with board = new int* [rows];
Is allocating an array of integer pointers. You still need to allocate the memory for the actual integers which is what thumbmunkey is doing with,
for(int i=0;i<rows;i++)
board[i] = new int [cols];
There is already a class to dynamically manage memory, it's called vector. If you try to use new in your code then you end up having to reinvent the wheel and write dozens of lines of boilerplate that already exists inside vector.
Also it is simpler to store your board in a contiguous array, there is no need to use a bunch of separate memory blocks to hold the board.
Here is an example:
class GameOfLife
{
public:
GameOfLife(int rows, int cols);
void clear();
void set(int row, int col, int value);
void set(int row, int col, const char* values);
int get(int row, int col);
void print();
void advance();
private:
int rows, cols;
std::vector<int> values;
};
// In the cpp file
GameOfLife::GameOfLife(int rows, int cols)
: rows(rows), cols(cols), values(rows * cols) {}
void GameOfLife::set(int row, int col, int value)
{ values.at(row * cols + col) = value; }
int GameOfLife::get(int row, int col)
{ return values.at(row * cols + col); }
The essentials - constructor, destructor, getters:
class GameOfLife
{
public:
GameOfLife(int _rows, int _cols);
~GameOfLife ();
int GetRows () {return rows;}
int GetCols () {return cols;}
int **GetBoard () {return board;}
private:
int rows, cols;
int **board;
};
GameOfLife::GameOfLife(int _rows, int _cols)
{
rows = _rows;
cols = _cols;
board = new int *[rows];
for (int i = 0; i<rows; i++)
board[i] = new int[cols];
}
GameOfLife::~GameOfLife()
{
for (int i = 0; i<rows; i++)
delete [] board[i];
delete [] board;
}
Related
I want to do something like:
int a[][]; // I know this code won't work, its to demonstrate what I want to do
void func(int n, int m){
a = int[n][m];
}
that is, initialise a global array whose size depends on function input. If this array was local, it would be a trivial case, but I don't know how to do this in the case shown above. Any help would be very useful!
You can create a matrix with std::vector:
std::vector<std::vector<int>> a;
void func(int n, int m) {
a.resize(n);
for(int i = 0; i < n; i++) {
a[i].resize(m);
}
}
Then you can access elements in the same way you do with int a[][]:
a[i][j] = number;
One way to achieve this is to encapsulate a flat std::vector in a Matrix class and use math to get an element with row and column as in this example:
template<typename T>
class Matrix {
private:
vector<T> vec;
//...
public:
T& get_value(size_t const row, size_t const col) {
return vec[row * col_count + col];
}
};
you can try this
int ** a; // is a pointer of two dimension
void func(int n, int m){
a = new int*[n]; //dynamic allocation global pointer a
for(int i = 0; i < n; i++)
a[i] = new int[m]();
}
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.
For a vector in C++, I have
class Vec
{
public:
int len;
double * vdata;
Vec();
Vec(Vec const & v)
{
cout<<"Vec copy constructor\n";
len = v.len;
vdata=new double[len];
for (int i=0;i<len;i++) vdata[i]=v.vdata[i];
};
I would greatly appreciate it if you could help me how to write an analogous code for a matrix. I am thinking something like this:
class Mat
{
public:
int nrows;
int ncols;
double * mdata;
Mat();
Mat(Mat const & m)
{
cout<<"Mat copy constructor\n";
nrows = m.nrows;
ncols = m.ncols;
But I don't know how to code the memory allocation for a matrix using the idea that first we put all the elements into a 1D array (row1 row2 ... rown) then we chop the array into rows and then chop each row into columns. Particularly, could you help me translate this idea into C++ language that is analogous to the following:
vdata=new double[len];
for (int i=0;i<len;i++) vdata[i]=v.vdata[i];
};
I am thinking of something like this:
double *data=new double[nrows*ncols];
for (int i=0;i<nrows;i++)
{
for (int j=0;j<ncols,j++){data(i,j)=m.mdata[i][j]};
};
But I am not sure about this part:
data(i,j)=m.mdata[i][j]
Also, I am supposed to use a pure virtual element indexing method: the (i,j) element of a Mat object m will be retrieved by m(i,j). I have to provide both const and non-const versions of this indexing operator.<-- May you show me how I could do this?
Thanks a lot.
Use as a single-dimensional array. You will notice that in practice, it's generally much simpler to use a 1d-array for such things.
class Matrix
{
public:
Matrix(unsigned int rows, unsigned int cols)
: _rows(rows)
, _cols(cols)
, _size(_rows*_cols)
, _components(new double[_size])
{
for(unsigned int i = 0; i < _size; ++i)
{
_components[i] = 0;
}
}
~Matrix()
{
delete[] _components;
}
double& operator()(unsigned int row, unsigned int col)
{
unsigned int index = row * _cols + col;
return _components[index];
}
private:
unsigned int _rows;
unsigned int _cols;
unsigned int _size;
double* _components;
};
However, if you want to actually use matrices and vectors, and not just implement them for learning, I would really advise you to use the Eigen library. It's free and open source and has great and easy-to-use vector and matrix classes.
While Eigen is great to use, if you want to look at source code of an existing implementation, it can be quite confusing for new programmers - it's very general and contains a lot of optimizations. A less complicated implementation of basic matrix and vector classes can be found in vmmlib.
Also you can use one standard vector to implement matrix but vector size will be nrows * ncols:
#include <vector>
class Mat {
public:
Mat(int rows, int cols):
nrows(rows),
ncols(cols),
elems(rows*cols,0)
{}
Mat(const Mat &m):
nrows(m.nrows),
ncols(m.ncols),
elems(m.elems.begin(), m.elems.end())
{}
double celem(int i,int j) const {
return elems[ncols*i + nrows*j];
}
double *pelem(int i,int j) {
return &elems[ncols*i + nrows*j];
}
private:
int nrows;
int ncols;
vector<double> elems;
};
I am trying to calculate the transpose of a matrix that is not n by n.
The problem is I have to allocate new memory to each element being added, I do not have to delete the **array.
Code is something like that.
// initialize a 2-D array.
array = new int*[row];
for (int i=0; i<row; i++){
arr[i] = new int[col]();
}
Now I am considering just One case that suppose my matrix is 3*4. transpose of Matrix has dim 4*3.
I do the following code But it is giving "SEGMENTATION FAULT". The idea is i allocate a new memory to the element that would be added as a result of transpose.
Code is:
int r=col;
int c=row;
if (col<c){
arr = new int*[row];
for (int i=col; i<=c; i++){
arr[i] = new int[col](); // trying to allocate New Memory to elem.
}
It is giving error here.
Any Help. Also if there is any other method to solve this prolem , do suggest.
In your second code sample, you write over the array limits. arr is row elements long, counting from 0 to row - 1. In the for loop your index i goes from col to c which is equivalent to row and one element beyond the array. Correct code would be < instead of <=
for (int i=col; i < c; i++){
arr[i] = new int[col](); // trying to allocate New Memory to elem.
}
Apart from that, may I suggest you look at Wikipedia: Transpose, because in your second case you can use the the first code sample with just row and col switched.
Write a wrapper with accessor functions (e.g. operator(row,col) for matrices), and use a single-dimensional array of size rows*cols internally.
It makes things much easier, and keeps the data for this matrix together. This can have cache benefits for smaller matrices.
Here is an example, as requested in your comment. It's held very simple by purpose and does not use any templates. It uses a vector as internal storage. You can access the matrix elements using operator(..), e.g.
Matrix A(3,4);
// fill matrix
// you can access each element in a natural syntax as expected from math
int x = A(2,2);
A(2,2) = 3;
In addition, you probably should use exceptions instead of asserts to check for index overflow.
// matrix.h
#include <vector>
class Matrix
{
public:
Matrix(size_t rows, size_t cols);
int& operator()(size_t row, size_t col);
const int& operator()(size_t row, size_t col) const;
int& operator[](size_t index);
const int& operator[](size_t index) const;
Matrix get_transposed() const;
size_t compute_index(size_t row, size_t col) const;
void print();
private:
size_t _rows;
size_t _cols;
std::vector<int> _data;
}; // class Matrix
// matrix.cpp
#include "matrix.h"
#include <iostream>
#include <cassert>
Matrix::Matrix(size_t rows, size_t cols)
: _rows(rows)
, _cols(cols)
, _data(rows*cols, 0)
{
}
int& Matrix::operator()(size_t row, size_t col)
{
const size_t index = compute_index(row, col);
assert(index < _data.size());
return _data[index];
}
const int& Matrix::operator()(size_t row, size_t col) const
{
const size_t index = compute_index(row, col);
assert(index < _data.size());
return _data[index];
}
int& Matrix::operator[](size_t index)
{
return _data[index];
}
const int& Matrix::operator[](size_t index) const
{
return _data[index];
}
size_t
Matrix::compute_index(size_t row, size_t col) const
{
// here you should check that:
// row < rows
// col < cols
// and throw an exception if it's not
assert(row<_rows);
assert(col<_cols);
return row * _cols + col;
}
Matrix
Matrix::get_transposed() const
{
Matrix t(_cols,_rows);
for(size_t row = 0; row < _rows; ++row)
for(size_t col = 0; col < _cols; ++col)
{
t(col,row) = (*this)(row,col);
}
return t;
}
I need to create 2d array in c++.
I can't do it by int mas= new int[x][y]; or auto mas= new int[x][y];
I need to create an array dynamically like:
int x,y
auto mas= new int[x][y];//error - must be const.
Please help me.
int x,y;
x =3;
y = 5;
int ** mas = new int*[x];
for (int i=0;i<x;i++)
{
mas[i] = new int[y];
}
I think something like this.
Don't forget
for(int i=0;i<x;i++)
delete[] mas[i];
delete[] mas;
at the end.
The C++ tool for creating dynamically sized arrays is named std::vector. Vector is however one-dimensional, so to create a matrix a solution is to create a vector of vectors.
std::vector< std::vector<int> > mas(y, std::vector<int>(x));
It's not the most efficient solution because you pay for the ability to have each row of a different size. You you don't want to pay for this "feature" you have to write your own bidimensional matrix object. For example...
template<typename T>
struct Matrix
{
int rows, cols;
std::vector<T> data;
Matrix(int rows, int cols)
: rows(rows), cols(cols), data(rows*cols)
{ }
T& operator()(int row, int col)
{
return data[row*cols + col];
}
T operator()(int row, int col) const
{
return data[row*cols + col];
}
};
Then you can use it with
Matrix<int> mat(y, x);
for (int i=0; i<mat.rows; i++)
for (int j=0; j<mat.cols; j++)
mat(i, j) = (i == j) ? 1 : 0;
My advice would be to avoid the pain of multidimensional arrays in the first place and use a struct.
struct Point {
int x;
int y;
}
int points = 10;
Point myArray[points];
Then to access a value:
printf("x: %d, y: %d", myArray[2].x, myArray[2].y);
Depends on exactly what you're trying to achieve, though.
You can do the manipulations yourself.
int* mas = new int[x*y];
and access [i,j] by:
mas[i*y + j] = someInt;
otherInt = mas[i*y +j];
std::vector<std::vector<int> > mas(y, std::vector<int>(x));