I am facing a problem in initializing an array of struct. Below is the code:
#include <iostream>
#include <array>
#include <string>
#define NUM_ELEMENT 5
struct Person
{
std::string m_name;
int m_age = 0;
Person() = default;
Person(std::string name, int age)
: m_name(name), m_age(age) {}
};
typedef std::array<Person, NUM_ELEMENT> PersonList;
class Detail
{
public:
void InitializePerson();
private:
PersonList personList;
};
void Detail::InitializePerson()
{
personList{ // <------ Getting Error here..
Person("abc", 10),
Person("cde", 20),
Person("pqr", 30),
Person("xyz", 40),
Person("apple", 50),
};
}
int main()
{
Detail detail;
detail.InitializePerson();
return 0;
}
Though, I know I can use the std::vector with push_back but I want to achive this through the static array as it elements are fixed. I want to initialize the array with above class Detail member and since the data can be random, so not able to do in for loop by personList[0] = Person{};
You are trying to initialize personList which can only be done at construction - but personList is already constructed so that doesn't work. You should be assigning instead:
personList = {
Person("abc", 10),
Person("cde", 20),
Person("pqr", 30),
Person("xyz", 40),
Person("apple", 50),
};
alternatively:
personList = {{
{"abc", 10},
{"cde", 20},
{"pqr", 30},
{"xyz", 40},
{"apple", 50},
}};
If you want it initialized, you could do that in a Detail constructor:
class Detail {
public:
Detail() :
personList{{
{"abc", 10},
{"cde", 20},
{"pqr", 30},
{"xyz", 40},
{"apple", 50},
}}
{}
private:
PersonList personList;
};
Seems you are missing = operator
personList = {
Person("abc", 10),
Person("cde", 20),
Person("pqr", 30),
Person("xyz", 40),
Person("apple", 50),
};
This seems to do
personList = {{
{ "abc", 10 },
{ "cde", 20 },
{ "pqr", 30 },
{ "xyz", 40 },
{ "apple", 50 },
}};
See this answer.
Related
I have the following code:
#include <map>
class vehicle {
private:
int id = 0;
std::map<std::pair<int, char>, int> seats{};
public:
void displaySeats();
};
class Bus : public vehicle {
private:
std::string type = "Bus";
public:
std::map<std::pair<int, char>, int> seats{ {{1,'A'},0 }, {{1,'B'},0 }, {{ 1,'C' }, 0}, {{ 1,'D' }, 0 }, {{ 1,'E' }, 0 },
{{2,'A'},0 }, {{2,'B'},0 }, {{ 2,'C' }, 0}, {{ 2,'D' }, 0 }, {{ 2,'E' }, 0 },
{{3,'A'},0 }, {{3,'B'},0 }, {{ 3,'C' }, 0}, {{ 3,'D' }, 0 }, {{ 3,'E' }, 0 },
{{4,'A'},0 }, {{4,'B'},0 }, {{ 4,'C' }, 0}, {{ 4,'D' }, 0 }, {{ 4,'E' }, 0 },
{{5,'A'},0 }, {{5,'B'},0 }, {{ 5,'C' }, 0}, {{ 5,'D' }, 0 }, {{ 5,'E' }, 0 }};
};
class MiniVan : public vehicle {
private:
std::string type = "MiniVan";
public:
// Seats map. <int, char> represents seats id(1A 1B 1C) the <int> will be either 0 or 1, representing if the seat is taken(1) or free(0).
std::map<std::pair<int, char>, int> seats{ {{1,'A'},0 }, {{1,'B'},0 }, {{ 1,'C' }, 0},
{{2,'A'},0 }, {{2,'B'},0 }, {{ 2,'C' }, 0},
{{3,'A'},0 }, {{3,'B'},0 }, {{ 3,'C' }, 0},
{{4,'A'},0 }, {{4,'B'},0 }, {{ 4,'C' }, 0} };
};
void vehicle::displaySeats()
{
std::pair<int, char> seat{ 1, 'E'};
int columns = 5?this->seats.count(seat)>0:3;
int displayRow = 0;
for (const auto& p : this->seats) {
if (displayRow == columns) {
std::cout << std::endl;
displayRow = 0;
}
displayRow++;
std::cout << p.first.first << p.first.second << "\t ";
}
};
In main() i have:
MiniVan testMiniVan;
testMiniVan.displaySeats();
It displays the empty seats map attribute from the base class.
I am new to c++, but in other languages, it takes the derived class attribute. How can I solve this problem? Will I have to create displaySeats for each child class ? If yes, then why do I need base class in the first place?
This is something I've done fairly often as well, the issue is how things are constructed and which functions have access to which variables. Maybe you could do something like:
class Vehicle {
private:
int id = 0;
std::map<std::pair<int, char>, int> seats{};
public:
// Add a constructor that takes in the `seats` map
Vehicle(std::map<std::pair<int, char>, int> s) : seats(std::move(s)) {}
void displaySeats();
};
and then for each child class:
class MiniVan : public Vehicle {
private:
std::string type = "MiniVan";
public:
// call the parent constructor passing in the seat map
MiniVan() : Vehicle({{1,'A'},0 }, ...}) {}
};
Another approach would be to make a virtual function on the base class like:
class Vehicle {
...
protected:
...
const std::map<std::pair<int, char>, int>& get_seats() const = 0;
};
that the displaySeats function would call instead of directly loading this->seats. Each child class would need to define get_seats(), but that would be pretty easy (pretty much just return seats;). Hopefully that makes sense, let me know if not!
I want to get true if list contains that value. Currently this code which I have pasted down there it is returning false. I want the value should be true if value exists.
void main() {
var demo = [
{123, 1},
{234, 1}
];
print(demo.contains(123));
}
If your want to "pass down" a logic to a list of list, your can try the buildin .any() or .every() function.
void main() {
var demo = [
{123, 1},
{234, 1}
];
print(demo.any((item) => item.contains(123)));
// output: true
}
var list = [123,11,202]; // list of int
list.contains(123); // true
var map = {'id':'123','name':'john'};
map.containsValue('123'); // true
var demos = [
{123, 1},
{234, 1}
];
print(demos[0].contains(123)); //true
**//OR**
demos.forEach((demo){
print(demo.contains(123)); // to check all items
});
i hope it helps
I'm new to cpp since a few days and struggling with the following definition:
struct menuItem {
char* name;
int value;
};
struct topMenu {
int menuIcon;
char* Name;
menuItem item[];
};
topMenu menuRoot[] = {
{ 0, "File",
{"Open ...", 1},
{"New ...", 4},
{"Close", 1},
{"Exit", 3}
},
{ 0, "Edit",
{"Cut ", 3},
{"Copy", 8},
{"Paste", 2},
{"Find", 1},
{"Replace", 6}
},
{ 0, "Help",
{"Help", 7},
{"About", 9},
{"Update ..", 9}
}
};
I receive the error
33:1: error: too many initializers for 'menuItem [0]'
33:1: error: too many initializers for 'topMenu'
33:1: error: too many initializers for 'menuItem [0]'
33:1: error: too many initializers for 'topMenu'
33:1: error: too many initializers for 'menuItem [0]'
33:1: error: too many initializers for 'topMenu'
Sorry, i'm a little bit stuck ... maybe its just to late :)
Thanks in advance.
First, wrap the menuItem item[] array in {} because currently it thinks there are many arrays rather than just one.
Next, change the char * to const char * as was mentioned.
Now for the flexible amount of menuItem structs, use a vector rather than an array.
#include <vector>
struct menuItem {
const char *name;
int value;
};
struct topMenu {
int menuIcon;
const char *Name;
std::vector<menuItem> item;
};
topMenu menuRoot[] = {
{ 0, "File", {
{"Open ...", 1},
{"Open ...", 1},
{"Open ...", 1},
{"Open ...", 1},
}
},
{ 0, "Help", {
{"Open ...", 1},
{"Open ...", 1},
{"Open ...", 1}, }
}
};
How to use json-spirit to read json string in C++? I read the demo code.
I find that:
const Address addrs[5] = { { 42, "East Street", "Newtown", "Essex", "England" },
{ 1, "West Street", "Hull", "Yorkshire", "England" },
{ 12, "South Road", "Aberystwyth", "Dyfed", "Wales" },
{ 45, "North Road", "Paignton", "Devon", "England" },
{ 78, "Upper Street", "Ware", "Hertfordshire", "England" } };
Can I convert a String into a json object?
char* jsonStr = "{'name', 'Tom'}";
json_spirit provides bool read_string( const String_type& s, Value_type& value ) and bool read( const std::string& s, Value& value ) to read json data from strings.
Here is an example:
string name;
string jsonStr("{\"name\":\"Tom\"}");
json_spirit::Value val;
auto success = json_spirit::read_string(jsonStr, val);
if (success) {
auto jsonObject = val.get_obj();
for (auto entry : jsonObject) {
if (entry.name_ == "name" && entry.value_.type() == json_spirit::Value_type::str_type) {
name = entry.value_.get_str();
break;
}
}
}
You could also use ifstream instead of string to read from json from file.
Please note, according to RFC4627 a string begins and ends with quotation marks.
I would like to see how this example of existing code would be able to take advantage of the C++0x initializer list feature.
Example0:
#include <vector>
#include <string>
struct Ask {
std::string prompt;
Ask(std::string a_prompt):prompt(a_prompt){}
};
struct AskString : public Ask{
int min;
int max;
AskString(std::string a_prompt, int a_min, int a_max):
Ask(a_prompt), min(a_min), max(a_max){}
};
int main()
{
std::vector<Ask*> ui;
ui.push_back(new AskString("Enter your name: ", 3, 25));
ui.push_back(new AskString("Enter your city: ", 2, 25));
ui.push_back(new Ask("Enter your age: "));
}
Would it support something like this:
Example1:
std::vector<Ask*> ui ={
AskString("Enter your name: ", 3, 25),
AskString("Enter your city: ", 2, 25),
Ask("Enter your age: ")
};
Or must it have literals like this?:
Example2:
std::vector<Ask*> ui ={
{"Enter your name: ", 3, 25},
{"Enter your city: ", 2, 25},
{"Enter your age: "}
};
If so how would the difference between AskString and Ask be handled?
You last examples wouldn't be allowed as you ask for pointers but try to provide local temporary objects instead.
std::vector<Ask*> ui ={
new AskString{"Enter your name: ", 3, 25},
new AskString{"Enter your city: ", 2, 25},
new Ask{"Enter your age: "}
};
That would be allowed and there would be no type ambiguity.
That would be right too :
std::vector<Ask*> ui ={
new AskString("Enter your name: ", 3, 25),
new AskString("Enter your city: ", 2, 25),
new Ask("Enter your age: ")
};
And your example is more like :
std::vector<Ask> ui ={ // not pointers
{"Enter your name: "},
{"Enter your city: "},
{"Enter your age: "}
};
std::vector<AskString> uiString ={ // not pointers
{"Enter your name: ", 3, 25},
{"Enter your city: ", 2, 25},
{"Enter your age: ", 7, 42}
};
and again there would be no ambiguity on the types.
A c++ initializer list is homogenous, meaning it must have all the same type, so example #2 is out. If you used new in example 1, it would work.