create a Dynamic std::array of std::array - c++

My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
If I was using a simple int array then this would've been a simple task but because I have to use std::array , I am lost .
My attempt so far
#include<iostream>
#include<array>
using std::array;
int main(){
array<array<int,1>*,3> x;
for(size_t i=0;i<3;i++)
{
x[i][0]=array<int,3>;
}
}
which leads to the error
array1.cpp:12:29: error: expected '(' for function-style cast or type
construction
x[i][0]=array;
~~~~~~~~~~~~^ 1 error generated.
when using clang++
I have read that an std::array is equivalent to a normal array ,
I know i can use vectors but since i know how many rows i have from the beginning , I feel it to be a waste to use vectors , while I would love the added functionality of std::array when compared to a traditional array. How do I implement this .

std::array<std::vector<int>,3> is the type you want.
std::vector is a dynamicly sized array.
int main(){
std::array<std::vector<int>,3> x;
for(std::size_t i=0;i<3;i++)
{
x[i]=std::vector<int>(22);
}
}
this creates a 3 "major" element array of 22 "minor" size.
Note that column-major and row-major (which is first and which is second) is a matter of convention. So std::vector<std::array<3,int>> is another equally valid interpretation of the requirements.
If you are banned from using std::vector, you will have to figure out an alternative solution, possibly rolling your own. I'd advise against unique_ptr<int[]> (or worse, raw pointers) as they don't store the size of the element.
A std::array< std::array< cannnot be dynamic in either dimension. std::array is fixed size.

My task requires me to create an array of arrays to store some data , where the number of row is fixed and the columns are to be decided at run-time.
It sounds like your task requires using a matrix class. Like boost::numeric::ublas::matrix.
The benefit of using a matrix class is that internally it uses one dynamic array to minimize storage overhead.
If you are coding this as an exercise create your own matrix class. Otherwise use an existing one.

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.

Get 5 last array objects C++

A simple task, but I don't remember the syntax for C++.
int array[n];
I need to get the last 5 objects of the array.
array.slice(array.length - 5, 1)??
In short
Algorithms will be your friends:
int last[5];
std::copy(array+n-5, array+n, last);
More details
First, the variable length array is not standard C++. So the following code is only portable and valid if n is a constant expression:
int array[n];
So the better approach would be to use vectors of int. The advantage is that their size may evolve dynamically when needed:
vector<int> varray(n);
If really you want to use variable raw arrays, you could use memory allocation, but this is cumbersome since you have to take a lot of precautions (e.g. deleting the allocated object in the end):
int *array = new int[n];
The solution with raw arrays is displayed above. I leave it up to you to generalize it to the k last elements.
The vector variant is very similar:
vector<int> vlast(5);
copy(varray.end()-vlast.size(), varray.end(), vlast.begin());
Note that the copy is more dynamic, since the number of elements will depend on the size of the output vector.
Attention - risk of UB: I leave you as an exercise to adapt the code for both solutions to the case where the size of the array would be smaller than 5.
Now if you like algorithms, it's worth also to look at iterators, because they allow you to do cool tricks like:
copy(vlast.begin(), vlast.end(), ostream_iterator<int>(cout," ")); // display
cout<<endl;
Online demo
Still not convinced by vectors ? Then have a look at these two other vector variants:
vector<int> vlast2(varray.end()-5, varray.end()); // powerful constructor
vector<int> vlast3(varray.rbegin(), varray.rbegin()+5); // and in reverse order

need to create multiple dynamic arrays in c++

I need to create a number of arrays of a certain object where the number I need is dependent on a separate variable the best way to explain it is with a psudo code example:
int num = 4;
for(int i=0;i<num;i++){
object_type arrayi [dynamic size];
}
So i need 4 arrays each with the names array0,array1,array2, and array3 and they must all be dynamic arrays.
Is there anyway to do this in C++?
std::array<std::vector<object_type>, 4> array;
for (auto & v : array)
v.resize(dynamic_size);
The names are array[0], array[1], etc... instead of array1, array2, etc... But who cares? If you absolutely must have those names, then Cassio's answer is your best bet.
Pre C++11 alternative:
std::vector<object_type> array[4];
for (size_t i=0; i<4; ++i)
array[i].resize(dynamic_size);
If you want a variable number of arrays, then you can use a vector of vectors, and actually, the initialization for that is even easier. It doesn't require a loop, you can do it in the constructor.
std::vector<std::vector<object_type>> array(num, std::vector<object_type>(dynamic_size));
Yes, use std::vector<object_type> instead. You can resize to an arbitrary size.
Otherwise for arrays you can use dynamic allocation with
ObjectType* myArray = new ObjectType[number];
but using std::vector instead is recommended.
If there is a way to dynamically create variables like the way you want within C++, I haven't heard of it.
If performance is an issue and you need to construct a bunch of 1-d arrays (rather than an array of arrays or a vector of arrays) then you could do code generation at build time to make as many as you want. That's outside of C++ though; it's a pre-build command that outputs a C++ text file.
If performance isn't an issue, then constructing a vector of arrays like Benjamin has done will work great.
Reading the OP again, it seems to me that the number of arrays is not known at compile time. In this case, you can use a std::vector<std::vector<object_type>>:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<std::vector<object_type>> vs(num);
for (auto& v: vs)
v.resize(dynamic_size);
then you can use vs[i][j] to get a reference to the j-th element of the i-th array (vector).
Piece of advise: Don't use this (std::vector<std::vector<double>>) for linear algebra matrices.
Bonus: In C++14 (actually this is a C99 feature that some compilers allow in C++ as an extension) you'll be able to do this:
#include <vector>
// ...
// int num = ???, dynamic_size = ???;
std::vector<object_type> vs[num];
for (auto& v: vs)
v.resize(dynamic_size);
For more information see this post.

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.

How to Implement a multidimensional array if the dimension is unknown at compile-time?

I want to implement a function that gets as a parameter a dimension "n" of an array of integers. This function also gets values "k_1, k_2, ..., k_n" defining the size of the array. Then this function will fill this n-dimensional array.
How do I implement this efficiently with C++?
For example for n = 3 I would use
vector < vector < vector < int > > > array;
But I don't know the dimension at compile time.
Use a one-dimensional array, and fake the other dimensions using multiplication of offsets for indexing, and you can pass the dimension sizes in by vector, i.e.
std::vector<int> create_md_array(const std::vector<int> & dimensions)
{
int size = std::accumulate(dimensions.begin(), dimensions.end(), 1, std::multiplies<int>());
return std::vector<int>(size);
}
You have a couple of choices. You can implement it yourself, basically multiplying the coordinates by the sizes to linearize the multi-dimensional address, and just have a simple std::vector<whatever> to hold the data.
Alternatively, you could use std::valarray and friends to accomplish the same. It has a set of classes that are specifically intended for the kind of situation you describe -- but they're used so rarely that almost nobody understands them. Writing the code yourself stands a good chance of being easier for most people to read and understand.