How to give names of 2D arrays dynamically in C++? - c++

I want to create few 2D arrays of the same size. e.g. table1[80][3], table2[80][3], table3[80][3], ..., tableN[80][3]. But the number(N) of arrays to create, will be provided by the user.
So, how can I create those arrays dynamically?
Thanks in advance.. :)

You can't have dynamic symbol names of variables or functions in c++. These only matter during compilation of the code, and there's no way to generate them at run time of your program.
As mentioned in my comment, the closest thing you can get is to map those tables with certain std::string values like
std::map<std::string,std::array<std::array<int,3>,80>> tables;
and manipulate values like this
tables["table1"][20][1] = 0;
tables["table2"][10][0] = 42;
// etc. ...

Sounds like a 3d array:
typedef int T[80][3]; // T is your 2d array type
T* tables = new T[N]; // an array of N T's.
Or an amusing mixture of arrays and vectors:
std::vector<T> tables(N); // the same, but safer
Sure, these aren't named... but is table1 really better than tables[0]? Your mileage may vary.

Related

How to pass dynamic and static 2d arrays as void pointer?

for a project using Tensorflow's C API I have to pass a void pointer (void*) to a method of Tensorflow. In the examples the void* points to a 2d array, which also worked for me. However now I have array dimensions which do not allow me to use the stack, which is why I have to use a dynamic array or a vector.
I managed to create a dynamic array with the same entries like this:
float** normalizedInputs;//
normalizedInputs = new float* [noCellsPatches];
for(int i = 0; i < noCellsPatches; ++i)
{
normalizedInputs[i] = new float[no_input_sizes];
}
for(int i=0;i<noCellsPatches;i++)
{
for(int j=0;j<no_input_sizes;j++)
{
normalizedInputs[i][j]=inVals.at(no_input_sizes*i+j);
////
////
//normalizedInputs[i][j]=(inVals.at(no_input_sizes*i+j)-inputMeanValues.at(j))/inputVarValues.at(j);
}
}
The function call needing the void* looks like this:
TF_Tensor* input_value = TF_NewTensor(TF_FLOAT,in_dims_arr,2,normalizedInputs,num_bytes_in,&Deallocator, 0);
In argument 4 you see the "normalizedInputs" array. When I run my program now, the calculated results are totally wrong. When I go back to the static array they are right again. What do I have to change?
Greets and thanks in advance!
Edit: I also noted that the TF_Tensor* input_value holds totally different values for both cases (for dynamic it has many 0 and nan entries). Is there a way to solve this by using a std::vector<std::vector<float>>?
Respectively: is there any valid way pass a consecutive dynamic 2d data structure to a function as void*?
In argument 4 you see the "normalizedInputs" array. When I run my program now, the calculated results are totally wrong.
The reason this doesn't work is because you are passing the pointers array as data. In this case you would have to use normalizedInputs[0] or the equivalent more explicit expression &normalizedInputs[0][0]. However there is another bigger problem with this code.
Since you are using new inside a loop you won't have contiguous data which TF_NewTensor expects. There are several solutions to this.
If you really need a 2d-array you can get away with two allocations. One for the pointers and one for the data. Then set the pointers into the data array appropriately.
float **normalizedInputs = new float* [noCellsPatches]; // allocate pointers
normalizedInputs[0] = new float [noCellsPatches*no_input_sizes]; // allocate data
// set pointers
for (int i = 1; i < noCellsPatches; ++i) {
normalizedInputs[i] = &normalizedInputs[i-1][no_input_sizes];
}
Then you can use normalizedInputs[i][j] as normal in C++ and the normalizedInputs[0] or &normalizedInputs[0][0] expression for your TF_NewTensor call.
Here is a mechanically simpler solution, just use a flat 1d array.
float * normalizedInputs = new float [noCellsPatches*no_input_sizes];
You access the i,j-th element by normalizedInputs[i*no_input_sizes+j] and you can use it directly in the TF_NewTensor call without worrying about any addresses.
C++ standard does its best to prevent programmers to use raw arrays, specifically multi-dimensional ones.
From your comment, your statically declared array is declared as:
float normalizedInputs[noCellsPatches][no_input_sizes];
If noCellsPatches and no_input_sizes are both compile time constants you have a correct program declaring a true 2D array. If they are not constants, you are declaring a 2D Variable Length Array... which does not exist in C++ standard. Fortunately, gcc allow it as an extension, but not MSVC nor clang.
If you want to declare a dynamic 2D array with non constant rows and columns, and use gcc, you can do that:
int (*arr0)[cols] = (int (*) [cols]) new int [rows*cols];
(the naive int (*arr0)[cols] = new int [rows][cols]; was rejected by my gcc 5.4.0)
It is definitely not correct C++ but is accepted by gcc and does what is expected.
The trick is that we all know that the size of an array of size n in n times the size of one element. A 2D array of rows rows of columnscolumns if then rows times the size of one row, which is columns when measured in underlying elements (here int). So we ask gcc to allocate a 1D array of the size of the 2D array and take enough liberalities with the strict aliasing rule to process it as the 2D array we wanted. As previously said, it violates the strict aliasing rule and use VLA in C++, but gcc accepts it.

Arrays of pointer to matrices initialized with arrays

I want to cycle between different matrices using an array of pointer to matrices.I want those matrices' rows initialized using array variables. For different reasons, I can't create a new class.
More specifically I want somethng like that:
First point
#define SIZE size-value
int row1MatrixM [SIZE]= {1,2,3,4,5,1,2,3,4,5};
int row2MatrixM [SIZE] = {2,4,5,7,8,9,10,11,12};
...
Then:
matrixM= {row1MatrixM, row2MatrixM, row3MatrixM .... };
But the complier says I can't initialize a matrix this way.
Now I have:
matrixM, matrixY, matrixX, matrixZ, etc.
Then I would like to access them using pointers, so I would need an array of pointers (a pointer to M, one to Y, etc.)
So I tried to write something like that:
#define NUMBER_OF_MATRICES number-of-matrices-value
int[SIZE][SIZE]* arrayOfPointersToMatrices[NUMBER_OF_MATRICES] = {&matrixM,&matrixY,&matrixX, &matrixZ};
I tried different combinations of [] and ** but no one seems working. I was looking for a type that would allow me to access to the array of pointers (3D array) with brackets:
arrayOfPointersToMatrices[x][y][z]
To get your code working:
Declare the arrays like:
int row1 [NUM_COLS]= {1,2,3,4,5,1,2,3,4,5};
int row2 [NUM_COLS] = {2,4,5,7,8,9,10,11,12};
Declare the 2d matrices like:
int *matrix2d1[NUM_ROWS] = {row1, row2};
int *matrix2d2[NUM_ROWS] = {row3, row4};
Declare the 3d matrices like:
int **matrix3d[NUM_MATRICES] = {matrix2d1, matrix2d2};
An alternative (the "right" way)
I would highly highly highly suggest using vectors. They're baked into the C++ language and infinitely easier than all this array/pointer work.

Get size of 3D char* Array

i'm trying to make a multidimensional array, which holds weapons and their attachments:
I have lots of arrays like this:
char *G18[19] = { "glock_mp", "glock_akimbo_mp", "glock_eotech_mp", "glock_fmj_mp", "glock_reflex_mp", "glock_silencer_mp", "glock_xmags_mp", "glock_akimbo_fmj_mp", "glock_akimbo_silencer_mp", "glock_akimbo_xmags_mp", "glock_eotech_fmj_mp",
"glock_eotech_silencer_mp", "glock_eotech_xmags_mp", "glock_fmj_reflex_mp", "glock_fmj_silencer_mp", "glock_fmj_xmags_mp", "glock_reflex_silencer_mp", "glock_reflex_xmags_mp", "glock_silencer_xmags_mp" };
But all weapons don't belong to same category, f.e. an AK47 is an Assault Rifle and this G18 is a Machine Gun. So i created 2D Arrays which represnt a category, like so:
char **MACHINEGUNS[4] = { G18, TMP, RAFFICA, PP2000 };
so now i have the weapons sorted i created another array which should hold the categories, like so:
char ***WEAPONS[7] = { ASSAULTRIFLES, SUBMACHINEGUNS, LIGHTMACHINEGUNS, SNIPERS, PISTOLS, MACHINEGUNS, SHOTGUNS };
accessing the weapons like
char *weapon = WEAPONS[assaultrifle][ak47][0]; // assaultrifle & ak47 are enum mebers
works perfectly fine. The problem i'm facing is that i can't get the row and column sizes. F.e. if i want to know how many weapon classes their are i would do:
sizeof(WEAPONS)
which gives me 7. If i want to know how many assaultrifles there are i do:
sizeof(WEAPONS[assaultrifles])
But here's the problem: This gives me 4 although the assaultrifle's array size is 9:
char **ASSAULTRIFLES[9] = { AK47, M16A4, M4A1, FN2000, ACR, FAMAS, FAL, SCARH, TAR21 };
it returns 4 aswell if i do this:
sizeof(WEAPONS[assaultrifles][ak47])
even though the ak47's array size is 39. Any idea why it's not working and how i could achiev this? Thanks in advance and sorry for the long text!
There is no such thing as "getting the size" of an array at runtime in C or C++. You can get the size of an array (declared with [<size>]) with sizeof because its size is known at compile time. When you get the sizeof a pointer you are literally getting how many bytes a pointer takes, which is why you get 4. If you want to know the size of a vector at runtime, the typical options are:
Use std::vector, and STL containers in general. There are a million tutorials and examples out there that you can check about that.
Instead of storing raw arrays (or pointers to arrays), store simple structs or classes containing the pointer to the array and the size. This is kinda like rolling your own, limited std::vector, and you have to be careful of freeing the memory correctly where necessary and so on, so I'm not sure it's a great choice.
Some other dirty C-like trick like adding NULL/nullptr at the end of every array and then iterate through the whole thing until you reach it every time you need to find the size. Inefficient and error-prone.
So, yeah, in short, use std::vector or other containers.

Trouble with initializing multidimensional array

We usually initialize a 2D array like this:
int a[2][3] = {{2,3,4},{5,6,7}};
I need to initialize the 2D array like this:
int a[2][3];
a[0] = {2,3,4};
a[1] = {5,6,7};
i.e. I want initialize it array by array. Why does this method fail? What should I do? Or can I define a as array of array?
The idea of an array is to keep all the data in memory contiguous, this would not be achieved with the approach you are using, I would recommend using a C style memory management with RAW memory for a low level fast, thigh and possibly dangerous solution, or change to a different data container like the vector (or others) where you can add elements similar to what you want and the memory will still be contagious like the simple array. Although depending on the size of your problem it might be an overkill to use a vector.

How to create variable name with integer appended to the end?

I want to create a for loop that will fill a bunch of arrays with data in c++. Now to save space and in the future once more arrays are added which they will, I have the for loop. Each array for demonstration purposes is called Array# (# being a number) The point of the for loop would be to set a constant with maximum arrays, then cycle through each array filling by appending i to the end of the Array name.
For example in pseudo code:
for (i = 1; i < numberofarrays; i++)
{ fill (Array & i) with ("Array" & i & "-default.txt")}
It is impossible to generate Variable Names by any type of code.
(Meaning it is impossible to generate dynamic variable names on Runtime or on Compiletime)
The best solution possible would be a array of arrays:
int Arrays[][];
Calling Arrays[0] would give you the first array.
If you want to determine the number of arrays during Runtime you need to use pointers!
That would look like that:
(int[])* Arrays = new (int[])[numberofarrays];
Accessing the arrays in the array would work the same!
An alternative would be using the container vector from std.
The code would the look like this:
#include<vector>
// More includes
// Optional
using namespace std;
// Somewhere in your code
vector<vector<int>> Arrays;
You still would acces the elements by using your standard array method (Arrays[15][78] e.g.)
You don't really need the name. You can use an std::vector of arrays. This will not work out of the box, see Correct way to work with vector of arrays
Another approach would be to have an std::map of arrays. You could have the name as the key, if that is what you really want. You will still have to use the same workaround as before to have an array as a value. See Character Array as a value in C++ map for example.