I have a list of objects derived from a class named "Campus" which contains two strings, one int and two lists : one for "Students", the other is for "Teachers", before closing the program, I want to save the campus objects and of course the "Student" and "Teachers" objects contained on their lists, I want to serialize those data in an XML or JSON format or even anything else then store the result in a file.
Can somebody give me the fastest way to do the serialization with a library (that is not heavy as boost) in XML or JSON or another solution. When it comes to deal with JSON or XML serialization, I don't know what to do !
EDIT: is this feasible with RapidJSON ?
class Campus
{
private:
std::string city;
std::string region;
int capacity;
std::list<Student> students;
std::list<Teacher> teachers;
}
class Student
{
private:
int ID;
std::string name;
std::string surname;
}
class Teacher
{
protected:
int ID;
std::string name;
std::string surname;
};
You can use this C++ serialization library : Pakal persist
#include "XmlWriter.h"
class Campus
{
private:
std::string city;
std::string region;
int capacity;
std::list<Student> students;
std::list<Teacher> teachers;
public:
void persist(Archive* archive)
{
archive->value("city",city);
archive->value("region",region);
archive->value("capacity",capacity);
archive->value("Students","Student",students);
archive->value("Teachers","Teacher",teachers);
}
}
class Student
{
private:
int ID;
std::string name;
std::string surname;
public:
void persist(Archive* archive)
{
archive->value("ID",ID);
archive->value("surname",surname);
archive->value("name",name);
}
}
class Teacher
{
protected:
int ID;
std::string name;
std::string surname;
public:
void persist(Archive* archive)
{
archive->value("ID",ID);
archive->value("surname",surname);
archive->value("name",name);
}
};
Campus c;
XmlWriter writer;
writer.write("campus.xml","Campus",c);
Unfortunately C++ doesn't support reflection, so it can't automagically figure out the parameter names.. but check out this answer which looks like it'll be close to what you want: https://stackoverflow.com/a/19974486/1715829
Related
New to classes and objects in c++ and trying to learn a few basics
I have the class TStudent in which the Name, Surname and Age of student are stored, also I have the constructor which is accessed in main and inserts in the data.
What I want to do is: having the class TRegistru, I have to add my objects data in it, in a way that I can store it there, then I could save the data in data.bin and free the memory from the data, then I want to put the data back in the class and print it out.
The question is: In what way & what is the best way to add my objects in the second class, so that I could eventually work with them in the way I've described in the comments, so that I won't have to change nothing in main
Here's my code so far:
#include <iostream>
using namespace std;
class TStudent
{
public:
string Name, Surname;
int Age;
TStudent(string name, string surname, int age)
{
Name = name;
Surname = surname;
Age = age;
cout <<"\n";
}
};
class TRegistru : public TStudent
{
public:
Tregistru()
};
int main()
{
TStudent student1("Simion", "Neculae", 21);
TStudent student2("Elena", "Oprea", 21);
TRegistru registru(student1);//initialising the object
registru.add(student2);//adding another one to `registru`
registru.saving("data.bin")//saving the data in a file
registru.deletion();//freeing the TRegistru memory
registru.insertion("data.bin");//inserting the data back it
registru.introduction();//printing it
return 0;
}
Hence the question is about passing data from A to B, I will not comment on the file handling portion.
This can be done in multiple ways, but here is one of the simplest and most generic. By calling TRegistru::toString() you serialize every TStudent added to TRegistru into a single string which then can be easily written to a file.
Demo
class TStudent
{
public:
std::string Name, Surname;
int Age;
std::string toString() const
{
return Name + ";" + Surname + ";" + to_string(Age);
}
};
class TRegistru
{
public:
void add(const TStudent& student)
{
students.push_back(student);
}
void deletion()
{
students.clear();
}
std::string toString() const
{
std::string ret{};
for(const auto& student : students)
{
ret += student.toString() + "\n";
}
return ret;
}
std::vector<TStudent> students;
};
I need help in the class design workflow with the following functionality.
I have a class with the name of Stage the stage has a variable of class Director as vector and i would want to point to these data elements of the vector from another class Channel.
class Stage
{
private:
int time;
std::vector<Director> directors;
public:
Stage()
{ }
void AddDirector(Director director)
{
directors.push_back(director);
}
Director* GetDirector(int index)
{
return &directors[index];
}
void DeleteDirector(std::string dirName)
{
// remove the director from the vector which matches the name of the input string
}
};
////////////////////////////////////////////////////////////////////////////////////////////////
class Director
{
private:
int time;
std::string stdstrDirName;
public:
Director()
{ }
std::string GetName()
{
return stdstrDirName;
}
void SetName(std::string name)
{
stdstrDirName = name;
}
// GetTime and SetTime
};
class Channel
{
private:
int time;
std::string stdstrChannelName;
Director* dir;
public:
Channel()
{ }
std::string GetName()
{
return stdstrChannelName;
}
void SetName(std::string name)
{
stdstrChannelName = name;
}
std::string GetDirectorName()
{
dir->GetName();
}
void SetDirector(Director* director)
{
dir = director;
}
};
This is how i would point them.
int main()
{
Stage stage; // Create Stage Object
Director d1, d2, d3; // Create Director Objects
Channel channel;
d1.SetName("D1"); d2.SetName("D2"); d3.SetName("D3");
stage.AddDirector(d1); stage.AddDirector(d2); stage.AddDirector(d3);
channel.SetDirector(stage.GetDirector(1)); // Link Director to Channel
}
This approach has a drawback whenever the vector gets resize the pointers in the Channel will not hold reference to their valid object.
I need help in what should be the design of the class structure ?
Perhaps your vector could store pointers to the Director objects rather than the objects themselves. That way, resizes will not affect existing pointers.
Have you thought of using reference(&) instead of pointers?
I have publication and library two classes and in publication class. How to manipulate(as encapsulation) genre, media, and target_age, If I want them to be separate classes. It's not class inside another class.
The genre have more type's as (fiction, non-fiction, self-help, performance) as well as media and age. I have done my research I'm serchin for the proper syntax for it.
class Publication {
private:
string title;
string authore;
string copyright;
Genre genre;
Media media;
Age target_age;
string isbn;
bool checked_out;
string patron_name;
string patron_phone;
public:
void check_out(string patron_name, string patron_phone ){}
void check_in(){}
bool is_checked_out(){}
string to_string(){}
};
The best way to encapsulate is to keep everything private. Create constant getters for stuff that might be read from the outside, and initialize everything in the constructor. After all, things like author/title/etc. should not ever change for an instance of a real book right? Have a look at the following snippet:
class Publication {
private:
string _title;
string _author;
Genre _genre;
public:
void check_out(string patron_name, string patron_phone );
void check_in();
bool is_checked_out() const;
string to_string() const;
string get_title() const { return _title; }
string get_author() const { return _author; }
const Genre& get_genre() const { return _genre; }
Publication(string author, string title, Genre genre) : _author(auth), _title(title), _genre(genre)
{ }
};
vector<string> hj{ "jack" };
vector<double> x{ 8 };
NamePairs pair1(hj,x);
This is the only way the code runs. Is there a way to pass the values directly to pair1 object instance
You are passing the wrong types to your constructor:
"Jack" is of type const char[5] and the second argument 28.2 is of type double
Your constructor though is expecting a std::vector<string> and a std::vector<double>. So the problem is your constructor is expecting a "list" of strings and doubles, what you are not giving him.
Considering the name of your class the correct solution should be:
class NamePairs
{
private:
double age;
std::string name;
public:
NamePairs(const std::string& name, double Age)
{
this->name = name;
this->age = age;
}
};
Now you can instantiate it like that:
NamePairs pair("Alfred", 43.4);
Also consider using a std::pair
Considering you want a list of Persons that each have a Name and Age there a some different Solutions:
You could create a class Person that has two attributes:
class Person
{
private:
double Age;
std::string Name;
public:
Person(double age, const std::string& name)
{
Age = age;
Name = name;
}
};
And use it like that:
std::vector<Person> persons;
persons.push_back(Person(23.4, "Alfons");
Or you also could (more like your try) create a class PersonList like this:
class PersonList
{
private:
std::vector<double> Ages;
std::vector<std::string> names;
public:
void addPerson(double Age, const std::string& Name)
{
Ages.push_back(Age);
Names.push_back(Names);
}
};
And use it like that:
PersonList list;
list.addPerson(23.5, "Andrea");
I would greatly prefer the first Approach because it is way easier to handle the Persons if they're are not in the list(e.g. returned by a accessor or passed around to other functions/objects or if you Need to operate upon them). And it Looks way cleaner to me
I have a quite simple situation I don't know how to resolve :
I am parsing a file with addresses (city, street and street number), and have the following class :
class Address
{
std::string city;
std::string street;
std::string number;
};
I would like to create an object for each address I find in the file, but I can't know how many there are since the file can change. Is there a way to create an Array of objects ; or any more suitable solution ?
NOTE : Parser works fine, all there is to do is to set the values in the objects.
You can use std::vector for such purpose: http://en.cppreference.com/w/cpp/container/vector
#include <vector>
struct Address
{
std::string city;
std::string street;
std::string number;
};
bool parseAddress(Address& address)
{
//TODO: implement
//TODO: return "true" if another address has been successfully parsed
}
int main()
{
std::vector<Address> addresses;
Address current;
while(parseAddress(current))
{
addresses.push_back(current);
}
return 0;
}
Like #Serge but rather than use the parser directly define an input operator.
struct Address
{
std::string city;
std::string street;
std::string number;
friend std::istream& operator>>(std::istream& in, Address& address) {
return parseAddress(in, address);
}
};
std::istream& parseAddress(std::istream& in, Address& address)
{
//TODO: implement
//TODO: return stream.
// If the parse failed.
// Then set the bad bit on the stream.
}
int main()
{
std::ifstream file("address.txt");
std::vector<Address> addresses(std::istream_iterator<Address>(file),
std::istream_iterator<Address>());
}