How to create variable name with integer appended to the end? - c++

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.

Related

Find End of Array Declared as Struct Type C++

I was recently learning to use struct datatype in c++. I know how the basics of struct datatype work and how to manipulate its variables. But I was wondering how would I determine the end of struct datatype array. For example consider the code below:
struct PersonDetails
{
string name, address;
int age, number;
}
Now in c++ program I create an array of struct type as follows:
PersonDetails Data[500];
Now consider that I have 30 records in data array and I have to display these records by looping through data array's index. So how would I determine that I have to loop through only first 30 indexes as the data is only stored in these indexes. As in char array we compare all indexes with '\0' to determine the end of array. Then what method will we use for Data[] array?
An edit that I have no idea about Vectors and the project i am working on requires me to use basics of c++(functions, control structures, loops, etc.).
It's not feasible.
For char[], back in times of C standardization, developers agreed to use \0 (integer value 0) as a special character marking end-of-string. Everything works as long as everyone is following this convention (i.e. both standard library functions and developers using those functions).
If you wanted to have such a convention for your type, you could just write down "Data object with both strings empty and both ints equal to 0 is array terminator", but you would have to follow this convention. You'd have to write functions that would stop processing array upon finding such an object. You'd have to make sure that in every array there is at least one such object.
Instead
You should use std::vector<Data> which can automatically accomodate for any number of Data objects and will now precisely how many of them are currently stored (using size() method)
or
use std::array<Data, 30>, which can store exactly 30 objects and you can assume all of them are valid objects.
IMHO the correct way to solve this is to not use a C-style array, but instead use a std::array or std::vector that knows it's .size().
Iterating a std::vector or std::array is trivial:
for (const auto& element : Data_array) {
// Do something with the array element
}
See also:
https://en.cppreference.com/w/cpp/container/array
https://en.cppreference.com/w/cpp/container/vector
https://en.cppreference.com/w/cpp/language/for
https://en.cppreference.com/w/cpp/language/range-for
The simplest solution is to just have a separate variable specifying how many array elements are filled in.
PersonDetails Data[500];
int numPersons = 0;
Data[0].name = ... ;
Data[0].address = ...;
Data[0].age = ...;
Data[0].number = ...;
numPersons = 1;
Data[1].name = ... ;
Data[1].address = ...;
Data[1].age = ...;
Data[1].number = ...;
numPersons = 2;
...
Then you use that variable when looping through the array.
for (int i = 0; i < numPersons; ++i)
{
// use Data[i] as needed...
}
I don't really agree using std::array makes any difference.
The problem you currently have doesn't occur in whether we have such an element in the container, but whether the element we are inspecting useful.
Consider the example you gave, for an array of chars, we simply check whether one of the elements is \0 to decide whether or not we should halt the iteration.
How does that work? The ramaining elements, of course, default initialized to be \0, they exist, but of no use.
Similarly, you can check, in this example, whether
name.empty()
Or, in order to avoid any possible exception, as mentioned in the comment section, do this:
add user-defined constructor to the class ( or struct, they are same actually.) which initialize age to -1 and then check if age == -1.
because it's impossible for a people not having any name, that means, you have not assign to any of the remaining elements. Thus, stop iteration.
As a supplement, using std::vector makes sense, but if that isn't a option for you for the time being, you don't need to consider it.

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.

create a Dynamic std::array of std::array

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.

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.

Convert std::vector to array

I have a library which expects a array and fills it. I would like to use a std::vector instead of using an array. So instead of
int array[256];
object->getArray(array);
I would like to do:
std::vector<int> array;
object->getArray(array);
But I can't find a way to do it. Is there any chance to use std::vector for this?
Thanks for reading!
EDIT:
I want to place an update to this problem:
I was playing around with C++11 and found a better approach. The new solution is to use the function std::vector.data() to get the pointer to the first element.
So we can do the following:
std::vector<int> theVec;
object->getArray(theVec.data()); //theVec.data() will pass the pointer to the first element
If we want to use a vector with a fixed amount of elements we better use the new datatype std::array instead (btw, for this reason the variable name "array", which was used in the question above should not be used anymore!!).
std::array<int, 10> arr; //an array of 10 integer elements
arr.assign(1); //set value '1' for every element
object->getArray(arr.data());
Both code variants will work properly in Visual C++ 2010. Remember: this is C++11 Code so you will need a compiler which supports the features!
The answer below is still valid if you do not use C++11!
Yes:
std::vector<int> array(256); // resize the buffer to 256 ints
object->getArray(&array[0]); // pass address of that buffer
Elements in a vector are guaranteed to be contiguous, like an array.