This question already has answers here:
How do I declare a 2d array in C++ using new?
(29 answers)
Closed 8 years ago.
I've stuck on a problem - I can't declare 2D arrays in C++ using integers, written by user.
This code works fine-
cin>>m>>n;
int *array;
array=new int[m*n];
But I can't make this work -
cin>>m>>n;
int *array;
array=new int[m][n];
Any ideas how i can bypass it?
P.S. the error : cannot convert 'int ()[2]' to 'int' in assignment.
Change
cin>>m>>n;
int *array;
array=new int[m][n];
to
cin>>m>>n;
int **array;
array=new int * [m];
for ( int i = 0; i < m; i++ ) array[i] = new int[n];
array is int * and you try to assign int **... change array to int**.
2D array is actually array of arrays, so you need pointer to pointer.
That's because you can only use new to allocate 1D arrays. In fact, 2D arrays are also 1D arrays, where, in most systems, all rows are simply concatenated. That is called a row-major memory layout.
You can emulate 2D arrays with a 1D array. The index conversion is:
index1 = y * m + x
This also has much better performance than creating one array per row, as recommended in the "duplicate" link or in other answers.
Just as Domi said (but not index1=y*m+x but rather index1=x*n+y to emulate your desired notation):
int *array = new int [m*n];
int get (int x, int y) // emulates array[x][y] for array[m][n]
{
return array[x*n+y];
}
However, I think the real 2-dimensional allocation (as Vlad from Moscow showed you) is slower in creation (and needs a bit more memory), but quicker in accessing. Cause array[x*n+y] == *(array+x*n+y), wether array[x][y] == *(*(array+x)+y), so you have one multiplication less, but one dereferenciation more, in sum I think it's quicker.
You could also create a class:
class array2d
{
private:
int *data;
int mm, nn;
public:
array2d (int m, int n)
{
mm = m;
nn = n;
data = new int [m*n];
}
~array2d ()
{
delete[] data;
}
int *operator[] (int x)
{
return (data+x*nn);
}
};
With it you can use
array2d arr(10,10);
arr[5][7] = 1;
You can do this:
typedef int RowType[n];
RowType *array = new RowType[m];
doStuffWith(array[y][x]);
Or, even shorter (but harder to remember):
int (*array)[n] = new (int[m][n]);
Edit:
There is a catch in C++ that array sizes must be constant for the new operator, so you can only do this if n is const. This is not a problem in C (and the reason I forgot about this), so the following works even if n and m are not const:
RowType *array = (RowType*)malloc(m * sizeof(RowType));
Of course, you can work around this restriction in C++ by doing this, which works even if both m and n are dynamic:
RowType *array = (RowType*)new int[m * n];
The typedef free version would be this:
int (*array)[n] = (int (*)[n])new int[m *n];
Firstly I suggest you should use std::vector to avoid memory allocation / deallocation issues.
In case you want an array implementation, then you can declare array as a pointer to pointer to int.
cin >> m >> n;
int** array = new int* [m];
for ( int I = 0; I < m; I++ ) {
array[I] = new int[n];
}
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 recently started programming in C++, I have quite some experience in JAVA programming but I am facing a rather unclear situations whilst trying to initialize multi dimensional arrays in c++.
The code I would use in java would be something like:
int x = 5;
int y = 10;
int array [][] = new int[x][y];
which works fine, I could assign any value to x and y using a scanner or option pane. However (and please bear with me, I am quite new to c++) in c++ I am required to use constants which prevent me from using for example:
int x;
cin >> x;
int y;
cin >> y;
int array [][] = new int[x][y];
I am trying to make a random map generator, eventually i will assign 3d object to positions within the array and design an algorithm to sort all of the objects. However I want the user to be able to specify the size of the grid, specify x and y, the rows and columns.
Any help would be greatly appreciated!
Many thanks in advance.
This record
int array [][] = new int[x][y];
is invalid in C++. If you want to allocate an array in the heap using operator new and the right dimension is not a constant expression then you should write
int x;
cin >> x;
int y;
cin >> y;
int **array = new int *[x];
for ( int i = 0; i < x; i++ ) array[i] = new int[y];
If the right dimension is set by a constant expression then you can write
int x;
cin >> x;
const int y = SomeValue;
int ( *array )[y] = new int [x][y];
Take into account that you could use standard container std::vector instead of a manually allocated array.
For example
std::vector<std::vector<int>> v( x, std::vector<int>( y ) );
There are multiple ways to do this. To create a permanent array on the heap:
int** data = new int*[x];
for(int i = 0; i < x;i++)
{
data[i] = new int[y];
}
To create an array of fixed size on the stack:
int data[5][5];
The dimensions of the array must be known at compile time.
For me this simple code fails to compile due to lack of knowledge of the array size.
int i = 5;
int arr [] = new int[i];
arr[2] = 2;
If you want to use arrays you have two choices, use constants that are known at compile time, or create the array using malloc to reserve memory.
If you are able to use the STL use the vector class.
int i = 5;
vector<int> vec(i);
vec[2] = 2;
Or you could use pointers as shown in 'Vlad from Moscow' or 'user3482801' answers.
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);
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).