Use the index in naming variables during a cycle C++ - c++

I need a tip in creating a C++ utility.
I'm implementening an optimization algorithm, and at a certain step, I would need to create as much new variables as the iterations of a cycle.
There's some code that would explain it better:
for(int i=1;i<112;i++){
struct nodo n_2i[111-i];
}
The structure nodo is defined as:
struct nodo{
int last_prod;
int last_slot;
float Z_L;
float Z_U;
float g;
bool fathomed;
};
I would like the names of the new variables (arrays of structures) to be n_21,n_22,n_23,...etc.
How can I handle that?

Why do you need the name to be n_21. you can use a vector of vector.
#include <vector>
using namespace std;
int main() {
vector<vector<struct nodo> > n;
for(int i=1;i<112;i++){
n.push_back(vector<struct nodo>(111-i));
}
// you can use n[0] ... n[111] now
}

You can't declare new variable names during run-time. You're best off creating a std::vector of the variables.

Once the code is compiled, variable names are no longer present. At compile time the loop is a single construct (unless/until it is unrolled), and at that point it does not make sense to have different names referring to the same compile time element (the variable). The whole question makes little sense, I would advise you to provide a single variable with a good name that need not change for each iteration.
Also, c++ has no variable sized arrays, that is a C99 construct that only some compilers accept, so you might want to get rid of that and use a single array of the greatest size you will need together with a constant initialized in each iteration that will control how many of the positions of the array are valid. If you don't have an upper bound on the size, you can dynamically allocate the memory before entering the loop and release after completing the last iteration. (to avoid the expense of reallocating with each iteration.
That is, unless you need to check the previous step results...

You might want to use a std::map<string,struct nodo*>, and hold your elements in it.
also note you cannot declare a static variable which length depends on i, as your example shows, you are going to need a std::vector or to dynamically allocate memory.
If you decide to use a vector, your map will be of type map<string,vector<struct node> >

A map should do that for you:
std::map<string, struct nodo*> n_2i;

I believe that an std::map will help here:
std::map< int , std::vector< struct nodo > > n;
for(int i=1;i<112;i++){
n.insert(std::make_pair(i, std::vector<struct nodo>(111-i)));
}
you could access you values after with using the index:
n[0].SomeProperty;

Related

iterate over std::vector of std::vector [duplicate]

I'm trying to pass a variable of type vector<vector<double> > to a function F(double ** mat, int m, int n). The F function comes from another lib so I have no option of changing it. Can someone give me some hints on this? Thanks.
vector<vector<double>> and double** are quite different types. But it is possible to feed this function with the help of another vector that stores some double pointers:
#include <vector>
void your_function(double** mat, int m, int n) {}
int main() {
std::vector<std::vector<double>> thing = ...;
std::vector<double*> ptrs;
for (auto& vec : thing) {
// ^ very important to avoid `vec` being
// a temporary copy of a `thing` element.
ptrs.push_back(vec.data());
}
your_function(ptrs.data(), thing.size(), thing[0].size());
}
One of the reasons this works is because std::vector guarantees that all the elements are stored consecutivly in memory.
If possible, consider changing the signature of your function. Usually, matrices are layed out linearly in memory. This means, accessing a matrix element can be done with some base pointer p of type double* for the top left coefficient and some computed linear index based on row and columns like p[row*row_step+col*col_step] where row_step and col_step are layout-dependent offsets. The standard library doesn't really offer any help with these sorts of data structures. But you could try using Boost's multi_array or GSL's multi_span to help with this.
The way I see it, you need to convert your vector<vector<double> > to the correct data type, copying all the values into a nested array in the process
A vector is organised in a completely different way than an array, so even if you could force the data types to match, it still wouldn't work.
Unfortunately, my C++ experience lies a couple of years back, so I can't give you a concrete example here.
Vector< Vector< double> > is not nearly the same as a double pointer to m. From the looks of it, m is assumed to be a 2-dimensional array while the vector is could be stored jagged and is not necessarily adjacent in memory. If you want to pass it in, you need to copy the vector values into a temp 2dim double array as pass that value in instead.

Vectors in structs

So basically I'm making a short version of Monoply. And I need to make a vector of a struct to contain all the info for multiple players that the user enters that also contains the properties owned by each player. I have a function to create x amount of players and all assign each player with the starting cash. However, when I compile this code, I get the error libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector. What am I doing wrong? Thank you!
void createPlayers(Board b, Rules r, int players)
{
for(int i = 0; i < players; i++)
{
b.listOfPlayers.at(i).cash = r.startCash;
}
for(int i = 0; i < players; i++)
{
cout << b.listOfPlayers.at(0).cash;
}
}
typedef struct Player_Struct
{
int cash;
vector<char> propertiesOwned;
} Player;
typedef struct Board_Struct
{
vector<char>listOfProperties;
vector<Player_Struct> listOfPlayers;
} Board;
Is this even a good way to attack the problem? The number of players is up to the user and I can't initialize a certain number of player_structs in the struct initialization. My thinking is to create a vector list of all the players, then be able to draw information out of each player in the vector list. Am I on the right track, logically at least, even though my code is really bad? I'm still new to C++ just switched from C.
You don't show any outputs nor what the variable values are when the error occurs.
You can reference elements in a vector the same as in a normal array such as b.listOfPlayers[i].
It is better practice to specify library, better to write std::vector<int> than vector<int>.
You don't need to pass players you could simply use a built in function on a vector .size() such as b.listOfPlayers.size().
You don't need to specify typedef on structs.
To sum up what people have said and a little more. Perhaps not the answer you wanted, but the answer you needed.
I can see how coming from C you would opt to code this project using Structs, but you're using C++, where you can make use of OOP concepts.
Start off by changing structs into classes, this way you can make use of Inheritance, encapsulation, abstraction and polymorphism concepts. Have a look at this. Keep Structs as POD, and use Classes for everything else
If you are learning C++, code in C++ and make use of its features, avoid using C++ as C with classes.
Going back to your original question;
If you want to add to a vector, use push_back. In your case listOfPlayers looks to be empty or i is out of bounds, so when you're calling .at as per documentation;
If this is greater than, or equal to, the vector size, an exception of type out_of_range is thrown.
To fix this, add Items to the vector using push_back and make sure that i is within bounds of the vector.
I suggest you read this

Accessing pointers of vector elements

I have this struct:
struct povezava{
int p;
int q;
int cena;
int index;
};
and this vector that contains pointers to the struct
vector<povezava*> povezave;
and I have to read information from a text file and then appoint the values to the elements of the vector
while(graf >> p1 >> q1 >> cena1){
povezave[counter]->p=p1;
povezave[counter]->q=q1;
counter++;
}
But there is an error when I try to access these elements, I'm guessing because they are not defined yet? The task says I have to use static data structures but that's impossible since the size of the array is dependant on a number in the graph. Is my only option to use dynamic allocation?(I really don't want to).
But there is an error when I try to access these elements, I'm guessing because they are not defined yet?
That's right. You need to create the elements. Fortunately, that's really easy, and should be demonstrated early on in your C++ book.
while(graf >> p1 >> q1 >> cena1){
povezava newElement;
newElement.p = p1;
newElement.q = q1;
povezave.push_back(newElement);
}
In this example I've also assumed that the vector is changed to std::vector<povezava>, because you've given no reason for it not to be.
You should go further and change its really confusing name.
Is my only option to use dynamic allocation?(I really don't want to).
Well, you already are (or, at least, you would be). A vector dynamically allocates its elements.
The task says I have to use static data structures but that's impossible since the size of the array is dependant on a number in the graph.
Depending on what this vague requirement means, it's possible that you cannot use a vector.
If you don't allocate the memory for the elements of the vector, you can't use them (set member of the elements, ...).
But the best solution is to have statically allocated variable inside the vector:
vector<povezava> povezave;
Of course, it means that you have to change the -> to . because the member aren't pointer anymore.

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 store an unknown number of elements in an array C++

Sorry if the title is not clear but I ll explain now my problem. I am new in C++.
I have created a class in C++. Instances of that class are the input of the program and they have to be stored in an array to perform the calculations. The problem is that the number of instances of that class that have to be defined by the user is fixed for a single run but can vary from run to run. Here an example:
#include <<blablah>blahblah>
int main()
{
int number_of_instances = 3;
MyClass first_instance(one_parameter_1, another_parameter_1);
MyClass second_instance(one_parameter_2, another_parameter_2);
MyClass third_instance(one_parameter_3, another_parameter_3);
///////////////////
NOW I HAVE TO STORE ALL THREE IN AN ARRAY LIKE
MyClass array[number_of_instances] = {first_instance, second_instance, third_instance};
THE PROBLEM IS THAT I DO NOT KNOW BEFORE HAND HOW MANY OF THEM ARE THE USER IS GOING TO INPUT
///////////////////
performCalculations(array);
return 0;
}
Thanks a lot in advance.
The typical C++ solution is to use a vector.
vector<MyClass> v;
v.push_back(first_instance); //add an already instantiated object to the end of the vector
v.push_back(second_instance);
v.push_back(third_instance);
You won't have to worry about memory management and you are able to access the vector like you would a normal array:
v[0].classMember
You can also add items to the vector in a loop if needed like so:
for(int i = 0; i < 5; i++){
v.push_back( MyClass(i, param2) );
}
And all the objects will be destructed when the vector goes out of scope if you're storing the objects directly in the vector.
One of the downsides to storing the objects directly in the vector is passing the vector as a parameter to a function. This will be a slow operation since the vector (and all the objects it holds) will have to be copied.
If you know the number of instances before you read them all in then you can allocate an array on the heap using new[]. (Don't forget to delete[] them when you've finished.) Note that this requires that the object have a default constructor.
you should use std::vector in this case rather than a built-in array.
#include <vector>
...
std::vector<MyClass> v = {first_instance, second_instance, third_instance};
...
v.push_back(fourth_instance);
If you don't know how many elements the array will contain, I would use a std::vector instead of a plain array as the vector will grow to accommodate the additional elements.
What you want is the Vector class from the standard template library, it behaves like an array but it will re-size itself if you fill it's internal allocation. If you do not need random access to it (i.e. use the [] opperator) you may want to use the List class instead. If you use List you will need to create an enumerator to step through it.
use std::vector<MyClass>, vector template can be found in <vector> header. YOu must learn a little bit to code well, before coding use any of online available c++ FAQs