Vector of structs initialization - c++

I want know how I can add values to my vector of structs using the push_back method
struct subject
{
string name;
int marks;
int credits;
};
vector<subject> sub;
So now how can I add elements to it?
I have function that initializes string name(subject name to it)
void setName(string s1, string s2, ...... string s6)
{
// how can i set name too sub[0].name= "english", sub[1].name = "math" etc
sub[0].name = s1 // gives segmentation fault; so how do I use push_back method?
sub.name.push_back(s1);
sub.name.push_back(s2);
sub.name.push_back(s3);
sub.name.push_back(s4);
sub.name.push_back(s6);
}
Function call
setName("english", "math", "physics" ... "economics");

Create vector, push_back element, then modify it as so:
struct subject {
string name;
int marks;
int credits;
};
int main() {
vector<subject> sub;
//Push back new subject created with default constructor.
sub.push_back(subject());
//Vector now has 1 element # index 0, so modify it.
sub[0].name = "english";
//Add a new element if you want another:
sub.push_back(subject());
//Modify its name and marks.
sub[1].name = "math";
sub[1].marks = 90;
}
You cant access a vector with [#] until an element exists in the vector at that index. This example populates the [#] and then modifies it afterward.

If you want to use the new current standard, you can do so:
sub.emplace_back ("Math", 70, 0); // requires a fitting constructor, though
or
sub.push_back ({"Math", 70, 0}); // works without constructor
.

You may also which to use aggregate initialization from a braced initialization list for situations like these.
#include <vector>
using namespace std;
struct subject {
string name;
int marks;
int credits;
};
int main() {
vector<subject> sub {
{"english", 10, 0},
{"math" , 20, 5}
};
}
Sometimes however, the members of a struct may not be so simple, so you must give the compiler a hand in deducing its types.
So extending on the above.
#include <vector>
using namespace std;
struct assessment {
int points;
int total;
float percentage;
};
struct subject {
string name;
int marks;
int credits;
vector<assessment> assessments;
};
int main() {
vector<subject> sub {
{"english", 10, 0, {
assessment{1,3,0.33f},
assessment{2,3,0.66f},
assessment{3,3,1.00f}
}},
{"math" , 20, 5, {
assessment{2,4,0.50f}
}}
};
}
Without the assessment in the braced initializer the compiler will fail when attempting to deduce the type.
The above has been compiled and tested with gcc in c++17. It should however work from c++11 and onward. In c++20 we may see the designator syntax, my hope is that it will allow for for the following
{"english", 10, 0, .assessments{
{1,3,0.33f},
{2,3,0.66f},
{3,3,1.00f}
}},
source: http://en.cppreference.com/w/cpp/language/aggregate_initialization

You cannot access elements of an empty vector by subscript.
Always check that the vector is not empty & the index is valid while using the [] operator on std::vector.
[] does not add elements if none exists, but it causes an Undefined Behavior if the index is invalid.
You should create a temporary object of your structure, fill it up and then add it to the vector, using vector::push_back()
subject subObj;
subObj.name = s1;
sub.push_back(subObj);

After looking on the accepted answer I realized that if know size of required vector then we have to use a loop to initialize every element
But I found new to do this using default_structure_element like following...
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
typedef struct subject {
string name;
int marks;
int credits;
}subject;
int main(){
subject default_subject;
default_subject.name="NONE";
default_subject.marks = 0;
default_subject.credits = 0;
vector <subject> sub(10,default_subject); // default_subject to initialize
//to check is it initialised
for(ll i=0;i<sub.size();i++) {
cout << sub[i].name << " " << sub[i].marks << " " << sub[i].credits << endl;
}
}
Then I think its good to way to initialize a vector of the struct, isn't it?

Related

c++, printing attribute value of an object inside a list, finding object of specific value of attribute, removing the object

I'm struggling with coding a-star search algorithm, I have to make it in c++, despite I'm not really familiar with it. I've decided to use classes and lists, but I have one problem. My code looks like this:
class gridPoint
{
public:
int x;
int y;
int field;
}
gridPoint mapa[20][20];
startX=1;
startY=1;
//code to set the values of attributes
int main(){
mapa[startX,startY] = 1;
list<gridPoint> listZ;
listZ.push_back(*mapa[startX,startY]);
}
To this point it seems to work, compiles and executes with no errors.
Now I need to get somehow to this element of list, but I have really no clue how to do that. I've tried simply:
list<gridPoint>::iterator it = listZ.begin();
cout<<listZ[it].x;
or:
cout<<*it.x;
but it doesn't work, either with ".x" or without
Later I would need to find specific object in a list with specific value of attribute and/or delete it, but without this mentioned above, I couldn't do it anyway. Any clues, how to make it work?
your code corrected, with explications/remarks
#include <iostream>
#include <list>
using namespace std;
class gridPoint
{
public:
int x;
int y;
int field;
}; // the ';' was missing
gridPoint mapa[20][20]; // why global ?
int startX=1; // why global ?, in case : the first index is 0 rather than 1 if you do not know that
int startY=1; // why global ?, in case : the first index is 0 rather than 1 if you do not know that
//code to set the values of attributes
int main() {
mapa[startX][startY] = { 1, 2, 3 }; // each index in its [], mapa[][] is not an int
list<gridPoint> listZ;
listZ.push_back(mapa[startX][startY]); // '*' removed, mapa[][] is a gridPoint, not a pointer to
list<gridPoint>::iterator it = listZ.begin(); // can be a const_iterator because let the list unchanged
cout << it->x << endl; // it->attr it->oper() etc, not it.attr etc
}

How to call constructor when overwriting array elements

I wanted to create an array where each element can be either set from an int or float (these particular types are just an example).
So I went ahead and made a class with two constructors:
class ScaledNumber {
private:
int scaled_number;
public:
ScaledNumber(int number);
ScaledNumber(float number);
};
ScaledNumber::ScaledNumber(int number) {
scaled_number = number * 1000;
}
ScaledNumber::ScaledNumber(float number) {
scaled_number = (int)(number * 1000);
}
This works fine when I work with a single variable of this class. But now I want to create an array of such objects. I had to add a third constructor to even get the declaration working:
ScaledNumber::ScaledNumber() {}
ScaledNumber numbers[5];
Now if I want to re-assign for example numbers[3], can I somehow make use of the constructor or do I have to add a set() method or something like that?
can I somehow make use of the constructor
You can simply use:
ScaledNumber numbers[5];
numbers[0] = 20;
numbers[1] = 30.2f;
The compiler will use the appropriate constructor before making the assignment. The last two lines are translated by the compiler to:
numbers[0] = ScaledNumber(20);
numbers[1] = ScaledNumber(30.2f);
What's the point of ScaledNumber numbers[5]; anyway? You previously didn't need ScaledNumber number; for a single object to work, presumably because it didn't make sense to create such a half-ready object, so why would you need it for five objects?
You can just initialise the objects in the array like this:
#include <iostream>
class ScaledNumber {
private:
int scaled_number;
public:
ScaledNumber(int number);
ScaledNumber(double number);
};
ScaledNumber::ScaledNumber(int number) : scaled_number(number * 1000) {
std::cout << "int\n";
}
ScaledNumber::ScaledNumber(double number) : scaled_number(static_cast<int>(number * 1000)) {
std::cout << "double\n";
}
int main() {
ScaledNumber numbers[] = { 1, 2.2, 3, 4.4, 5 };
}
Output:
int
double
int
double
int
Note that I also made four improvements: I replaced float with double (the default floating-point type of the language), turned the C-style cast into static_cast, I added initialisation lists to the constructors and I made the compiler count the elements in the array.

How can I check if a vector with a custom class is NULL?

I have made this custom class
#ifndef VEHICLE_H_
#define VEHICLE_H_
Class Vehicle {
public:
Vehicle();
Vehicle(char,char,int,int);
virtual ~Vehicle();
char getLicense_plate();
void setLicense_plate(char);
char getBrand();
void setBrand(char);
int getTime_in();
void setTime_in(int);
int getTime_out();
void setTime_out(int);
char license_plate;
char brand;
int timei;
int timeo;
};
And I have created a Vehicle vector with size 50 in the main.cpp but I don't how to check each value if they are empty.
#inlcude<iostream>
#include<vector>
#include<algorithm>
#inlude "Vehicle.h"
using namespace std;
int main()
{
vector<Vehicle> avai_space(50);
for(int i=0;i<avai_space.size();i++)
{
//if(avai_space(i) == NULL??){}
vector<Vehicle> avai_space(50); does not create an empty vector with a storage capacity of 50; it creates a vector with 50 valid entries where each entry gets initialized using the default constructor of Vehicle class.
To create an empty vector with max storage of 50, use:
vector<Vehicle> vehicle_vec;
vehicle_vec.reserve(50);
You can use vehicle_vec.push_back() to add items into the vector without affecting the storage.
Once the vector is populated with entries, you can now use vehicle_vec.size() to iterate through the valid entries in this vector:
for (size_t i = 0 ; i < vehicle_vec.size() ; i++) {
// Use vehicle_vec[i], for e.g.
std::cout << vehicle_vec[i].brand << "\n";
}
vector<Vehicle> avai_space(50); creates 50 Vehicles. They exist after this line and are not empty, but what ever Vehicle's default constructor makes them.
If you want to store Vehicles in your vector, but not create them yet (I assume that's what you mean with == NULL), just write vector<Vehicle> avai_space; and then add new Vehicless to the end with std::vector::push_back.
None of the elements will ever be 'empty', as in a null pointer, because they're stored by value, not by pointer.
That scenario would correspond to a declaration like
std::vector<Vehicle*>
or, if the pointers need to own the objects
std::vector<std::unique_ptr<Vehicle>>

structure array won't initialize

I'm trying to initialize the members of candy like this.
#include <iostream>
#include <string>
struct CandyBar
{
std::string Brand;
float weight;
int cal;
};
int main()
{
CandyBar candy[3];
candy[0] = {"toe foe", 30.2f, 500};
candy[1] = {"lays", 2.1f, 10};
candy[2] = {"fin", 40.5f, 1000};
return 0;
}
But it gives me a syntax error near the opening brace
i know this is wrong but is there a way like this to initialize a array of struct.
And can someone explain why is the above code wrong.
You're not initializing the array, you're making assignments to its elements. If you do use an initializer, it will work fine:
CandyBar candy[3] = {
{"toe foe", 30.2f, 500},
{"lays", 2.1f, 10},
{"fin", 40.5f, 1000}
};
CandyBar candy[3] = {
{"toe foe", 30.2f, 500},
{"lays", 2.1f, 10},
{"fin", 40.5f, 1000}};
You can do this.
This style can only be used in the initialization stage, i.e when you create the variable. It cannot be used to assign the value later. (pre C++11)

Class C++ trace this value!

#include <iostream>
using namespace std;
class t
{ public:
int health; //its members
int speed;
int power;
void attack() // its methods
{ cout<<"I'm attacking"<<endl;
};
};
int main()
{ t A,B,C,D;
A.power = 100;
B.health = 87;
C.speed = 92;
cout<<"A= "<<A.power<<"B= "<<A.health<<"C= "<<A.speed<<endl; // <---
cout<< "My health is "<<C.health<<" My speed is "<<A.speed<<endl;
cout<<"My power is "<<B.power<<endl;
D.attack();
system("pause");
return 0;}
The output result was ::
A= 100 B= 96 C=6234392 <--- From where these values come
A.health and A.speed are just junk values on the stack because you didn't explicitly set them. If you want to initialize all fields of A to zero, you can use memset:
memset(&A, 0, sizeof(A));
You should create a constructor to initialize those values to some default value in the initializer list.
class t {
public:
t() : health(100),power(100),speed(100) {}
// ...
};
This will guarantee that those values are all set to 100, or some default, or even an input parameter, rather than garbage. It's considered much better design since otherwise the initialization of those values would be handled in the constructor that the compiler generates for you behind the scenes.
Uninitialized memory?
Uninitialized variable won't be zero setted at the creation of the class/struct. You need to manualy do it. Otherwise, you will get whatever_is_in_memory_at_that_time.