c++ right way to initialize a vector of a struct - c++

i searched a lot here, but there is no right explanation for me, for an advanced newbie in c++. I worked before with vector of structs and now I get segmentation faults...
Thats why I want to know how such objects actually works and if it is the right the way I am doing!
I have a struct like
struct numberOfSpecies {
int predator;
int prey1;
int prey2;
};
and a vector of it:
std::vector<numberOfSpecies> size;
Before I resize it and fill it with values.
size.resize(100);
what is actually this doing? Is this right for a struct?
It looks like it is initialized with zeros...
Now I am doing this like:
size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;
for(int k = 0; k < N; ++k){
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
Is this right? Where are possible issues? How to do it better?

The easiest and 'correct' solution here is probably to just use the resize() function that belongs to the vector object with aggregate initialization (if you have access to c++11 and on), something like
size.resize(100,{0,0,0}); //aggregate initialization
for(int k = 0; k < N; ++k)
{
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
All members of each numberOfSpecies object will be initialized to 0.

This:
size[t].predator=0;
size[t].prey1=0;
size[t].prey2=0;
will write zeros to the tth element of size - that may or may not be useful:
This:
for(int k = 0; k < N; ++k){
size[t].predator++;
size[t].prey1++;
size[t].prey2++;
}
will increment the tth element of size N times. This seems incredibly unlikely to be useful. I think what you want is:
size[0].predator=0; // Technically not needed because .resize()
size[0].prey1=0; // will have initialized it to zero anyway
size[0].prey2=0; // *BUT* explicit is always better than implicit.
// Initialize each element of size to be one greater than previous.
for(int k = 1; k < N; ++k){
size[k].predator = size[k-1].predator + 1;
size[k].prey1 = size[k-1].prey1 + 1;
size[k].prey2 = size[k-1].prey2 + 1;;
}

Use the value parameter for static parameters.
#include <vector>
struct foo{
int g;
int h;
int l;
};
int main()
{
std::vector<foo> manyFoo(10, {0});
manyFoo.resize(60, {0});
}
If you want to grow your vector as you also put arbitrary values into the struct you could ->
#include <iostream>
#include <vector>
struct foo{
foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
int g;
int h;
int l;
};
int main() {
std::vector<foo> lVec;
for (int i=0;i<10;i++) {
lVec.emplace_back(foo(i,i*2,i*4));
}
int lPos=0;
for (auto &rFoo: lVec) {
std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
}
return EXIT_SUCCESS;
}
If you know the size of the vector and you want to populate it you could ->
#include <iostream>
#include <vector>
struct foo{
foo(int aG,int aH, int aL):g(aG),h(aH),l(aL) {};
int g;
int h;
int l;
};
int main() {
std::vector<foo> lVec(10,{0,0,0});
int lPos = 0;
for (auto &rFoo: lVec) {
rFoo = foo(lPos,lPos*2,lPos*4);
lPos++;
}
lPos=0;
for (auto &rFoo: lVec) {
std::cout << "Item pos" << lPos++ << " g:" << rFoo.g << " h:" << rFoo.h << " l:" << rFoo.l << std::endl;
}
return EXIT_SUCCESS;
}

You could add an default constructor to your structure. The new code will look something like this:
struct numberOfSpecies {
numberOfSpecies (): predator(0), prey1(0), prey2(0) { } // default constructor
int predator;
int prey1;
int prey2;
};
That way, your structure will be properly initialized inside your vector when resize is applied.

Related

Can we pass an array to any function in C++?

I have passed an array of size 10 to a funtion to sort the array reversely, but it's going wrong after rightly sorting first five elements of the array.
I want to sort the array 'std' reversely here,
# include <iostream>
using namespace std;
int reverse(int a[]); //funtion prototype
int main()
{
int std[10] = {0,1,2,3,4,5,6,7,8,9};
reverse(std);
}
int reverse(int a[]) //funtion defination
{
int index = 0;
for (int i = 9; i >= 0; i--)
{
a[index] = a[i]; //swaping values of the array
cout << a[index] << " ";
index++;
}
}
There's basically three things wrong with your code.
You aren't swapping anything
You have to swap the first half of the array with the second half, not swap the whole array. If you do that then everything gets swapped twice, so that nothing changes
You should print the reversed array after you have finished the reverse, not while you are doing the reverse.
Here's some code that fixes all these problems
# include <iostream>
# include <utility>
void reverse(int a[]);
int main()
{
int std[10] = {0,1,2,3,4,5,6,7,8,9};
reverse(std);
// print the array after reversing it
for (int i = 0; i < 10; ++i)
std::cout << std[i] << ' ';
std::cout << '\n';
}
void reverse(int a[])
{
for (int i = 0; i < 5; ++i) // swap the first half of the array with the second half
{
std::swap(a[i], a[9 - i]); // real swap
}
}
Yes you can.
I usually don't use "C" style arrays anymore (they can still be useful, but the don't behave like objects). When passing "C" style arrays to functions you kind of always have to manuall pass the size of the array as well (or make assumptions). Those can lead to bugs. (not to mention pointer decay)
Here is an example :
#include <array>
#include <iostream>
// using namespace std; NO unlearn trhis
template<std::size_t N>
void reverse(std::array<int, N>& values)
{
int index = 0;
// you only should run until the middle of the array (size/2)
// or you start swapping back values.
for (int i = values.size() / 2; i >= 0; i--, index++)
{
// for swapping objects/values C++ has std::swap
// using functions like this shows WHAT you are doing by giving it a name
std::swap(values[index], values[i]);
}
}
int main()
{
std::array<int,10> values{ 0,1,2,3,4,5,6,7,8,9 };
reverse(values);
for (const int value : values)
{
std::cout << value << " ";
}
return 0;
}

How to sort an array of structures according to the value of an included pointer

my aim is to sort an array of structures. The structure contains the index of a customer {1,..., number} and a pointer to a value of an other sturcture,
e.g,
for (int i = 1; i < no_orders+1; i++){
sorting_array[i].index_order = i;
sorting_array[i].some_vaule = &order_data[i].some_value;
}
Here, order_data is an array of structures contains all customer data which allows for directly accessing variable data a customer the index. The array sorting_array is the one to sort according to a value in order_data; therefore the pointer in DATA_TO_SORT in order to avoid copying effort since this function is called millions of times (same indices, changed values).
The actual problem appears with the sorting function. If I do not use the pointer but the real value (int some_value, including copying effort however), sorting works as it should.
Defining some_value as pointer, std::sort terminates after some seconds without any feedback the whole program. The actual question is why and what may I change.
struct DATA_TO_SORT {
int index_order;
int *some_value;
};
bool compare_by_val( DATA_TO_SORT &a, DATA_TO_SORT &b) {
return *a.some_value > *b.some_value;
}
void sort_acc_release() {
std::sort(sorting_array.begin() + 1, sorting_array.end(), compare_by_val);
}
Also tried the following from a related topic, however, the depicted error statement occurs - besides several similar error statements.
std::sort(sorting_array.begin() + 1, sorting_array.end(), [&](size_t a, size_t b) {return *sorting_array[a].some_value > *sorting_array[b].some_value; });
<lambda_0a6c4bdbc69eba5706031ee8a4b875c6>::operator ()(::size_t,::size_t) const" : Konvertierung von Argument 1 von "DATA_TO_SORT" in "::size_t" nicht möglich Algorithm ...\microsoft visual studio\2017\community\vc\tools\msvc\14.12.25827\include\xutility 1017
Minimum Example which WORKS.
#include <iostream>
#include <cstdlib> //rand
#include <algorithm> //swap etc
#include <array> //array
struct OTHER_DATA {
int other_data;
};
struct DATA_TO_SORT {
int index_order;
int *some_value;
};
bool compare_by_val(DATA_TO_SORT &a, DATA_TO_SORT &b) {
return *a.some_value > *b.some_value;
}
int main() {
const int max_no = 10;
std::array<OTHER_DATA, max_no> some_other_values;
std::array<DATA_TO_SORT, 10> sorting_array;
for (int i = 0; i < some_other_values.size(); i++)
{
some_other_values[i].other_data = i * 5;
sorting_array[i].index_order = i;
sorting_array[i].some_value = &some_other_values[i].other_data;
}
for (int i = 0; i < sorting_array.size(); i++)
{
std::cout << "\n" << sorting_array[i].index_order << "\t" << *sorting_array[i].some_value;
}
std::sort(sorting_array.begin(), sorting_array.end(), compare_by_val);
for (int i = 0; i < sorting_array.size(); i++)
{
std::cout << "\n" << sorting_array[i].index_order << "\t" << *sorting_array[i].some_value;
}
system("pause");
return 0;
}
Thank you in advance for your problem-related and well-intentioned answers!

Vector of tuple structs

I'm getting an error on the following code snippet;
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <iostream>
using namespace std;
struct tuple {
int x;
int y;
};
int main() {
//srand(time(NULL));
vector<tuple> locations;
int dimentions = 20;
double filledness = 0.65;
while (locations.size() < dimentions * dimentions * filledness) {
tuple point;
point.x = rand() % dimentions;
point.y = rand() % dimentions;
locations.push_back(point);
}
int count = locations.size();
tuple start, end;
start = locations[rand() % count];
end = locations[rand() % count];
cout << count << endl;
for (int i = 0; i < locations.size(); i++) {
cout << locations[i].x << " " << locations[i].y << endl;
}
cout << start.x << start.y << endl;
cout << end.x << end.y;
return 0;
}
The vector initialization is in my main and the struct outline just above. I obviously don't understand something about vectors. I've tried making the struct a class as well as replacing vector of tuples with a vector of tuple*.
Can someone please explain why a vector can't be used in this way,
I would prefer if you didn't tell me how to fix the error directly.
error: template argument 1 is invalid
vector<tuple> locations;
The reason for your error is this struct:
struct tuple {
int x;
int y;
};
1) You called your type tuple, when there is a std::tuple that exists in the standard library and
2) You used using namespace std;, thus any mention of tuple in your code potentially clashes with std::tuple.
If you rename your struct to my_tuple or similar, the error that you are getting now should be remediated.

Take item position in vector with structure

Let see code:
struct tmp {
int a;
std::vector <second_struct> b;
}
struct second_struct {
int x;
int y;
}
//main.cpp
int main {
std::vector<tmp> test;
(...); //push data to test
}
So when i push data to test, in second function i want to get vector "b" from this vector 'test'. And find vector b by a;
(i.e I have int a and std::vector<tmp> test; , dont have std::vector <second_struct> b;(from vector test) and want to get it. (vector test is a big array, so i need to do it fastest and using little power )
How to do that? (i suppose std::map will be better? But if you tell me yes, tell me too how to do that in std::Vector)
Loop through test vector checking if tmp::a member is equal to your int a. If so, you have your vector<second_struct> b
for (int i=0;i<test.size();i++) {
if (test[i].a == a) {
// do whatever you need to do with test[i].b
break;
}
}
P.S. map would be easier, just
std::map<int, std::vector<second_struct>> map;
//insert data
std::vector<second_struct> b = map[a]; //assuming it's a that you're looking for
The most straightforward approach is to use map (or unordered_map in C++11). Hope this full example helps:
#include <map>
#include <vector>
#include <iostream>
struct str {
str(int _x, int _y) : x(_x), y(_y) {}
int x, y;
};
std::map<int, std::vector<str> > test;
int main() {
std::vector<str> vec;
for (int i = 0; i < 100; ++i) {
vec.clear();
vec.push_back(str(i, 2 * i));
vec.push_back(str(i + 1, i + 2));
test[i] = vec;
}
std::vector<str> result;
// get some element
result = test[10];
std::cout << "Found at position 10:\n";
for (int i = 0; i < result.size(); ++i)
std::cout << result[i].x << ' ' << result[i].y << '\n';
return 0;
}

C++ - Using 'i' to check different variables in a for loop

I'm not sure what to call this, so I'm also not sure what to search for, but is there a way to use 'i' as part of a variable name within a for loop? Using C++ by the way.
For example,
int int1, int2, int3;
for(int i = 1; i<=3; i++){
//somehow use i as inti or int+i, etc.
//I was wondering if this is possible?
}
I appreciate any input.
Thanks.
use an array
int ints [3];
for(int i = 0; i<3; i++){
int x = ints[i];
}
Department for insane solutions:
int int1, int2, int3;
int *arr[3] = { &int1, &int2, &int3 };
for(int i = 1; i<=3; i++){
... *arr[i] ...
}
would also work, but not as easy as using an array, of course.
If you are using C++ you should pick up one of the containers from the C++ standard library, as [std::array]1 or [std::vector]2.
Example:
#include <array>
#include <iostream>
int main() {
std::array<int, 3> const ia = {{ 2, 4, 8 }};
for( int i : ia ) {
std::cout << "[" << i << "] ";
}
std::cout << std::endl;
return 0;
}