I'm developing a 2d-platformer. Everything was fine until I've got some hard to solve problem. Level map is stored in dynamic multidemension array(char **map). It works fine, until I want to redefine it
Here's the part of code:
Map& Map::operator=(const Map& rhs)
{
if(width!=0||height!=0)
{
for(int i=0;i<width;i++)
delete[] map[i];
delete[] map;
} //deleting previously created array
height=rhs.height;
width=rhs.width; //receiving other map's size
map=new char* [width];
walkmap=new unsigned char* [width];
objmap=new char* [width];
for(int i=0;i<width;i++)
{
*(map+i)=new char[height];
} //creating new array
for(int h=0;h<height;h++)
for(int w=0;w<width;w++)
{
map[w][h]=rhs.map[w][h];
} //receiving new values
//...
}
Everything works fine for the first time, but when I need to redefine array for the second time my program crashes at the part, when array is receiving new values from another one. May be I miss something, but I can't find it! I was searching for this problem, but didn't find what I am doing wrong. Help me, please.
As always, Boost has an elegant and memory efficient multi-dimensional array class:
http://www.boost.org/doc/libs/1_39_0/libs/multi_array/doc/user.html
For example, to setup a 10 x 20 array of bool values:
boost::multi_array mtaFlagMatrix(boost::extents[10][20]);
Then to access its elements:
mtaFlagMatrix[2][6] = false; // indexes are zero-based - just like normal C arrays
...
if ( mtaFlagMatrix[2][6] )
{
...
}
Then, you can resize the array this way (existing values are preserved):
typedef boost::multi_array array_type;
array_type::extent_gen extents;
array_type A(extents[3][3][3]);
A[0][0][0] = 4;
A[2][2][2] = 5;
A.resize(extents[2][3][4]);
assert(A[0][0][0] == 4);
// A[2][2][2] is no longer valid.
This saved me a lot of time testing for extreme cases.
Your 2d array is not freeed properly. I advise you to use the Iliffe way of allocating 2d arrays which is faster and safer to use:
char** alloc_array( int h, int w )
{
typedef char* cptr;
int i;
char** m = new cptr[h];
m[0] = new char[h*w];
for(i=1;i<h;i++) m[i] = m[i-1]+w;
return m;
}
void release_array(char** m)
{
delete[] m[0];
delete[] m;
}
int main()
{
int r,c;
char** tab;
int width = 5;
int height = 3;
tab = alloc_array(height, width); /* column first */
for(r = 0;r<height;++r)
for(c = 0;c<width;++c)
tab[r][c] = (1+r+c);
for(r = 0;r<height;++r)
{
for(c = 0;c<width;++c)
{
printf("%d\t",tab[r][c]);
}
puts("");
}
release_array(tab);
}
This can be easily encapsulated in a neat 2d-array class or made to use std::vector instead of raw allocation. Prefer this way of doing 2d array as it is cache friendly , style provide the [][] access and is no slower and soemtimes faster than the polynomial 1d access.
Related
How to create a dynamic array of integers in C++ using the new keyword?
int main()
{
int size;
std::cin >> size;
int *array = new int[size];
delete [] array;
return 0;
}
Don't forget to delete every array you allocate with new.
Since C++11, there's a safe alternative to new[] and delete[] which is zero-overhead unlike std::vector:
std::unique_ptr<int[]> array(new int[size]);
In C++14:
auto array = std::make_unique<int[]>(size);
Both of the above rely on the same header file, #include <memory>
You might want to consider using the Standard Template Library . It's simple and easy to use, plus you don't have to worry about memory allocations.
http://www.cplusplus.com/reference/stl/vector/vector/
int size = 5; // declare the size of the vector
vector<int> myvector(size, 0); // create a vector to hold "size" int's
// all initialized to zero
myvector[0] = 1234; // assign values like a c++ array
int* array = new int[size];
As soon as question is about dynamic array you may want not just to create array with variable size, but also to change it's size during runtime. Here is an example with memcpy, you can use memcpy_s or std::copy as well. Depending on compiler, <memory.h> or <string.h> may be required. When using this functions you allocate new memory region, copy values of original memory regions to it and then release them.
// create desired array dynamically
size_t length;
length = 100; //for example
int *array = new int[length];
// now let's change is's size - e.g. add 50 new elements
size_t added = 50;
int *added_array = new int[added];
/*
somehow set values to given arrays
*/
// add elements to array
int* temp = new int[length + added];
memcpy(temp, array, length * sizeof(int));
memcpy(temp + length, added_array, added * sizeof(int));
delete[] array;
array = temp;
You may use constant 4 instead of sizeof(int).
dynamically allocate some memory using new:
int* array = new int[SIZE];
The answers above are all good for assigning one-dimensional int-arrays. Anyhow, I want to add that it is also possible to do this for multi-dimensional arrays you'd normally define like int[][] matrix = {{1,2}, {3,4}}.
The key is that you store all elements in one array and make use of the fact that the array is a continuous block in memory (see here for a clarification of "block"), meaning that you can "slice" yourself through dimensions. Below you can see an example for a 2d-array.
You can find a discussion regarding this topic here on SO.
/*Defining a 2d-matrix.*/
struct Matrix {
int rows, columns;
int* matrix;
Matrix(int rows, int columns) : rows(rows), columns(columns) {
// This approach uses a single array since "new" cannot create
// multidimensional arrays.
// It also spares the performance cost of an array of arrays.
matrix = new int[columns * rows];
}
~Matrix() {
// Release the memory after destroying the Matrix-object
delete[] matrix;
}
/*Access the element at position [r]ow and [c]olumn.*/
int getElement(int r, int c) {
// matrix[c][r] is rewritten as matrix[column + columns * rows]
// -> matrix <=> Single memory block
return matrix[c + columns * r];
}
/*Set the element at position [r]ow and [c]olumn with given [val]ue.*/
void setElement(int r, int c, int val) {
matrix[c + columns * r] = val;
}
};
An example to populate such a Matrix-object would be:
/*Initialize the matrix with the continuous numbers 0..N*/
void Matrix::initDummyMatrix(){
int counter = 0;
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < columns; ++col) {
setElement(row, col, counter++);
}
}
}
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
float arr[2095879];
long k,i;
char ch[100];
k=0;
do{
cin>>ch;
arr[k]=atof(ch);
k++;
}while(ch[0]=='0');
cout<<"Array output"<<endl;
for(i=0;i<k;i++){
cout<<arr[i]<<endl;
}
return 0;
}
The above code works, the maximum float or int array size that could be defined was with size 2095879, and exit condition would be non zero beginning input number
How to create a dynamic array of integers in C++ using the new keyword?
int main()
{
int size;
std::cin >> size;
int *array = new int[size];
delete [] array;
return 0;
}
Don't forget to delete every array you allocate with new.
Since C++11, there's a safe alternative to new[] and delete[] which is zero-overhead unlike std::vector:
std::unique_ptr<int[]> array(new int[size]);
In C++14:
auto array = std::make_unique<int[]>(size);
Both of the above rely on the same header file, #include <memory>
You might want to consider using the Standard Template Library . It's simple and easy to use, plus you don't have to worry about memory allocations.
http://www.cplusplus.com/reference/stl/vector/vector/
int size = 5; // declare the size of the vector
vector<int> myvector(size, 0); // create a vector to hold "size" int's
// all initialized to zero
myvector[0] = 1234; // assign values like a c++ array
int* array = new int[size];
As soon as question is about dynamic array you may want not just to create array with variable size, but also to change it's size during runtime. Here is an example with memcpy, you can use memcpy_s or std::copy as well. Depending on compiler, <memory.h> or <string.h> may be required. When using this functions you allocate new memory region, copy values of original memory regions to it and then release them.
// create desired array dynamically
size_t length;
length = 100; //for example
int *array = new int[length];
// now let's change is's size - e.g. add 50 new elements
size_t added = 50;
int *added_array = new int[added];
/*
somehow set values to given arrays
*/
// add elements to array
int* temp = new int[length + added];
memcpy(temp, array, length * sizeof(int));
memcpy(temp + length, added_array, added * sizeof(int));
delete[] array;
array = temp;
You may use constant 4 instead of sizeof(int).
dynamically allocate some memory using new:
int* array = new int[SIZE];
The answers above are all good for assigning one-dimensional int-arrays. Anyhow, I want to add that it is also possible to do this for multi-dimensional arrays you'd normally define like int[][] matrix = {{1,2}, {3,4}}.
The key is that you store all elements in one array and make use of the fact that the array is a continuous block in memory (see here for a clarification of "block"), meaning that you can "slice" yourself through dimensions. Below you can see an example for a 2d-array.
You can find a discussion regarding this topic here on SO.
/*Defining a 2d-matrix.*/
struct Matrix {
int rows, columns;
int* matrix;
Matrix(int rows, int columns) : rows(rows), columns(columns) {
// This approach uses a single array since "new" cannot create
// multidimensional arrays.
// It also spares the performance cost of an array of arrays.
matrix = new int[columns * rows];
}
~Matrix() {
// Release the memory after destroying the Matrix-object
delete[] matrix;
}
/*Access the element at position [r]ow and [c]olumn.*/
int getElement(int r, int c) {
// matrix[c][r] is rewritten as matrix[column + columns * rows]
// -> matrix <=> Single memory block
return matrix[c + columns * r];
}
/*Set the element at position [r]ow and [c]olumn with given [val]ue.*/
void setElement(int r, int c, int val) {
matrix[c + columns * r] = val;
}
};
An example to populate such a Matrix-object would be:
/*Initialize the matrix with the continuous numbers 0..N*/
void Matrix::initDummyMatrix(){
int counter = 0;
for (int row = 0; row < rows; ++row) {
for (int col = 0; col < columns; ++col) {
setElement(row, col, counter++);
}
}
}
#include <stdio.h>
#include <cstring>
#include <iostream>
using namespace std;
int main()
{
float arr[2095879];
long k,i;
char ch[100];
k=0;
do{
cin>>ch;
arr[k]=atof(ch);
k++;
}while(ch[0]=='0');
cout<<"Array output"<<endl;
for(i=0;i<k;i++){
cout<<arr[i]<<endl;
}
return 0;
}
The above code works, the maximum float or int array size that could be defined was with size 2095879, and exit condition would be non zero beginning input number
I originally asked using nested std::array to create an multidimensional array without knowing dimensions or extents until runtime but this had The XY Problem of trying to accomplish it with std::array.
The questions One-line initialiser for Boost.MultiArray and How do I make a multidimensional array of undetermined size a member of a class in c++? and their answers give some helpful information how to use Boost::MultiArray to avoid needing to know the extents of the dimensions at runtime, but fail to demonstrate how to have a class member that can store an array (created at runtime) whose dimensions and extents are not known until runtime.
Just avoid multidimensional arrays:
template<typename T>
class Matrix
{
public:
Matrix(unsigned m, unsigned n)
: n(n), data(m * n)
{}
T& operator ()(unsigned i, unsigned j) {
return data[ i * n + j ];
}
private:
unsigned n;
std::vector<T> data;
};
int main()
{
Matrix<int> m(3, 5);
m(0, 0) = 0;
// ...
return 0;
}
A 3D access (in a proper 3D matrix) would be:
T& operator ()(unsigned i, unsigned j, unsigned k) {
// Please optimize this (See #Alexandre C)
return data[ i*m*n + j*n + k ];
}
Getting arbitrary dimensions and extent would follow the scheme and add overloads (and dimensional/extent information) and/or take advantage of variadic templates.
Having a lot of dimensions you may avoid above (even in C++11) and replace the arguments by a std::vector. Eg: T& operator(std::vector indices).
Each dimension (besides the last) would have an extend stored in a vector n (as the first dimension in the 2D example above).
Yes. with a single pointer member.
A n multidimensional array is actually a pointer. so you can alocate a dynamic n array and with casting, and put this array in the member pointer.
In your class should be something like this
int * holder;
void setHolder(int* anyArray){
holder = anyArray;
}
use:
int *** multy = new int[2][1][56];
yourClass.setHolder((int*)multy);
You can solve the problem in at least two ways, depending on your preferences. First of all - you don't need the Boost library, and you can do it yourself.
class array{
unsigned int dimNumber;
vector<unsigned int> dimSizes;
float *array;
array(const unsigned int dimNumber, ...){
va_list arguments;
va_start(arguments,dimNumber);
this->dimNumber = dimNumber;
unsigned int totalSize = 1;
for(unsigned int i=0;i<dimNumber;i++)
{
dimSizes.push_back(va_arg(arguments,double));
totalSize *= dimSizes[dimSizes.size()-1];
}
va_end(arguments);
array = new float[totalSize];
};
float getElement(unsigned int dimNumber, ...){
va_list arguments;
va_start(arguments,dimNumber);
unsgned int elementPos = 0, dimAdd = 1;
for(unsigned int i=0;i<dimNumber;i++)
{
unsigned int val = va_arg(arguments,double);
elementPos += dimAdd * val;
dimAdd *= dimsizes[i];
}
return array[elementPos]
};
};
Setting an element value would be the same, you will just have to specify the new value. Of course you can use any type you want, not just float... and of course remember to delete[] the array in the destructor.
I haven't tested the code (just wrote it straight down here from memory), so there can be some problems with calculating the position, but I'm sure you'll fix them if you encounter them. This code should give you the general idea.
The second way would be to create a dimension class, which would store a vector<dimension*> which would store sub-dimensions. But that's a bit complicated and too long to write down here.
Instead of a multidimensional array you could use a 1D-array with an equal amount of indices. I could not test this code, but I hope it will work or give you an idea of how to solve your problem. You should remember that arrays, which do not have a constant length from the time of being compiled, should be allocated via malloc() or your code might not run on other computers.
(Maybe you should create a class array for the code below)
#include <malloc.h>
int* IndexOffset; //Array which contains how many indices need to be skipped per dimension
int DimAmount; //Amount of dimensions
int SizeOfArray = 1; //Amount of indices of the array
void AllocateArray(int* output, //pointer to the array which will be allocated
int* dimLengths, //Amount of indices for each dimension: {1D, 2D, 3D,..., nD}
int dimCount){ //Length of the array above
DimAmount = dimCount;
int* IndexOffset = (int*) malloc(sizeof(int) * dimCount);
int temp = 1;
for(int i = 0; i < dimCount; i++){
temp = temp * dimLengths[i];
IndexOffset[i] = temp;
}
for(int i = 0; i < dimCount; i++){
SizeOfArray = SizeOfArray * dimLengths[i];
}
output = (int*)malloc(sizeof(int) * SizeOfArray);
}
To get an index use this:
int getArrayIndex(int* coordinates //Coordinates of the wished index as an array (like dimLengths)
){
int index;
int temp = coordinates[0];
for(int i = 1; i < DimAmount; i++){
temp = temp + IndexOffset[i-1] * coordinates[i];
}
index = temp;
return index;
}
Remember to free() your array as soon as you do not need it anymore:
for(int i = 0; i < SizeOfArray; i++){
free(output[i]);
}
free(output);
Can we dynamically allocate 2D array without using any for loop or while loops?
i there any direct command or function in c c++?
Without using a loop you will have one restriction in ISO c++ i.e. size of one dimension has to be determined at compile time. Then this allocation can be done in a single statement as follows:
#define COLUMN_SIZE 10 // this has to be determined at compile time
int main()
{
int (* arr)[COLUMN_SIZE];
int rows = 20; // this is dynamic and can be input from user at run time
arr = new int[rows][COLUMN_SIZE];
arr[3][4] = 10;
cout << arr[3][4] << endl;
return 0;
}
The memory allocated with new needs to be freed. Also if we extend it to n dimensions, only one of these dimensions can be determined at run time. The reason is that compiler has to know the size of each row in order to create a row of contiguous memory.
Although you should avoid raw pointers, this should work->
int *myArray = new int[R*C];
Here R is number of rows and C is number of columns. Although it is really a 1D array, you can manipulate it as 2D array. For example, myArray[i][j] can be read as->
myArray[i*C + j]
The only way to do it with out loops is to allocate a psuedo 2D array thus:
int *ary = new int[sizeX * sizeY];
but then accessing that is non standard & frankly ugly:
ary[y*sizeX + x]
If you want a "real" 2D array then your stuck with loop intialization:
int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
ary[i] = new int[sizeX];
}
But then you have to be careful about clean up:
for(int i = 0; i < sizeY; ++i) {
delete [] ary[i];
}
delete [] ary;
So in my view
std::vector<std::vector < int> >
is probably the simplest and safest way to go in a real world app.
Alternative way to access in arr[..][..] format.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int COL ;
int ROW ;
COL = 8;
ROW = 12;
int (*p)[COL];
int *mem = (int*)malloc(sizeof(int)*COL*ROW);
memset(mem,0,sizeof(int)*COL*ROW);
p = (int (*)[10])mem;
printf("0x%p\n", p);
printf("0x%p %d\n", p+1, (((int)(p+1))-((int)p))/sizeof(int));
mem[2*COL+0] = 1;
printf("%d\n", p[2][0]);
mem[2*COL+5] = 2;
printf("%d\n", p[2][5]);
mem[6*COL+7] = 3;
printf("%d\n", p[6][7]);
p[1][2] = 4;
printf("%d\n", mem[1*COL+2]);
free(p);
return 0;
}
Of course, you can do int (*p)[COL] = (int (*)[COL]) malloc(sizeof(int)*COL*ROW); directly.
A std::map<TypeDim1, std::map<TypeDim2, TypeContent> > might be a dynamically allocated choice to represent a 2D array.
#include <map>
typedef std::map<int, std::map<int, std::string> > array2dstring;
int main(int argc, char *argv[])
{
array2dstring l_myarray2d;
l_myarray2d[10][20] = "Anything";
}
Try to replace loop by recursion
In C++ I'd like to do something like:
int n = get_int_from_user();
char* matrix = new char[n][n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
delete [][] matrix;
but of course this doesn't work. What is the best way to do something similar? I've seen some solutions to this but they seem pretty messy.
The manual dynamic way:
Let's say you want an array of width*height, the most efficient way is to just use a single dimensional array:
char *matrix = new char[width*height];
To delete it:
delete[] matrix;
To access it:
char getArrayValue(char *matrix, int row, int col)
{
return matrix[row + col*width];
}
To modify it:
void setArrayValue(char *matrix, int row, int col, char val)
{
matrix[row + col*width] = val;
}
Boost Matrix:
Consider using boost::matrix if you can have the dependency.
You could then tie into the boost linear algebra libraries.
Here is some sample code of boost::matrix:
#include <boost/numeric/ublas/matrix.hpp>
using namespace boost::numeric::ublas;
matrix<char> m (3, 3);
for (unsigned i = 0; i < m.size1 (); ++ i)
for (unsigned j = 0; j < m.size2 (); ++ j)
m (i, j) = 3 * i + j;
On the stack for some compilers:
Some compilers actually allow you to create arrays on the stack with runtime determined sizes. g++ is an example of such a compiler. You cannot do this by default VC++ though.
So in g++ this is valid code:
int width = 10;
int height = 10;
int matrix[width][height];
Drew Hall mentioned that this C99 feature is called Variable Length Arrays (VLAs) and it can probably be turned on in any modern compiler.
I usually do something like this:
char *matrix = new char [width * height];
matrix[i + j * width] = 'c'; // same as matrix[i][j] = 'c';
delete [] matrix;
You seem to be missing the whole point of C++ (C with classes) :-). This is the sort of use that's crying out for a class to implement it.
You could just use STL or other 3rd party class library which I'm sure would have the data structure you're looking for but, if you need to roll your own, just create a class with the following properties.
constructor which, given n, will just create a new n*n array of char (e.g., charray)..
member functions which get and set values based on x.y which simply refer to charray[x*n+y];
destructor which delete[]'s the array.
What about std::vector< std::vector<int> > array2d; ?
For a true two dimensional array:
int n = get_int_from_user();
char** matrix = new char*[n];
for (int i = 0; i < n; i++) {
matrix[i] = new char[n];
}
// Operations on matrix.
for (int i = 0; i < n; i++) {
delete [] matrix[i];
}
delete matrix;
Just off the top of my head. Mistakes, no doubt. However, other people have posted a more elegant approach, I think.
I like the 1-d array approach (the selected answer by Brian R. Bondy) with the extension that you wrap the data members into a class so that you don't need to keep track of the width separately:
class Matrix
{
int width;
int height;
char* data;
public:
Matrix();
Matrix(int width, int height);
~Matrix();
char getArrayValue(int row, int col);
void setArrayValue(int row, int col, char val);
}
The implementation is an exercise for the reader. ;)
I think this would be a good one.
int n = get_int_from_user();
char **matrix=new (char*)[n];
for(int i=0;i<n;i++)
matrix[i]=new char[n];
matrix[0][0] = 'c';
//...
matrix[n][n] = 'a';
for(int i=0;i<n;i++)
delete []matrix;
delete []matrix;
std::vector<int> m;
Then call m.resize() at runtime.
int* matrix = new int[w*h];
if you want to do something like Gaussian elimination your matrix should be
int** matrix = new int*[h];
for(size_t i(0); i < h; ++i)
matrix[i] = new int[w];
(in Gaussian elimination we usually need to exchange one row with another so it's better to swap pointers to rows in constant time rather than swapping by copying in linear time).