Struct inside a struct - c++

I have struct
struct Course{
int cId;
string courseName;
};
and I want to add students for each Course. I thought to define another struct in to struct Course like
struct Course{
int cId;
string courseName;
struct Student{
int sId;
string studentName;
};
};
if I define struct like this how could I use it ? I have Course * cptr = new Course[1];
which for using the struct course.
How could I add Students to specified cId's ?

Your Course does not contain a Student. It just defines a struct of that name, i.e. a type Course::Student. For a type to contain an instance of another type, you just have to declare a member variable:
struct Student { .... };
struct Course
{
....
Student student;
};
If you want each course to hold more than one Student, then you can use a container. In the absence of more information, the best candidate for that is std::vector:
struct Course
{
....
std::vector<Student> students;
};

struct Course
{
// ...
struct Student
{
int sId;
string studentName;
};
};
This defines a struct Course and another struct Course::Student, but Course does not instantiate any student (there is no member of Course which has a type Student). If you want students to be a member of course, you need something like this:
struct Course
{
// ...
struct Student
{
int sId;
string studentName;
} student;
};
or
struct Course
{
// ...
struct Student
{
int sId;
string studentName;
} students[10];
};
Which would define a single student or an array of 10 students as members of Course, respectively. (NOTE: std::vector would be a better choice than a statically sized array)
Alternatively, you can declare Student as a struct outside of Course:
struct Student { ... };
struct Course
{
// ...
Student student;
// or std::vector<Student> students;
// or std::array<Student, 10> students;
// or Student* students
};

A very simple way:
struct Student
{
int sId;
string studentName;
};
struct Course
{
int cId;
string courseName;
std::vector <Student> students;
};
This way you may write
Student s;
Course c;
c.students.push_back(s);

std::vector is your friend, but if you are not allowed to use that, you can do:
struct Student {...}; // Implementation omitted for brevity...
struct Course
{
Student *students_; // Use students_=new Student[num_students]; to allocate
// memory dynamically
};

I prefer you to divide this struct into two individual struct. Then you can initialize a student object in the Course struct. Or u can implement a function in Course struct to link with Student struct.

Related

C++ Creating Array of Objects

I'm having an issue with making one array with 3 objects. I'm trying to display the information of employees and my issue is that I don't know where I would assign the strings to the appropriate members and how to keep one variable for name. My code and an example are below:
class employee
{
private:
string name;
string idNumber;
public:
void setName(string);
void setIDnumber(string);
string getName();
string getIDnumber();
};
const int numEmployees = 3;
int main()
{
employee employeeInfo [numEmployees];
}
I want to create a constructor for 3 employees and input(name, idNumber). for example, in employeeInfo[0], the first employee, I want to input "Tom Jones", "123456"
and in employee[1], the second employee, "James Blyth", "QE123"
You can simply call the setter methods on the individual employee objects, eg:
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0].setName("Tom Jones");
employeeInfo[0].setIDNumber("123456");
employeeInfo[1].setName("James Blyth");
employeeInfo[1].setIDNumber("QE123");
// and so on...
...
}
If you really want to add a constructor, then it would look like this:
class employee
{
private:
string name;
string idNumber;
public:
employee() = default;
employee(string name, string idNumber);
...
};
employee::employee(string name, string idNumber) {
setName(name);
setIDnumber(idNumber);
};
...
int main()
{
employee employeeInfo [numEmployees];
employeeInfo[0] = employee("Tom Jones", "123456");
employeeInfo[1] = employee("James Blyth", "QE123");
// and so on...
}
Just note that this will default-construct the array elements first, and then construct temporary objects to overwrite the array elements.
If you want to avoid the temporaries, but still want a fixed array of objects stored consecutively, you can use placement-new to construct the array members directly using your non-default constructor, eg:
#include <type_traits>
int main()
{
std::aligned_storage_t<sizeof(employee), alignas(employee)> buffer[numEmployees];
employee* employeeInfo = reinterpret_cast<employee*>(buffer);
new(&employeeInfo[0]) employee("Tom Jones", "123456");
new(&employeeInfo[1]) employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
employeeInfo[i].~employee();
}
}
Or, you can use a std::vector (if you don't mind the array being allocated in dynamic memory), eg:
#include <vector>
int main()
{
std::vector<employee> employeeInfo;
employeeInfo.reserve(numEmployees);
employeeInfo.emplace("Tom Jones", "123456");
employeeInfo.emplace("James Blyth", "QE123");
// and so on...
...
}
Otherwise, create an array of pointers to objects instead, and then you can create the individual objects dynamically using new with your non-default constructor. The objects just won't be stored consecutively in memory, eg:
int main()
{
employee* employeeInfo[numEmployees];
employeeInfo[0] = new employee("Tom Jones", "123456");
employeeInfo[1] = new employee("James Blyth", "QE123");
// and so on...
...
for(int i = 0; i < numEmployees; ++i) {
delete employeeInfo[i];
}
}
Which would be safer handled with std::unique_ptr, eg:
#include <memory>
int main()
{
std::unique_ptr<employee> employeeInfo[numEmployees];
employeeInfo[0] = std::make_unique<employee>("Tom Jones", "123456");
employeeInfo[1] = std::make_unique<employee>("James Blyth", "QE123");
// and so on...
...
}

std::vector push_back class from a different namespace

I have a little example.
Im trying to add data to my std::vector from a class that is not in the same namespace.
both classes are the same.
How can i push data to to vector from a class that is not in same namespace
class A
{
public:
std::string name;
int32_t Size;
};
namespace TEST {
class A
{
public:
std::string name;
int32_t Size;
};
class File
{
public:
std::vector<A> data;
};
}
int main()
{
A data = { "outside namespace", 10 };
TEST::File file;
file.data.push_back(data);
return 0;
}
I guess you need an extra constructor in TEST::A for copying members from global A:
namespace TEST {
class A
{
public:
A(const ::A& a) :
name(a.name),
Size(a.Size)
{}
std::string name;
int32_t Size;
};
...
When pushing to vector do it like this:
int main()
{
A data = { "outside namespace", 10 };
TEST::File file;
file.data.push_back(TEST::A(data));
return 0;
}
How can i push data to to vector from a class that is not in same
namespace
The problem isnt really different namespaces, but the problem is that A and TEST::A are two different classes and you cannot push an A into a vector of TEST::As.
Just qualify the names with the namespace name:
TEST::A data = { "outside namespace", 10 };
A and TEST::A are two different classes.
You declare your vector to accept objects from the relevant class in its namespace:
std::vector<A> v; // will accept objects of class A
std::vector<TEST::A> v; // will accept objects of class TEST::A

C++ Access struct member by string reference [reflection]

Say I have a struct like the following:
struct employee
{
std::string name;
int age;
};
With boost fusion I can decorate the struct:
BOOST_FUSION_ADAPT_ASSOC_STRUCT(
demo::employee,
(std::string, name)
(int, age)
)
And access its members like this:
employee e;
boost::fusion::at_c<0, employee>(e)
Is there any way, at runtime, to get from a string "name" to the struct field
name?
The scenario of the code will be like this:
employee e; // or some other struct determined at runtime!
string attribute;
cin >> attribute;
// ApplyVisitor would inspect the correct field from the struct and act on it.
cout << ApplyVisitor(e, attribute);

implementing nested linked list in c++

Is this kind of implementation of nested linked list valid in c++?
if yes,then how to declare a head to those nested linked lists?
what is the syntax for accessing the data in those lists inside?
here is a part of my general code.
I'm trying to perform a library management system in c++.
struct course
{
string course_name;
struct course_books
{
struct wait_list
{
long stu_num;
//date inserted
wait_list * next_wait_stu;
};
struct voters_list
{
long stu_num;
int vote;
voters_list * next_voter;
};
struct deposit_list
{
long stu_num;
//date given
//bring back date
deposit_list * next_depositor;
};
};
course * next_course;
};
struct demand
{
int ISBN;
string book_name,
course,
author,
edition;
int demands_num;
struct demanding_students
{
string demander_name;
int demander_stu_number;
//demand date
demanding_students * next_demanding_stu;
};
demand * next_demand;
};
struct STUDENT_INFO
{
struct all_deposited_books
{
int ISBN;
//date given
//bring back date
all_deposited_books * next_dep_book;
};
struct today_deposited
{
int ISBN;
today_deposited * next_today_dep_book;
};
};
You would probably want to use classes for this instead. Something like:
class STUDENT_INFO{
protected:
struct all_deposited_books
{
int ISBN;
//date given
//bring back date
};
struct today_deposited
{
int ISBN;
};
public:
all_deposited_books * next_dep_book;
today_deposited * next_today_dep_book;
};
Then you create a class instance like: STUDENT_INFO theBestStudentInfo; and if you want to accses a struct variable inside that you just call: theBestStudentInfo.all_deposited_books[0].ISBN = 5; or something like that.
Aswell as I dont think you can create a struct instance inside the struct itself, like:
struct all_deposited_books
{
int ISBN;
//date given
//bring back date
all_deposited_books * next_dep_book; //<- this is probably gonna cause problems
};
first create the struct and how its going to look like, and then you can start creating how many instances of it as you want :)

dynamic memory allocation

how allocate memory dynamically for the array of stucture....
eg:
class students
{
struct stud
{
int r_no;
char name[20];
}*s;
}
how to allocate memory dynamically for *s...
First of all, this is not the way of doing it, as you could use a vector of stud, for instance. With the code as you have it, it would be something like:
class students
{
public:
struct stud ... *s;
students() // ctor
{
s = new stud[100]; // say you have 100 students
// from now on you can use s[0], s[1], etc. in the class
}
};
However, what you should be using is kind of an STL vector or list:
class students
{
public:
struct stud ... ;
std::vector<stud> my_students;
students() // ctor
{
stud aStudent = {0, "Student Name"};
my_students.push_back(aStudent); // add a new student.
}
};
Why the extra wrapping of the struct in a class with nothing but a pointer?
Anyway, in C you'd do something like this:
struct stud
{
int r_no;
char name[20];
} *s;
size_t num_students = 4711;
s = malloc(num_students * sizeof *s);
Then it'd be prudent to go through and make sure all those individial structs are initialized, of course.
If you mean this to be C++, you should write constructors that take care of that, and use a new[] to allocate an array of structures.
You should make use of standard components when you can. Here std::string and std::vector would help you.
struct Student
{
int r_no;
std::string name;
};
typedef std::vector<Student> StudentList;
With such an approach, there is no point in wondering how to dynamically allocate memory. Everything's taken care of !
EDIT:
I simply typedef'ed StudentList because to me, adding more functionality to it would have been unrelated to the question.
Clearly, the last line can be replaced with a true class definition:
class StudentList
{
public:
// Add your own functionalities here
private:
std::vector<Student> m_students;
};
class students
{
public:
students(size_t noOfStudents):m_noOfStudents(noOfStudents)
{
s = new stud[m_noOfStudents];
}
~students()
{
delete s;
}
private:
struct stud
{
int r_no;
char name[20];
}*s;
size_t m_noOfStudents;
}