Vectors in structs - c++

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

Related

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.

Use the index in naming variables during a cycle 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;

Adding element to Array of Objects in C++

How do I add an element to the end of an array dynamically in C++?
I'm accustomed to using vectors to dynamically add an element. However, vectors does not seem to want to handle an array of objects.
So, my main goal is having an array of objects and then being able to add an element to the end of the array to take another object.
EDIT**
Sorry, its the pushback() that causes me the problems.
class classex
{
private:
int i;
public:
classex() { }
void exmethod()
{
cin >> i;
}
};
void main()
{
vector <classex> vectorarray;
cout << vectorarray.size();
cout << vectorarray.push_back();
}
Now I know push_back must have an argument, but What argument?
Now I know push_back must have an argument, but What argument?
The argument is the thing that you want to append to the vector. What could be simpler or more expected?
BTW, you really, really, really do not want exmethod as an actual method of classex in 99% of cases. That's not how classes work. Gathering the information to create an instance is not part of the class's job. The class just creates the instance from that information.
Arrays are fixed sized containers. So enlarging them is not possible. You work around this and copy one array in a bigger and gain space behind the old end, but that's it.
You can create a array larger than you currently need it and remember which elements are empty. Of course they are never empty (they at least contain 0's), but that's a different story.
Like arrays, there are many containers, some are able to grow, like the stl containers: lists, vectors, deques, sets and so on.
add a Constructor to set i (just to give your example a real world touch) to your example classex, like this:
class classex {
public:
classex(int& v) : i(v) {}
private:
int i;
};
An example for a growing container looks like this:
vector <classex> c; // c for container
// c is empty now. c.size() == 0
c.push_back(classex(1));
c.push_back(classex(2));
c.push_back(classex(3));
// c.size() == 3
EDIT: The question was how to add an element to an array dynamically allocated, but the OP actually mean std::vector. Below the separator is my original answer.
std::vector<int> v;
v.push_back( 5 ); // 5 is added to the back of v.
You could always use C's realloc and free. EDIT: (Assuming your objects are PODs.)
When compared to the requirement of manually allocating, copying, and reallocating using new and delete, it's a wonder Stroustrup didn't add a keyword like renew.

What does a C++ vector relate to in Objective-C?

I'm moving from Objective-C to C++ and am not sure what vectors are. I've read documentation about them, I'm not quite clear though. How would you explain C++ vectors using Objective-C analogies?
They're pretty similar to NSMutableArrays but vector is a template class and so can be instanciated for any (standard-template-library compatible) type. NSArrays always hold NSObjects.
That is, assuming you mean std::vector.
They're like NSMutableArrays but can hold any data type - pointer or not. However, each vector can only ever hold one type at a time. Also as it's C++ there are fewer functions e.g. no plist loading/saving.
A C++ vector (presumably you mean something like std::vector) is basically an NSArray, except it holds any type you want (which is the template parameter, e.g. a std::vector<int> holds ints). Of course, it doesn't do memory management (which NSArray does), because arbitrary types aren't retain-counted. So for example a std::vector<id> would be rather inappropriate (assuming Obj-C++).
NSArray is a wrapper around CFArray. CFArray can store any data type.
I don't know much about C++, but it sounds like CFArray can do everything you'd use a vector for? When creating a CFArray you give it a CFArrayCallBacks pointer, which contains any logic that is specific to the data type being stored.
Of course, you could always just rename your Obj-C file to *.mm, and mix C++ into your objective-c.
http://developer.apple.com/library/mac/#documentation/CoreFOundation/Reference/CFArrayRef/Reference/reference.html
In C++ an Array is basically just a pointer to a contiguous block of data---a series of elements. It offers no built-in methods, or higher functionality.
int intArr[] = {0,1,2,3};
is the same as
int *intArr = (int *)malloc(4*sizeof(int));
for(int i = 0; i < 4; i++) { intArr[i] = i; }
A vector (std::vector), on the other hand, is a container for elements (basically like an array) which also offers additional built in methods (see: http://www.cplusplus.com/reference/stl/vector/) such as
vector<int> intArr;
for(int i = 0; i < 4; i++) { intArr.push_back(i); }
// this yields the same content; i.e. intArr = {0,1,2,3}
Both arrays and vectors can be used on any type of objects, int, double, 'MySpacePirateWizardClass' etc. The big bonus of vectors is the additional functionality from built-in functions like:
int arrSize = intArr.size(); // vector also includes useful information
int *firstElement = intArr.begin(); // methods for creating pointers to elements
intArr.delete(0); // modify elements
intArr.insert(0, 2); // modify vector
// now: intArr = {2,1,2,3}
etc etc.
When I know I'm not going to be short on space (or looking at massive amounts of data), I always use vectors because they're so more convenient (even just the size() method alone is reason enough).
Think about vectors as advanced arrays.
If you are new to C++, this page will be your best friend:
http://www.cplusplus.com/reference/stl/vector/

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