How should we add function inside a structure? - c++

#include <iostream>
using namespace std;
struct teacher
{
int id;
char name[50];
int salary;
void input(teacher a)
{
cout << "Enter Name : ";
cin >> a.name;
cout << "Enter ID : ";
cin >> a.id;
cout << "Enter Salary : ";
cin >> a.salary;
}
void output(teacher b)
{
cout << "Your Name Is : " << b.name << endl;
cout << "Your ID Is : " << b.id << endl;
cout << "Your Salary Is : " << b.salary;
}
};
int main()
{
teacher t;
t.input(t);
t.output(t);
return 0;
}
Is there any problem? The output is random numbers, don't know what is it.
I tried writing the output function separately, but still same results.

This seems like a weird design, why don't your class methods directly operate on this?
struct teacher
{
int id;
std::string name;
int salary;
void input()
{
cout << "Enter Name : ";
cin >> name;
cout << "Enter ID : ";
cin >> id;
cout << "Enter Salary : ";
cin >> salary;
}
void output() const
{
cout << "Your Name Is : " << name << endl;
cout << "Your ID Is : " << id << endl;
cout << "Your Salary Is : " << salary;
}
};
Then main would look like
int main()
{
teacher t;
t.input();
t.output();
return 0;
}
Also I'd prefer to use std::string instead of char[] when possible.

In input() you modify parameter a which goes out of scope when it reaches the end of the function.
Instead you should modify the class members variables themselves.
void input()
{
cout << "Enter Name : ";
cin >> name;
cout << "Enter ID : ";
cin >> id;
cout << "Enter Salary : ";
cin >> salary;
}

Related

Getting in error while performing Nested STRUCT in C++

I am solving a question of Nested structure in C++ but
I am getting an error in accessing the member function of struct Date i.e: void showdata()
First I have made a Data struct then in it I have added member function called void showdata which will show data of my another Struct Employee. However I can't access this member function in my main program.
ERROR :
Error C2660 'Date::showdata': function does not take 0 arguments
so basically getting an error in the last line of code that is:
d.showdata()
Here's my code:
struct Date
{
int year, month, date;
void showdata(int empid, string name, double salary, int year, int month,int date)
{
cout << "\t\tEmployee's Data:\n";
cout << "Employee ID --> " << empid << endl;
cout << "Employee Name --> " << name << endl;
cout << "Salary --> " << salary << endl;
cout << "Joining Date -- >" << date << "-" << month << "-" << year << endl;
}
};
struct Employee
{
int empid;
string name;
double salary;
Date joiningdate;
};
int main()
{
//Q3
Employee e;
Date d;
cout << "Enter Employee ID = ";
cin >> e.empid;
cout << "Enter Employee Name = ";
cin >> e.name;
cout << "Enter Salary = ";
cin >> e.salary;
cout << "Enter Employee joining year = ";
cin >> e.joiningdate.year;
cout << "Enter Employee joining month = ";
cin >> e.joiningdate.month;
cout << "Enter Employee joining date = ";
cin >> e.joiningdate.date;
d.showdata();
}
Did you mean to move the member function into the Employee class?
struct Date
{
int year, month, date;
};
struct Employee
{
int empid;
string name;
double salary;
Date joiningdate;
void showdata()
{
cout << "\t\tEmployee's Data:\n";
cout << "Employee ID --> " << empid << endl;
cout << "Employee Name --> " << name << endl;
cout << "Salary --> " << salary << endl;
cout << "Joining Date -- >" << joiningdate.date << "-" << joiningdate.month << "-" << joiningdate.year << endl;
}
};
int main()
{
//Q3
Employee e;
cout << "Enter Employee ID = ";
cin >> e.empid;
cout << "Enter Employee Name = ";
cin >> e.name;
cout << "Enter Salary = ";
cin >> e.salary;
cout << "Enter Employee joining year = ";
cin >> e.joiningdate.year;
cout << "Enter Employee joining month = ";
cin >> e.joiningdate.month;
cout << "Enter Employee joining date = ";
cin >> e.joiningdate.date;
e.showdata();
}
You defined the showdata method inside the Date struct to take 6 arguments, yet when invoking the method in main you are supplying 0 arguments. To correctly invoke the showdata method you need to supply it with the correct set of parameters:
d.showdata(e.empid, e.name, e.salary, e.joiningdate.year, e.joiningdate.month, e.joiningdate.date);
Also be sure to check that the parameter types that you are passing in match the argument types that you defined the method to accept.

Why won't Xcode (10.1) realize this class? What am I doing wrong

Basically trying to just run this program for extra learning, Xcode won't understand that I have written a class, and wont implement it. Really confused and need some guidance.
When I run the code only the main method is implemented, nothing else works...
#include <iostream>
using namespace std;
class students {
int id;
char name[20];
int s1;
int s2;
int s3;
public:
void getData() {
cout << "Enter the ID " << endl;
cin >> id;
cout << "Enter the name " << endl;
cin >> name;
cout << "Enter the grade in subject 1 " << endl;
cin >> s1;
cout << "Enter the grade in subject 2 " << endl;
cin >> s2;
cout << "Enter the grade in subject 3 " << endl;
cin >> s3;
}
void putData() {
cout << id << " " << name << " " << s1 << " " << s2 << " " << s3 << endl;
}
};
int main () {
students s[20];
int i, n; //i is for the for loop, n for number of students
cout << "Enter the number of students " << endl;
cin >> n;
for (i=0;i>n;i++)
{
s[i].getData();
}
for (i=0;i>n;i++)
{
s[i].putData();
}
return 0;
}

How to modify a nested struct on a vector?

I am working on a program that keeps inventory of vehicles, so I created a struct for it. It also needs to keep a list of the drivers, so I created a nested struct for that. Here's the code:
struct Vehicle {
string License;
string Place;
int Capacity;
struct Driver {
string Name;
int Code;
int Id;
} dude;
};
I ask for user input and then put the structs in a vector using this function:
void AddVehicle(vector<Vehicle> &vtnewV) {
Vehicle newV;
Vehicle::Driver dude;
cout << "Enter license plate number: " << endl;
cin >> newV.License;
cout << "Enter the vehicle's ubication: " << endl;
cin >> newV.Place;
cout << "Enter the vehicle's capacity: " << endl;
cin >> newV.Capacity;
cout << "Enter the driver's name: " << endl;
cin >> dude.Name;
cout << "Enter the driver's code: " << endl;
cin >> dude.Code;
cout << "Enter the driver's identification number: " << endl;
cin >> dude.Id;
vtnewV.push_back(newV);
};
Now, I need to know if there's a way to add the driver on another function, like, you ask for the vehicle info on one function and then ask for the driver's info on another. The user enters the license plate, for example, and the driver is added in the struct that has that license plate. I don't know if I'm explaining myself. So, that's it, if you can help me, I would really appreciate it.
Example of your own code:
#include <iostream>
#include <string>
#include <vector>
#include <limits>
struct Vehicle {
std::string License;
std::string Place;
int Capacity;
struct Driver {
std::string Name;
int Code;
int Id;
}dude;
};
void AddVehicle(std::vector<Vehicle> &vtnewV)
{
Vehicle newV;
std::cout << "Enter license plate number: " << std::endl;
std::cin >> newV.License;
std::cout << "Enter the vehicle's ubication: " << std::endl;
std::cin >> newV.Place;
std::cout << "Enter the vehicle's capacity: " << std::endl;
std::cin >> newV.Capacity;
std::cout << "Enter the driver's name: " << std::endl;
std::cin >> newV.dude.Name;
std::cout << "Enter the driver's code: " << std::endl;
std::cin >> newV.dude.Code;
std::cout << "Enter the driver's identification number: " << std::endl;
std::cin >> newV.dude.Id;
vtnewV.push_back(newV);
};
int main()
{
std::vector<Vehicle> listVehicle;
AddVehicle(listVehicle);
AddVehicle(listVehicle);
for (auto& i : listVehicle)
{
std::cout << i.dude.Name << " got crabs" << std::endl;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 0;
}
Now, I need to know if there's a way to add the driver on another
function, like, you ask for the vehicle info on one function and then
ask for the driver's info on another.
I don't know if this is what you are after but there is a way better way to solve this than doing it this way, but without changing too much of your code, this will give you a hint:
#include <iostream>
#include <string>
#include <vector>
#include <limits>
struct Vehicle {
std::string License;
std::string Place;
int Capacity;
struct Driver {
std::string Name;
int Code;
int Id;
}driver;
};
Vehicle CreateVehicle()
{
Vehicle vehicle;
std::cout << "Enter license plate number: " << std::endl;
std::cin >> vehicle.License;
std::cout << "Enter the vehicle's ubication: " << std::endl;
std::cin >> vehicle.Place;
std::cout << "Enter the vehicle's capacity: " << std::endl;
std::cin >> vehicle.Capacity;
return vehicle;
};
Vehicle::Driver CreateDriver()
{
Vehicle::Driver driver;
std::cout << "Enter the driver's name: " << std::endl;
std::cin >> driver.Name;
std::cout << "Enter the driver's code: " << std::endl;
std::cin >> driver.Code;
std::cout << "Enter the driver's identification number: " << std::endl;
std::cin >> driver.Id;
return driver;
}
int main()
{
std::vector<Vehicle> listVehicle;
auto vehicle = CreateVehicle();
auto driver = CreateDriver();
vehicle.driver = driver;
listVehicle.push_back(vehicle);
for (auto& i : listVehicle)
{
std::cout << i.driver.Name << " got crabs" << std::endl;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return 0;
}
How to modify a nested struct on a vector?
To set the driver of the N-th item from the vector of Vehicles, you'd use:
Vehicle::Driver driver_dude;
...
...
vtnewV[N-1].dude = driver_dude;
#include <iostream>
#include <vector>
using namespace std;
struct Driver
{
string Name;
int Code;
int Id;
};
struct Vehicle
{
string License;
string Place;
int Capacity;
///from my opinion driver should be declare like this
Driver driver;
};
vector <Vehicle> vtnewV ;
/// the vector need to declare outside the void
/// else it will keep recreate a new vector
void AddVehicle()
{
Vehicle newV;
cout << "Enter license plate number: " << endl;
cin >> newV.License;
cout << "Enter the vehicle's ubication: " << endl;
cin >> newV.Place;
cout << "Enter the vehicle's capacity: " << endl;
cin >> newV.Capacity;
cout << "Enter the driver's name: " << endl;
cin >> newV.driver.Name;
cout << "Enter the driver's code: " << endl;
cin >> newV.driver.Code;
cout << "Enter the driver's identification number: " << endl;
cin >> newV.driver.Id;
vtnewV.push_back(newV);
};
void ShowInfo()
{
for(int i= 0; i<vtnewV.size();i++)
{
cout<<vtnewV[].License<<newV.driver.Id;
///you need to use for loop to cout all that exist in vector info
}
}
int main()
{
AddVehicle();
ShowInfo();
return 0;
}
I have modify and added some comment to your code base by my own opinion
hope that will solve you problem

Create a vector of base class objects and store derived class objects within

I am trying to create an employee database (Vector of Employees). There are 3 types of employees ie. employees is the base class and Manager, Engg and Scientist are derived class.
Every employee has first name and last name. In addition to the name, each of the 3 types of employees have unique stats ie. Manager has number of meetings/week whereas the Engg has work experience and so on.
I have a couple of questions
1. Should I upcast the derived objects to the base class or downcast the base class to the derived class?
2. How do I use polymorphism to override methods, since I want the user to add an employee type and based on the type selected the respective entry fields should appear ie. in case of a Manager, in addition to the first and last names, the program should also ask for meetings/week?
Here is my Class file
class Employee{
public:
Employee();
Employee(string fName, string lName, int sal);
virtual void printEmp();
string getFirstName();
string getLastName();
protected:
string m_fName;
string m_lName;
int m_sal;
};
class Manager : public Employee{
public:
Manager();
Manager(string fName, string lName, int sal, int meets, int hols);
void printEmp();
protected:
int m_meets;
int m_hols;
};
Here is the implementation
Employee::Employee(){
m_fName = "Default";
m_lName = "Default";
m_sal = 0;
}
Employee::Employee(string fName, string lName, int sal){
m_fName = fName;
m_lName = lName;
m_sal = sal;
}
void Employee::printEmp(){
cout << "First Name: " << m_fName << endl
<< "Last Name: " << m_lName << endl
<< "Salary: " << m_sal << endl;
}
string Employee::getLastName(){
return m_lName;
}
string Employee::getFirstName(){
return m_fName;
}
Manager::Manager(string fName, string lName, int sal, int meets, int hols) : Employee(fName, lName, sal), m_meets(meets), m_hols(hols)
{
//empty
}
void Manager::printEmp(){
Employee::printEmp();
cout << "Meets/Week: " << m_meets << endl
<< "Holidays/Year: " << m_hols << endl << endl;
Here is the main
int main(){
bool exit = false;
vector<Employee*> dBVector;
while (!exit){
cout << "Welcome to Employee Database, Enter an option to continue..." << endl;
cout << "1) Add an Employee, 2) Delete an Employee, 3) Save Database, 4) Exit" << endl;
int input;
cin >> input;
string fNameInp;
string lNameInp;
int salInp;
string lNameSearch;
int i; // for loop in Delete employee case
bool deleted = false;
switch (input){
case 1: //Add
cout << "1) Add a Manager, 2) Add an Engg, 3) Add a Researcher" << endl;
int empInput;
cin >> empInput;
if (empInput == 1){
cout << "Enter First Name: ";
cin >> fNameInp;
cout << "Enter Last Name: ";
cin >> lNameInp;
cout << "Enter Salary: ";
cin >> salInp;
cout << "Number of meetings/week: ";
int meetsInp;
cin >> meetsInp;
cout << "Number of holidays/year: ";
int holsInp;
cin >> holsInp;
Manager mEmp(fNameInp, lNameInp, salInp, meetsInp, holsInp);
Employee &emp = mEmp;
dBVector.push_back(&mEmp);
dBVector[dBVector.size()-1]->printEmp();
}
else if (empInput == 2){
cout << "Enter First Name: ";
cin >> fNameInp;
cout << "Enter Last Name: ";
cin >> lNameInp;
cout << "Enter Salary: ";
cin >> salInp;
cout << "Cpp Experience (Y/N): ";
string cppInp;
cin >> cppInp;
cout << "Years of experience: ";
float expInp;
cin >> expInp;
cout << "Engg Type (Chem, Mech, IT): ";
string typInp;
cin >> typInp;
Engg eEmp(fNameInp, lNameInp, salInp, cppInp, expInp, typInp);
Employee &emp = eEmp;
dBVector.push_back(&eEmp);
dBVector[dBVector.size() - 1]->printEmp();
}
else if (empInput == 3){
cout << "Enter First Name: ";
cin >> fNameInp;
cout << "Enter Last Name: ";
cin >> lNameInp;
cout << "Enter Salary: ";
cin >> salInp;
cout << "School of PhD: ";
string schoolInp;
cin >> schoolInp;
cout << "Topic of PhD: ";
string topImp;
cin >> topImp;
Researcher rEmp(fNameInp, lNameInp, salInp, schoolInp, topImp);
Employee &emp = rEmp;
dBVector.push_back(&rEmp);
dBVector[dBVector.size() - 1]->printEmp();
}
break;
case 2: // Delete Emp
for (int x = 0; x < dBVector.size(); x++){
dBVector[x]->getLastName();
cout << endl;
}
cout << "Input Last name of the employee to delete: " << endl;
cin >> lNameSearch;
for (i = 0; i < dBVector.size(); i++){
if (dBVector[i]->getLastName() == lNameSearch){
dBVector.erase(dBVector.begin() + i);
cout << dBVector[i]->getFirstName() << "has been deleted from database";
deleted = true;
break;
}
}
if (deleted == false && i == dBVector.size()){
cout << "No Employee with Last Name - " << lNameSearch << " exists in Database." << endl;
}
else
break;
case 3: //save
cout << "saving..." << endl;
break;
case 4: //exit
exit = true;
break;
}
}
}
Please Help!
Firstly, if you want to use polymorphism you need to store pointers in your vector. As the vector is the sole owner of the employees something like std::vector<std::unique_ptr<Employee>> would be suitable.
Edit: I see you have updated the vector to use pointers. But you are storing a pointer to a local stack allocated object, e.g mEmp. This will not work, when the mEmp variable goes out-of-scope at the closing brace the object will be deleted and you will be left with a dangling pointer in your vector that points to a deleted object. Using this dangling pointer is undefined behaviour. You need to allocate the Manager on the heap using new. Then the object will not be deleted when the variable goes out-of-scope but you do need to remember to delete the object when you are done. Something like unique_ptr makes this easy.
Regarding your questions:
Try to minimize explicit casting, especially downcasting. At the point that you store the Employee in the vector it will be implicitly upcast from the derived class to Employee but other than that there is not much need for casting.
You have roughly the right idea when it comes to overriding methods, if you call the virtual printEmp method on an Employee pointer it will call the override in the derived class.
If you are happy for the user input to be the responsibility of the Employee classes you could simply add a virtual method that initializes the employee using suitable input from the user. But I would be tempted to keep that separate from your domain objects. You need a switch statement on the user choice of employee type anyway so polymorphism doesn't gain you much there.
If you really want to use polymorphism for the employee creation I would suggest using something like the Abstract Factory pattern.
Here is my suggestion anyway:
#include <vector>
#include <string>
#include <iostream>
#include <memory>
class Employee {
public:
Employee(std::string fName, std::string lName, int sal);
virtual ~Employee();
virtual void printEmp();
protected:
std::string m_fName;
std::string m_lName;
int m_sal;
};
class Manager : public Employee {
public:
Manager(std::string fName, std::string lName, int sal, int meets, int hols);
void printEmp() override;
protected:
int m_meets;
int m_hols;
};
Employee::Employee(std::string fName, std::string lName, int sal)
: m_fName(fName), m_lName(lName), m_sal(sal) {
}
Employee::~Employee() {
}
void Employee::printEmp(){
std::cout << "First Name: " << m_fName << "\n"
<< "Last Name: " << m_lName << "\n"
<< "Salary: " << m_sal << "\n";
}
Manager::Manager(std::string fName, std::string lName, int sal, int meets, int hols)
: Employee(fName, lName, sal), m_meets(meets), m_hols(hols){
}
void Manager::printEmp(){
Employee::printEmp();
std::cout << "Meets/Week: " << m_meets << "\n"
<< "Holidays/Year: " << m_hols << "\n";
}
std::unique_ptr<Manager> createManager() {
std::cout << "Enter First Name: ";
std::string fNameInp;
std::cin >> fNameInp;
std::cout << "Enter Last Name: ";
std::string lNameInp;
std::cin >> lNameInp;
std::cout << "Enter Salary: ";
int salInp;
std::cin >> salInp;
std::cout << "Number of meetings/week: ";
int meetsInp;
std::cin >> meetsInp;
std::cout << "Number of holidays/year: ";
int holsInp;
std::cin >> holsInp;
std::cout << "\n";
return std::make_unique<Manager>(fNameInp, lNameInp, salInp, meetsInp, holsInp);
}
std::unique_ptr<Employee> createEmployee() {
int input;
std::cout << "1) Add a Manager, 2) Add an Engg, 3) Add a Researcher\n";
std::cin >> input;
switch (input){
case 1:
return createManager();
default:
return nullptr;
}
}
int main() {
std::vector<std::unique_ptr<Employee>> dBVector;
std::cout << "Welcome to Employee Database, Enter an option to continue...\n";
std::cout << "1) Add an Employee"
<< ", 2) Delete an Employee"
<< ", 3) Save Database"
<< ", 4) Exit\n";
int input;
std::cin >> input;
switch (input){
case 1:
dBVector.push_back(createEmployee());
break;
default:
break; // Do nothing
}
dBVector.at(0)->printEmp();
}
Live demo
You may want to store pointers in the vector to avoid slicing, as others mentioned. Then each employee could have their own input method and ask the right questions to initialize themselves (main would not implement that but only call the respective employee's virtual input function). Input and output are conceptually sysmmetrical operations which hints at implementing them symmetrically, i.e. in this case both as member functions.

Address Book using Inheritance and Operator Overloading or Exception handling

I have to make an address book using C++ and should include classes and inherited classes. The main class contains name and address and the inherited Teacher class contains teacher Phone number and CNIC and Employee class contains Phone and CNIC and the Student class contains student ID and Phone. I made a program in C++ but that would always over write the previous data. I am stuck here. I would need a skull program or simple algorithms to guide me ahead.
This is my code.
// new.cpp : Defines the entry point for the console application.
// Address Book.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include<iostream>
#include<string>
#include <conio.h>
#include <fstream>
#include <sstream>
#include <iomanip>
using namespace std;
class Main
{
private:
string Name;
string Address;
char test;
public:
virtual void getdata()
{
ofstream outfile("TEMP.txt");
cout <<"Enter Name: " ;
cin>>test;
getline(cin, Name); //cin >> Name;
cout << endl;
cout << "Enter Address: ";
getline(cin, Address);// cin >> Address;
outfile << Name
<< endl
<< Address;
}
virtual void setdata()
{
cout << "\n\nName: " << test+Name;
cout << "\nAddress: " << Address;
}
virtual void remove()
{
}
};
//----------------------------------------------------------
class Teacher : public Main
{
private:
int T_Number;
string T_CNIC;
public:
void getdata()
{
ofstream outfile("Teacher.txt");
Main::getdata();
cout << "Enter CNIC: ";
getline(cin,T_CNIC);//cin >> T_CNIC;
cout << "Enter Contact Number: " << endl;
cin >> T_Number;
outfile << T_CNIC
<< endl
<< T_Number;
cout << "Data entered" << endl;
}
void setdata()
{
Main::setdata();
cout << "\nTeacher CNIC: " << T_CNIC;
cout << "\nTeacher Contact Number: " << T_Number;
}
};
//------------------------------------------------------------
class Student : public Main
{
private:
int S_Number;
int S_ID;
public:
void getdata()
{
ofstream outfile("Student.txt");
Main::getdata();
cout << "Enter ID: ";
cin >> S_ID;
cout << "Enter Contact Number: ";
cin >> S_Number;
outfile << S_ID
<< endl
<< S_Number;
cout << "Data entered" << endl;
}
void setdata()
{
Main::setdata();
cout << "\nStudent Unique ID: " << S_ID;
cout << "\nStudent Contact Number: " << S_Number;
}
};
class Employee : public Main
{
private:
int E_Number;
string E_CNIC;
public:
void getdata()
{
ofstream outfile("Employee.txt");
Main::getdata();
cout << "Enter Employee CNIC: ";
getline(cin,E_CNIC);//cin >> E_CNIC;
cout << "Enter Contact Number: ";
cin >> E_Number;
outfile << E_CNIC
<< endl
<< E_Number;
cout << "Data entered" << endl;
;}
void setdata()
{
Main::setdata();
cout << "\nEmployee Unique ID: " << E_CNIC;
cout << "\nEmployee Contact Number: " << E_Number;
}
};
//-----------------------------------------------------------------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
Main* myarr[100];
int var = 0;
int choice;
char input;
start:
printf("===============MAIN MENU===============");
printf("\n[1]Insert\n[2]Search\n[3]Delete\n[4]Exit\n");
printf("=======================================");
printf("\n\nEnter Your Choice: ");
cin >> choice;
switch(choice)
{
case 1:
cout << "\nEnter data for Student or Teacher or Employee (s/t/e)? ";
cin >> input;
do
{
if( input=='t' )
myarr[var] = new Teacher;
else if (input == 'e')
myarr[var] = new Employee;
else
myarr[var] = new Student;
myarr[var++]->getdata();
cout << " Enter another (y/n)? ";
cin >> input;
if(input == 'n')
{
goto start;
}
}
while( input =='y');
for(int j=0; j<var; j++)
myarr[j]->setdata();
cout << endl;
break;
case 2:
return 0;
break;
case 3:
return 0;
break;
case 4:
cout << "Are you sure you want to quit? " << endl;
getch();
break;
default:
cout << "Choose from 1 - 4 ONLY!!" << endl;
goto start;
break;
}
return 0;
}
Then I would try declared it protected, and instead of calling main::getdata(), you directly write data into the file. see if that works.