I recently made an application with 1 superclass and 2 subclasses. The main idea of it is storing information in 3 different list. My question is, can you only use 1 list for all 3 classes? Even though the 2 subclasses have some extra members. Someone told me that you could use unique_ptr as a member of the superclass and make only 1 list. I have read about it on the internet, but I can't quite get it. Any suggestions? Thank you for your time.
class Student {
std::string Name;
std::string Pinfo;
std::map < std::string, float > Ngradelist;
public:
std::string getName() {return Name;}
std::string getPinfo() {return Pinfo;}
virtual void InsertGradeList(std::string a, float b) {
for(auto& it : Ngradelist)
Ngradelist.insert(std::pair <std::string, float > (a,b));
}
Student( std::string n, std::string p, std::map < std::string, float > Ng) :
Name(std::move(n)), Pinfo(std::move(p)), Ngradelist(std::move(Ng)) {}
virtual void Display() {
std::cout << "Name: " << Name << std::endl;
std::cout << "Personal information: " << Pinfo << std::endl;
std::cout << "NCourse:" << std::endl;
for(auto& it : Ngradelist)
std::cout << " " << it.first << " Grade: " << it.second << std::endl;
}
};
class HWStudent : public Student {
std::string FieldOfWork;
std::map<std::string, float> HWgradelist;
public:
void InsertGradeList(std::string a, float b) override{
for (auto &it : HWgradelist)
HWgradelist.insert(std::pair<std::string, float>(a, b));
}
HWStudent(std::string n, std::string p, std::map<std::string, float> Ng, std::string f,
std::map<std::string, float> HWg) : Student(std::move(n), std::move(p), std::move(Ng)),
FieldOfWork(std::move(f)), HWgradelist(std::move(HWg)) {}
void Display() override {
Student::Display();
std::cout << "Field of Work: " << FieldOfWork << std::endl;
std::cout << "HWCourse:" << std::endl;
for(const auto& it : HWgradelist)
std::cout << " " << it.first << " Grade: " << it.second << std::endl;
}
};
class SWStudent : public Student {
std::map<std::string, float> SWgradelist;
std::list < std::string > Languages;
public:
void InsertGradeList(std::string a, float b) override {
for (const auto &it : SWgradelist)
SWgradelist.insert(std::pair<std::string, float>(a, b));
}
SWStudent(std::string n, std::string p, std::map<std::string, float> Ng, std::list < std::string > l,
std::map<std::string, float> SWg) : Student(std::move(n), std::move(p), std::move(Ng)),
Languages(std::move(l)), SWgradelist(std::move(SWg)) {}
void Display() override {
Student::Display();
std::cout << "SWCourse:" << std::endl;
for(const auto& it : SWgradelist)
std::cout << " " << it.first << " Grade: " << it.second << std::endl;
std::cout << "SW Languages:" << std::endl;
for(const auto& it : Languages)
std::cout << " " << it << std::endl;
}
};
std::list < Student > listaStudenti;
std::list < HWStudent > HWlistaStudenti;
std::list < SWStudent > SWlistaStudenti;
void InsertListaStudenti(unsigned short option) {
unsigned short numbers;
std::string name , pinfo, course, fieldofwork, hwcourse, swcourse;
std::string language;
float grade = 0, hwgrade, swgrade;
std::list < std::string > languagelist;
if(option == 1) {
std::cout << "Insert name: ";
std::cin >> name;
std::cout << "Insert personal information: ";
std::cin >> pinfo;
std::cout << "Insert course: ";
std::cin >> course;
std::cout << "Insert grade: ";
std::cin >> grade;
Student student(name, pinfo, {{course, grade}});
listaStudenti.push_back(student);
}
if(option == 2) {
std::cout << "Insert name: ";
std::cin >> name;
std::cout << "Insert personal information: ";
std::cin >> pinfo;
std::cout << "Insert course: ";
std::cin >> course;
std::cout << "Insert grade: ";
std::cin >> grade;
std::cout << "Insert hwcourse: ";
std::cin >> hwcourse;
std::cout << "Insert hwgrade: ";
std::cin >> hwgrade;
std::cout << "Insert fieldofwork: ";
std::cin >> fieldofwork;
HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork,{{hwcourse, hwgrade}});
HWlistaStudenti.push_back(hwstudent);
}
if(option == 3) {
std::cout << "Insert name: ";
std::cin >> name;
std::cout << "Insert personal information: ";
std::cin >> pinfo;
std::cout << "Insert course: ";
std::cin >> course;
std::cout << "Insert grade: ";
std::cin >> grade;
std::cout << "Insert swcourse: ";
std::cin >> swcourse;
std::cout << "Insert swgrade: ";
std::cin >> swgrade;
std::cout << "How many languages: ";
std::cin >> numbers;
for(auto it = 0;it < numbers; ++it) {
std::cout << "Insert language: ";
std::cin >> language;
languagelist.push_back(language);
}
SWStudent swstudent(name, pinfo, {{course, grade}},languagelist,{{swcourse, swgrade}});
SWlistaStudenti.push_back(swstudent);
}
}
int main() {
unsigned short option = 10;
while(option != 0) {
std::cout << "1.Add student." << std::endl;
std::cout << "2.Add HW student." << std::endl;
std::cout << "3.Add SW student." << std::endl;
std::cout << "4.Display Student." << std::endl;
std::cout << "5.Display HW Student." << std::endl;
std::cout << "6.Display SW Student." << std::endl;
std::cout << "0 is for exit." << std::endl;
std::cout << "Option is : ";
std::cin >> option;
switch (option) {
case 0 : {
std::cout <<" You chose to leave.";
exit;
break;
}
case 1 : {
InsertListaStudenti(option);
break;
}
case 2 : {
InsertListaStudenti(option);
break;
}
case 3: {
InsertListaStudenti(option);
break;
}
case 4: {
for(auto &it : listaStudenti)
it.Display();
break;
}
case 5: {
for(auto &it : HWlistaStudenti)
it.Display();
break;
}
case 6: {
for(auto &it : SWlistaStudenti)
it.Display();
break;
}
}
}
}
You can indeed have
std::list<std::unique_ptr<Student>> students;
instead of
std::list<Student> listaStudenti;
std::list<HWStudent> HWlistaStudenti;
std::list<SWStudent> SWlistaStudenti;
with insertion similar to
Student student(name, pinfo, {{course, grade}});
students.push_back(std::make_unique<Student>(std::move(student)));
// or std::make_unique<Student>(name, pinfo, std::map<std::string, float>{{course, grade}})
HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork, {{hwcourse, hwgrade}});
students.push_back(std::make_unique<HWStudent>(std::move(hwstudent));
instead of
Student student(name, pinfo, {{course, grade}});
listaStudenti.push_back(student);
HWStudent hwstudent(name, pinfo, {{course, grade}}, fieldofwork,{{hwcourse, hwgrade}});
HWlistaStudenti.push_back(hwstudent);
Issue would be with your "filtering":
for (auto& student : SWlistaStudenti) {
student.Display();
}
becomes
for (auto& studentPtr : SWlistaStudenti) {
if (auto ptr = dynamic_cast<SWStudent*>(studentPtr.get())) ptr->Display();
}
but (to show only regular students (not HW/SW))
for(auto& student : listaStudenti) { student.Display(); }
becomes
for (auto& studentPtr : students) {
if (!dynamic_cast<SWStudent*>(studentPtr.get())
&& !dynamic_cast<HWStudent*>(studentPtr.get())) {
studentPtr->Display();
}
}
One list allows to treats them equality BTW:
To display all students:
for (auto& studentPtr : students) { studentPtr->Display(); }
instead of
for (auto& student : listaStudenti) { student.Display(); }
for (auto& student : HWlistaStudenti) { student.Display(); }
for (auto& student : SWlistaStudenti) { student.Display(); }
Related
so i am making a program that takes student data as objects and prints it, i am trying to store the data as an array so each student is a element in the array, i am having issues with printing the data though as i cannot pass the array into the print function, can anyone help? when i try and compile i get "studentarray: arrays of references are illegal". sorry if this is a stupid question i am new to coding, thankyou!
You wrote student printstudent(student & studentarray); which looks more like a deceleration than a function call.
I'm guessing you wanted to write printstudent(studentarray)?
Your error is caused by declaring printstudent(student& studentarray[10]) , which declares the function argument to be an array of 10 student& i.e. references to students, which the c++ standard forbids:
There shall be no references to references, no arrays of references, and no pointers to references.
Some more details on why can be found here: Why are arrays of references illegal?
After a bit of refactoring and fixing bugs, here it is:
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
class Student
{
public:
std::string name;
std::string email;
std::string number;
int grade1, grade2, grade3, grade4, totalGrade;
float percentage1, percentage2, percentage3, percentage4, totalPercentage;
public:
static void addStudent( std::vector<Student>& students )
{
std::cout << "\nEnter the number of students: ";
std::size_t count { };
std::cin >> count;
std::cout << '\n';
for ( std::size_t idx { }; idx < count; ++idx )
{
std::cout << "Enter the details of student #" << idx + 1 << ":\n";
students.resize( students.size( ) + 1 );
students.back( ).inputStudentDetails( );
std::cout << '\n';
}
std::cout << '\n';
}
void inputStudentDetails( )
{
std::cout << "Enter Student name: ";
std::cin >> name;
std::cout << "Enter student number: ";
std::cin >> number;
std::cout << "Enter student email: ";
std::cin >> email;
std::cout << "Enter grade for test1: ";
std::cin >> grade1;
std::cout << "Enter grade for test2: ";
std::cin >> grade2;
std::cout << "Enter grade for test3: ";
std::cin >> grade3;
std::cout << "Enter grade for test4: ";
std::cin >> grade4;
percentage1 = static_cast<float>( grade1 );
percentage2 = static_cast<float>( grade2 );
percentage3 = static_cast<float>( grade3 );
percentage4 = static_cast<float>( grade4 );
totalPercentage = percentage1 + percentage2 + percentage3 + percentage4;
}
void printStudentDetails( ) const
{
std::cout << "Student Name: " << name << "\nStudent Number: " << number
<< "\nStudent email: " << email << "\ngrade1: " << grade1
<< "\ngrade2: " << grade2 << "\ngrade3: " << grade3
<< "\ngrade4: " << grade4 << "\ntotal " << totalPercentage << " out of 400\n";
}
static void printAllStudentsDetails( const std::vector<Student>& students )
{
std::size_t idx { };
for ( const Student& stud : students )
{
std::cout << "\nDetails of student #" << ++idx << ":\n";
stud.printStudentDetails( );
std::cout << std::setfill( '-' ) << std::setw( 28 ) << '\n';
}
}
};
int main( )
{
std::vector<Student> students;
while ( true )
{
std::cout << "\t\tMENU\n" << std::setfill( '_' ) << std::setw( 36 ) << "\n\n";
std::cout << "1: Enter student details\n";
std::cout << "2: Display all students' details\n";
std::cout << "3: Exit the Application\n";
char select { };
std::cin >> select;
switch ( select )
{
case '1' : Student::addStudent( students ); break;
case '2' : Student::printAllStudentsDetails( students ); break;
case '3' : return 0;
default : std::cout << "Invalid Input!\n";
}
}
}
void Dog::readDog()
{
cout << "Name: ";
cin >> this->name;
cout << "height: ";
cin >> this->height;
cout << "weight: ";
cin >> this->weight;
cout << "Color: ";
cin >> this->color;
}
void Dog::printDog()
{
cout << "Name: " << this->name << endl;
cout << "Height: " << this->height << endl;
cout << "Weight: " << this->weight << endl;
cout << "Color: " << this->color << endl;
}
int main() {
Dog dogs;
int n;
cout << "Number of dogs to introduce: ";
cin >> n;
dogs.readDog();
dogs.printDog();
}
this is a part of my code and i have a little problem because i forgot how to set up a number of dogs that i want to introduce in program, e.g. i want 3 dogs : Max, Rex, Terry. My program read and print just one dog
You can use a std::vector for creating a container that will contain n number of Dog objects as shown below:
#include <iostream>
#include <vector>
#include <string>
class Dog
{
public:
void readDog();
void printDog();
private:
std::string name, color;
double height, weight;
};
void Dog::readDog()
{
std::cout << "Name: ";
std::cin >> this->name;
std::cout << "height: ";
std::cin >> this->height;
std::cout << "weight: ";
std::cin >> this->weight;
std::cout << "Color: ";
std::cin >> this->color;
}
void Dog::printDog()
{
std::cout << "Name: " << this->name << std::endl;
std::cout << "Height: " << this->height << std::endl;
std::cout << "Weight: " << this->weight << std::endl;
std::cout << "Color: " << this->color << std::endl;
}
int main() {
Dog dogs;
int n;
std::cout << "Number of dogs to introduce: ";
std::cin >> n;
std::vector<Dog> vecDogs(n); //create a vector (of size n) of Dog objects
for(int i = 0; i < n; ++i)
{
vecDogs.at(i).readDog();
vecDogs.at(i).printDog();
}
}
std::vector is a variable size container which means you can use it to have n number of Dog objects, where n need not be a constant expression.
The output of the above program can be seen here.
int a[9],b[9],i;
for(i=0; num>0; i++)
{
a[i]=num%2;
num= num/2;
}
I am working on decimal to binary conversion. I can convert themi want answer in 8 bits. And it gives me as, for example x =5, so output will be 101, but i want 00000101. Is there any way to append zeros in the start of array, without using any library.
The health clinic manages patients and the patient manages their own data.
You can run/check this code in https://repl.it/#JomaCorpFX/StdGetLine#main.cpp
Code
#include <iostream>
#include <string>
#include <vector>
class Patient
{
private:
std::string phoneNumber;
std::string name;
std::string email;
float weight;
float height;
public:
void SetName(const std::string &name)
{
this->name = name;
}
void SetEmail(const std::string &email)
{
this->email = email;
}
void SetPhoneNumber(const std::string &phoneNumber)
{
this->phoneNumber = phoneNumber;
}
void SetWeight(const float &weight)
{
this->weight = weight;
}
void SetHeight(const float &height)
{
this->height = height;
}
std::string GetName()
{
return this->name;
}
std::string GetEmail()
{
return this->email;
}
std::string GetPhoneNumber()
{
return this->phoneNumber;
}
float GetWeight()
{
return this->weight;
}
float GetHeight()
{
return this->height;
}
public:
};
class HealtClinic
{
private:
std::vector<Patient> patients;
public:
void AddPatient()
{
Patient p;
std::cout << "\nEnter name : ";
std::string sdata;
std::getline(std::cin, sdata);
p.SetName(sdata);
std::cout << "\nEnter email : ";
std::getline(std::cin, sdata);
p.SetEmail(sdata);
std::cout << "Enter phone number : ";
std::getline(std::cin, sdata);
p.SetPhoneNumber(sdata);
int idata;
std::cout << "Enter weight in kg : ";
std::cin >> idata;
p.SetWeight(idata);
std::cout << "Enter height in meters: ";
std::cin >> idata;
p.SetHeight(idata);
patients.push_back(p);
}
void ShowPatients()
{
std::cout << "--- PATIENTS ---" << std::endl;
for (int i = 0; i < patients.size(); i++)
{
std::cout << "--- " << i << std::endl;
std::cout << "Name: " << patients[i].GetName() << std::endl;
std::cout << "Email: " << patients[i].GetEmail() << std::endl;
std::cout << "Phone number: " << patients[i].GetPhoneNumber() << std::endl;
std::cout << "Weight: " << patients[i].GetWeight() << std::endl;
std::cout << "Height: " << patients[i].GetHeight() << std::endl;
std::cout << std::endl;
}
}
};
int main()
{
HealtClinic clinic;
clinic.AddPatient();
clinic.ShowPatients();
return EXIT_SUCCESS;
}
Output
Enter name : Joma
Enter email : joma#email.com
Enter phone number : 123456789
Enter weight in kg : 88
Enter height in meters: 1.8
--- PATIENTS ---
--- 0
Name: Joma
Email: joma#email.com
Phone number: 123456789
Weight: 88
Height: 1
I am brushing up some skills on C++ STL and I wrote a basic insertion/deletion code for maps.
Below is the code.
It is taking some inputs from user and inserting/deleting accordingly.
Very simple code.
But the issue is I have to write separate print functions for every map variant.
Is there anything I can do to make it common as we do in templates?
Any help would be highly appreciated.
#include <iostream>
#include <map>
#include <unordered_map>
using namespace std;
void print(const map<int, string>& mp)
{
cout << "Contents of map: { ";
for(auto& it: mp)
{
cout << it.first << " -> " << it.second << " ";
}
cout << "}" << endl;
}
void print(const multimap<int, string>& mp)
{
cout << "Contents of multi map: { ";
for(auto& it: mp)
{
cout << it.first << " -> " << it.second << " ";
}
cout << "}" << endl;
}
void print(const unordered_map<int, string>& mp)
{
cout << "Contents of unordered map: { ";
for(auto& it: mp)
{
cout << it.first << " -> " << it.second << " ";
}
cout << "}" << endl;
}
void print(const unordered_multimap<int, string>& mp)
{
cout << "Contents of unordered multi map: { ";
for(auto& it: mp)
{
cout << it.first << " -> " << it.second << " ";
}
cout << "}" << endl;
}
int main()
{
map<int, string> mp1;
multimap<int, string> mp2;
unordered_map<int, string> mp3;
unordered_multimap<int, string> mp4;
int value = 0;
string str;
cout << "Inserting..." << endl;
while(value >= 0)
{
cout << "Enter number: ";
cin >> value;
if(value >= 0)
{
cout << "Enter string: ";
cin >> str;
mp1.insert(pair<int, string>(value, str));
mp2.insert(pair<int, string>(value, str));
mp3.insert(pair<int, string>(value, str));
mp4.insert(pair<int, string>(value, str));
}
}
print(mp1);
print(mp2);
print(mp3);
print(mp4);
value = 0;
cout << "Removing..." << endl;
while(value >= 0)
{
cout << "Enter number: ";
cin >> value;
if(value >= 0)
{
// removing by value
mp1.erase(value);
mp2.erase(value);
mp3.erase(value);
mp4.erase(value);
}
}
print(mp1);
print(mp2);
print(mp3);
print(mp4);
return 0;
}
Well, yes, that is, indeed, what templates are used for, right?
template<typename T>
void print(const T& mp)
{
cout << "Contents of map: { ";
for(auto& it: mp)
{
cout << it.first << " -> " << it.second << " ";
}
cout << "}" << endl;
}
This'll work as long as only maps, or reasonable facsimiles thereof, are passed to print() (and both keys and values in the maps have a working << overload). Otherwise, it might become necessary to use SFINAE or C++20 concepts to constrain overload resolution.
here is the code
class student
{
int num;
string name;
float marks;
public:
void add()
{
cout << "Enter the num name and marks:" << endl;
cin >> num >> name >> marks;
}
void display()
{
cout << num << endl;
cout << name << endl;
cout << marks << endl;
}
};
void main()
{
student ss;
multimap<int,student> st;
multimap<int,student>::iterator itr;
ss.add();
st.insert(make_pair(1000, ss));
for (itr = st.begin(); itr != st.end(); itr++)
{
cout << itr->second; // its showing ERROR
}
}
the error is
Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'student' (or there is no acceptable conversion) firstmultimap
how to fix this
To display the student object you need to overload << operator.
I have made the operator overloading function friend of student class so it could be called without creating an object.
Also, check this example on MSDN.
Example:
#include<iostream>
#include<map>
#include<string>
using namespace std;
class student
{
private:
int num;
string name;
float marks;
public:
void add()
{
cout << "Enter the num name and marks:" << endl;
cin >> num >> name >> marks;
}
void display()
{
cout << num << endl;
cout << name << endl;
cout << marks << endl;
}
friend ostream &operator << (ostream &output, const student &s)
{
output << "Num: " << s.num << "\nName: " << s.name << "\nMarks: " << s.marks << endl;
return output;
}
};
int main()
{
student ss;
multimap<int, student> st;
multimap<int, student>::iterator itr;
ss.add();
st.insert(make_pair(1000, ss));
for (itr = st.begin(); itr != st.end(); itr++)
{
cout << itr->second;
}
// Using Range based for loop
// for(const auto &i : st)
// cout << i.second;
return 0;
}