I would like to get a two dimensional int array arr that I can access via arr[i][j].
As far as I understand I could declare int arr[10][15]; to get such an array.
In my case the size is however variable and as far as I understand this syntax doesn't work if the size of the array isn't hardcoded but I use a variable like int arr[sizeX][sizeY].
What's the best workaround?
If you don't want to use a std::vector of vectors (or the new C++11 std::array) then you have to allocate all sub-arrays manually:
int **arr = new int* [sizeX];
for (int i = 0; i < sizeX; i++)
arr[i] = new int[sizeY];
And of course don't forget to delete[] all when done.
c/c++ does not support multidimensional array. But it does support array of array:
//simulate 2-dimension array with 1-dimension array
{
int x = 20;
int y = 40;
int * ar = new int(x*y);
int idx_x =9;
int idx_y=12;
ar[idx_x + idx_y * x] = 23;
}
//simulate 2-dimension array with array of array
{
int x = 20;
int y = 40;
int**ar = new int*[y];
for(int i = 0; i< y; ++i)
{
ar[i] = new int[x];
}
ar[9][12] = 0;
}
If you're looking for the solution in C, see this Stack Overflow thread:
How do I work with dynamic multi-dimensional arrays in C?.
If C++ is okay, then you can create a 2D vector, i.e. a vector of vectors. See http://www.cplusplus.com/forum/general/833/.
You can't, with array syntax. The language requires that you use compile time constants to create arrays.
C++ does not have variable length arrays. You can consider using vector<vector<int> >. It can be also accessed using arr[i][j].
As fefe said you can use vector of vectors, e. g. :
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector< vector<int> > vec;
vector<int> row1;
row1.push_back(1);
row1.push_back(2);
vector<int> row2;
row2.push_back(3);
row2.push_back(4);
vec.push_back(row1);
vec.push_back(row2);
for( int ix = 0; ix < 2; ++ix)
for( int jx = 0; jx < 2; ++jx)
cout << "[" << ix << ", " << jx << "] = " << vec[ix][jx] << endl;
}
Related
On a project I'm working on, I need some dynamic allocation due to the size of the used data not been known in advance. std::vector seems perfect for this use case. However, due to the software environnement, I can not use "modern" C++ in the headers. I would like to convert this vectors array to be used in fuction with compliant headers.
Quick example:
void func(int tab[][]/*Vector can not be used here*/){/*Do things*/}
int main(){
std::vector<int> vecTab[6/*Fixed, prior known, dimension*/];
//Adding a random number of values in each vector (equal number in each one)
//Transformation of vecTab
func(vecTabMod);
return 1;
}
There is a lot of similar questions on this site, none of them really adressing bi-dimensionnal arrays.
Bonus point: no reallocation, access through pointers
You'll need to copy the data pointers into a separate array so that the type and layout matches what the funciton expects. This can be done without heap allocation since the size of this array is fixed.
int* vecTabMod[6];
std::transform(std::begin(vecTab), std::end(vecTab), std::begin(vecTabMod),
[](auto& v) { return v.data(); });
func(vecTabMod);
std::vector is worst choice for this soultion!
Using dynamic arrays is better.
Anyway you can use this code:
#include <vector>
#include <iostream>
int func(uint32_t firstDimensionSize, uint32_t* secoundDimensionSizes, int** tab){
int sum = 0;
for(uint32_t i = 0; i < firstDimensionSize; i++){
for(uint32_t j = 0; j < secoundDimensionSizes[i]; j++){
sum += tab[i][j];
}
}
return sum;
}
int main(){
std::vector<int> vecTab[6];
vecTab[0].push_back(2);
vecTab[0].push_back(5);
vecTab[3].push_back(43);
// Calculate count of elements in non dynamically arrays
uint32_t firstDimensionSize = (sizeof(vecTab) / sizeof((vecTab)[0]));
uint32_t* secoundDimensionSizes = new uint32_t[firstDimensionSize];
int**tab = new int*[firstDimensionSize];
for(uint32_t i = 0; i < firstDimensionSize; i++){
secoundDimensionSizes[i] = vecTab[i].size();
tab[i] = &(vecTab[i][0]);
}
std::cout << func(firstDimensionSize, secoundDimensionSizes, tab) << std::endl;
delete[] secoundDimensionSizes;
delete[] tab;
system("pause");
}
I am new to C++ and programming in general so i apologize if this is a trivial question.I am trying to initialize 2 arrays of size [600][600] and type str but my program keeps crashing.I think this is because these 2 arrays exceed the memory limits of the stack.Also,N is given by user so i am not quite sure if i can use new here because it is not a constant expression.
My code:
#include<iostream>
using namespace std;
struct str {
int x;
int y;
int z;
};
int main(){
cin>>N;
str Array1[N][N]; //N can be up to 200
str Array2[N][N];
};
How could i initialize them in heap?I know that for a 1-D array i can use a vector but i don't know if this can somehow be applied to a 2-D array.
How 2-or-more-dimensional arrays work in C++
A 1D array is simple to implement and dereference. Assuming the array name is arr, it only requires one dereference to get access to an element.
Arrays with 2 or more dimensions, whether dynamic or stack-based, require more steps to create and access. To draw an analogy between a matrix and this, if arr is a 2D array and you want access to a specific element, let's say arr[row][col], there are actually 2 dereferences in this step. The first one, arr[row], gives you access to the row-th row of col elements. The second and final one, arr[row][col] reaches the exact element that you need.
Because arr[row][col] requires 2 dereferences for one to gain access, arr is no longer a pointer, but a pointer to pointer. With regards to the above, the first dereference gives you a pointer to a specific row (a 1D array), while the second dereference gives the actual element.
Thus, dynamic 2D arrays require you to have a pointer to pointer.
To allocate a dynamic 2D array with size given at runtime
First, you need to create an array of pointers to pointers to your data type of choice. Since yours is string, one way of doing it is:
std::cin >> N;
std::string **matrix = new string*[N];
You have allocated an array of row pointers. The final step is to loop through all the elements and allocate the columns themselves:
for (int index = 0; index < N; ++index) {
matrix[index] = new string[N];
}
Now you can dereference it just like you would a normal 2D grid:
// assuming you have stored data in the grid
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << matrix[row][col] << std::endl;
}
}
One thing to note: dynamic arrays are more computationally-expensive than their regular, stack-based counterparts. If possible, opt to use STL containers instead, like std::vector.
Edit: To free the matrix, you go "backwards":
// free all the columns
for (int col = 0; col < N; ++col) {
delete [] matrix[col];
}
// free the list of rows
delete [] matrix;
When wanting to allocate a 2D array in C++ using the new operator, you must declare a (*pointer-to-array)[N] and then allocate with new type [N][N];
For example, you can declare and allocate for your Array1 as follows:
#define N 200
struct str {
int x, y, z;
};
int main (void) {
str (*Array1)[N] = new str[N][N]; /* allocate */
/* use Array1 as 2D array */
delete [] Array1; /* free memory */
}
However, ideally, you would want to let the C++ containers library type vector handle the memory management for your. For instance you can:
#include<vector>
..
std::vector <std::vector <str>> Array1;
Then to fill Array1, fill a temporary std::vector<str> tmp; for each row (1D array) of str and then Array1.push_back(tmp); to add the filled tmp vector to your Array1. Your access can still be 2D indexing (e.g. Array1[a][b].x, Array1[a][b].y, ..., but you benefit from auto-memory management provided by the container. Much more robust and less error prone than handling the memory yourself.
Normally, you can initialize memory in heap by using 'new' operator.
Hope this can help you:
// Example program
#include <iostream>
struct str {
int x;
int y;
int z;
};
int main()
{
int N;
std::cin>>N;
str **Array1 = new str*[N]; //N can be up to 200
for (int i = 0; i < N; ++i) {
Array1[i] = new str[N];
}
// set value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
Array1[row][col].x=10;
Array1[row][col].y=10;
Array1[row][col].z=10;
}
}
// get value
for (int row = 0; row < N; ++row) {
for (int col = 0; col < N; ++col) {
std::cout << Array1[row][col].x << std::endl;
std::cout << Array1[row][col].y << std::endl;
std::cout << Array1[row][col].z << std::endl;
}
}
}
I am trying to implement a binary tree as a 2d array. I want the user to enter the required height of the tree and the program should give an appropriate size array. Then, I want to print the array, which is why I need to pass it as a parameter. However, I get the following error:
arrayTree/main.cpp|19|error: cannot convert ‘std::__cxx11::string** (*)[maxNumberOfNodes] {aka std::__cxx11::basic_string<char>** (*)[maxNumberOfNodes]}’ to ‘std::__cxx11::string** {aka std::__cxx11::basic_string<char>**}’ for argument ‘1’ to ‘void printTree(std::__cxx11::string*)’|
Please, what is causing the error and how can I fix it?
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
void printTree(string** tree);
int main()
{
int treeHeight = 0;
int maxNumberOfNodes = 1;
cout << "enter tree height";
cin >> treeHeight;
cout << treeHeight<< "\n";
//create an array that can hold every combination for a given tree height
maxNumberOfNodes = pow(2,treeHeight) - 1;
string** tree [3][maxNumberOfNodes];
cout << maxNumberOfNodes;
printTree(tree);
}
void printTree(string** tree){
//not fully implemented yet
for(int i=0; i < sizeof(tree); i++){
cout << "*" << " ";
}
}
string** tree [3][maxNumberOfNodes];
is the syntax of a static 2D array of type string** , where both dimensions have to be declared const.
The difference between a static and a dynamic array is shown in here: Multidimensional variable size array in C++
Instead you want to write something like
string** tree = new string*[3];
for(int i = 0; i < 3; i++)
tree[i] = new string[maxNumberOfNodes];
As #Remy Lebeau commented: Every occurrence of new[] needs to be answered by a delete[] call, like this:
for (int i = 0; i < 3; i++)
delete tree[i];
delete[] tree;
to remove the dynamic allocation from the heap.
Like #drescherjm pointed out sizeof(tree) is not valid, as tree is just a pointer and does not include size information about the array.
You could solve this by additionally passing the dimensions of your array with it:
void printTree (string** tree, int dim, int dim2)
and rewriting the loop to
for(int i = 0; i < dim; i++){
for(int j = 0; j < dim2; j++){
cout << tree[i][j]; //...
}
}
string** tree [3][maxNumberOfNodes];
This declares a 2D array of string** pointers. That is not what you want. You want a 2D array of string objects instead, so drop the pointers:
string tree [3][maxNumberOfNodes];
Also, your printTree() is not implemented correctly. It would need to be implemented more like this instead:
void printTree(string** tree, int height) {
for(int i = 0; i < 3; i++) {
for(int j = 0; j < height; j++) {
// use tree[i][j] as needed ...
}
}
}
That being said, since the value of maxNumberOfNodes is not known until runtime, the string tree [3][maxNumberOfNodes] syntax is declaring a Variable Length Array, which is not officially supported by the C++ standard, only as an extension by a few C++ compilers. You need to use new[] instead to allocate the 2nd dimension:
string* tree [3];
for(int i = 0; i < 3; ++i)
tree[i] = new string[maxNumberOfNodes];
printTree(tree, maxNumberOfNodes);
for(int i = 0; i < 3; ++i)
delete[] tree[i];
Or better, use std::vector instead:
std::vector<string> tree [3];
for(int i = 0; i < 3; ++i)
tree[i].resize(maxNumberOfNodes);
Though, in this latter case, you won't be able to pass tree to a string** function parameter, so you will have to adjust the code accordingly.
the method call is given by
printTree(tree [3][maxNumberOfNodes]);
it's working for me
This question already has answers here:
how to use memset for double dimentional array?
(2 answers)
Closed 9 years ago.
What is the fastest way to set a 2-dim array of double,such as double x[N][N] all to -1?
I tried to use memset, but failed. Any good idea?
Use: std::fill_n from algorithm
std::fill_n(*array, sizeof(array) / sizeof (**array), -1 );
Example:
double array[10][10];
std::fill_n( *array, sizeof(array) / sizeof (**array), -1.0 );
//Display Matrix
for(auto i=0;i<10;i++)
{
for(auto j=0;j<10;j++)
cout<<array[i][j]<< " ";
cout<<endl;
}
A simple loop:
#include <stdio.h>
int main(void)
{
#define N 5
double x[N][N];
size_t i, n = sizeof(x) / sizeof(double);
for (i = 0; i < n; i++)
x[0][i] = -1.0;
for (i = 0; i < n; i++)
printf("%zu) %f\n", i, x[0][i]);
}
// create constants
const int rows = 10;
const int columns = 10;
// declare a 2D array
double myArray [rows][columns];
// run a double loop to fill up the array
for (int i = 0; i < rows; i++)
for (int k = 0; k < columns; k++)
myArray[rows][columns] = -1.0;
// print out the results
for (int i = 0; i < rows; i++) {
for (int k = 0; k < columns; k++)
cout << myArray[rows][columns];
cout << endl;
}
Also you can set directly
double x[4][4] = {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1}
if the array index is small.
Using std::array and its fill method:
#include <array>
#include <iostream>
int main()
{
const std::size_t N=4
std::array<double, N*N> arr; // better to keep the memory 1D and access 2D!
arr.fill(-1.);
for(auto element : arr)
std::cout << element << '\n';
}
Using C++ containers you can use the fill method
array<array<double, 1024>, 1024> matrix;
matrix.fill(-1.0);
if, for some reason, you have to stick with C-style arrays you can initialize the first row manually and then memcpy to the other rows. This works regardless if you have defined it as static array or allocated row by row.
const int rows = 1024;
const int cols = 1024;
double matrix[rows][cols]
for ( int i=0; i<cols; ++i)
{
matrix[0][cols] = -1.0;
}
for ( int r=1; r<rows; ++r)
{
// use the previous row as source to have it cache friendly for large matrices
memcpy(&(void*)(matrix[row][0]), &(void*)(matrix[row-1][0]), cols*sizeof(double));
}
But I rather would try to move from C style arrays to the C++ containers than doing that kind of stunt.
memset shouldn't be used here because it is based on void *. So all bytes in are the same. (float) -1 is 0xbf800000 (double 0xbff0000000000000) so not all bytes are the same...
I would use manual filling:
const int m = 1024;
const int n = 1024;
double arr[m][n];
for (size_t i = 0; i < m*n; i++)
arr[i] = -1;
Matrix is like array in memory, so better to have 1 loop, it slightly faster.
Or you can use this:
std::fill_n(arr, m*n, -1);
Not sure which one is faster, but both looks similar. So probably you'll need to make small test to find it out, but as far as I know people usually use one or another. And another thing first one is more C on some compiler it won't work and second is real C++ it and never works on C. So you should choose by the programming language I think :)
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