Exception thrown - c++

I am working on a project and I'm a beginner. The project involves a person, adult, kid and bogie class. In bogie class I have initialsed pointer of type person named adult as adult = new Adult [adultcount], where adultcount is the number of adults user wants to add.
When I add only one adult in input, it works fine, it takes the input and assigns it in while assigning values in for loop.
But when I add more than one, it stops working and says exception throw at line Adults[i].setdata().
#include<iostream>
#include<string>
using namespace std;
class Person {
public:
string Name;
int Age;
string Gender;
public:
Person()
{
Name = '\0';
Age = 0;
Gender = '\0';
}
Person(string Name, int Age, string Gender)
{
this->Name = Name;
this->Age = Age;
this->Gender = Gender;
}
virtual void setdata()
{
string name, gender;
int age;
cin.ignore();
cout << " enter Name :";
getline(cin, name, '\n');
this->Name = name;
cout << endl;
cout << " Enter gender ";
getline(cin, gender, '\n');
this->Gender = gender;
cout << endl;
cout << " Enter age ";
cin >> age;
Age = age;
cout << endl;
}
virtual void printinfo()
{
cout << " name " <<Name;
cout << " Gender " << Gender;
cout << " age : " << Age;
}
};
class Adult :public Person {
public:
string Occupation;
string Qualification;
string NIC;
Adult():Person()
{
Occupation = '\0';
Qualification = '\0';
NIC = '\0';
}
Adult(string Occupation, string Qualification, string NIC, string Name, int Age, string Gender) : Person(Name, Age, Gender)
{
this->Occupation = Occupation;
this->NIC = NIC;
this->Qualification = Qualification;
}
void setdata()
{
Person::setdata();
string occupation, qualification/*, name, gender,*/ ,cnic;
/* int age;*/
cin.ignore();
/* cout << " enter Name :" ;
getline(cin, name, '\n');
this->Name = name;
cout << endl;*/
cout << "enter occupation ";
getline(cin, occupation, '\n');
this->Occupation = occupation;
cout << endl;
/*cout << " Enter gender ";
getline(cin, gender, '\n');
this->Gender = gender;
cout << endl;*/
cout << " enter qualification ";
getline(cin, qualification, '\n');
this->Qualification = qualification;
cout << endl;
cout << " Enter cnic ";
getline(cin, cnic, '\n');
this->NIC = cnic;
cout << endl;
/* cout << " Enter age ";
cin >> age;
this->Age = age;
cout << endl;*/
}
void printinfo()
{
Person::printinfo();
/*cout << " name "<<Name << endl;*/
cout << " occupation " << Occupation << endl;
/*cout << " Gender " << Gender << endl;*/
cout << " Qualifcation " << Qualification << endl;
/*cout << " Age " << Age << endl;
cout << " Gender " << Gender << endl;*/
}
};
class kid :public Person {
public:
string B_form_number;
kid() : Person()
{
B_form_number = '\0';
}
kid(string B_form_number, string Name, int Age, string Gender) :Person(Name, Age, Gender)
{
this->B_form_number = B_form_number;
}
void setdata()
{
Person::setdata();
string bform;
cout << " Enter B Form number ";
/* getline(cin, bform, '\n')*/;
cin >> bform;
this->B_form_number = bform;
cout << endl;
}
void setbform()
{
string bform;
cout << " Enter B Form number ";
getline(cin, bform, '\n');
this->B_form_number = bform;
cout << endl;
}
void printinfo()
{
Person::printinfo();
cout << " b form number " << B_form_number;
}
};
class Bogie /*:public kid*/ {
int Bogie_ID;
Bogie* next;
Person* Adults;
Person* kids;
string familyName;
int adultcount;
int kidcount;
public:
Bogie(int id)
{
Bogie_ID = id;
next = nullptr;
Adults = nullptr;
kids = nullptr;
familyName = '\0';
adultcount = 0;
kidcount = 0;
}
void AddPassengers() // should add adults and kids information etc
{
string familyName;
cout << "Enter family name " << endl;
cin.ignore();
getline(cin, familyName, '\n');
this->familyName = familyName;
bool condition = false;
bool condition2 = false;
while (condition == false) // runs until valid input for adults
{
cout << " How many adults in the family " << endl;
cin >> adultcount;
if (adultcount >= 1 && adultcount <= 4)
{
condition = true;
}
else
{
cout << " Invalid input " << endl;
cout << " We have seats for 4 adults " << endl;
condition = false;
}
}
while (condition2 == false) //runs until valid input for kids
{
cout << " How many kids in the family " << endl;
cin >> kidcount;
if (kidcount >= 1 && kidcount <= 6)
{
condition2 = true;
}
else
{
cout << " Invalid input " << endl;
cout << " We have seats for 6 kids " << endl;
condition2 = false;
}
}
this->Adults = new Adult[adultcount];
for (int i = 0; i < adultcount; i++)
{
Adults[i].setdata();
}
}
}
};
int main()
{
Bogie a(1);
a.AddPassengers();
a.Print();
}

I believe you need to change Adults from Person * to Adult *.
When the program tries to access Adults[1] at
for (int i = 0; i < adultcount; i++)
{
Adults[i].setdata();
}
It jumps ahead sizeof(Person) in the array, while the objects in the array are sizeof(Adult), which leads to the exception you're seeing.

so I found the answer the appropriate method to to it was declaring pointers named adult and kid in the members as
Person ** Adults;
Person **kids
and then
adults = new Person * [adultcount];
for (int i = 0; i < adultcount; i++)
{
adults[i] = new Adult;
adults[i]->setdata();
}

Related

Passing a struct array and updating array in C++

For one of my options, I had to add a row of data to my struct array, I was able to update the array but it does not update the actual array. So I am trying to update my struct array by passing it as a reference. I placed the '&' sign before the name of the variable, but all my indexes within the function errored.. I'm still a newbie to programing and I'm not "allowed " to use any vectors according to my Professor. . I looked online and placed the '&' on the function name as well as on the prototype. I also changed it from void to the "data type" to return the updated array, but no luck... I hope this comes out clear....
#include<iostream>
#include<iomanip>
#include<fstream>
using namespace std;
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void readFile( ifstream& , string, Data [],int&);
void getEmployeeDetail(Data [], int&);
void getEmployeeLast(Data [], int&);
Data getAddEmployee(Data &, int&);
void getRemoveEmployee();
void getManagerOnly();
void getStaffOnly();
const int SIZE = 15;
Data employee[SIZE];
int main() {
ifstream inputFile;
ofstream outputFile;
int count = 0;
int selection;
const int EMPLOYEE_DETAIL = 1,
EMPLOYEE_LAST = 2,
ADD_EMPLOYEE = 3,
REMOVE_EMPLOYEE = 4,
MANAGER_ONLY = 5,
STAFF_ONLY = 6,
QUIT = 7;
readFile( inputFile ,"employeeData.txt", employee,count);
do {
cout << "\t Please select your option.\n"
<< "1. List all employee details\n"
<< "2. List employee by last name\n"
<< "3. Add a new employee\n"
<< "4. Remove an employee\n"
<< "5. Show all managers only\n"
<< "6. Show all staff only\n"
<< "7. Quit\n"
<< "Please enter your selection.\n" << endl;
cin >> selection;
while (selection < EMPLOYEE_DETAIL || selection > QUIT) {
cout << " Pleasse enter a valid selection.\n";
cin >> selection;
}
switch (selection) {
case EMPLOYEE_DETAIL:
getEmployeeDetail(employee,count);
break;
case EMPLOYEE_LAST:
getEmployeeLast(employee, count);
break;
case ADD_EMPLOYEE:
getAddEmployee(employee, count);
break;
case REMOVE_EMPLOYEE:
getRemoveEmployee();
break;
case MANAGER_ONLY:
getManagerOnly();
break;
case STAFF_ONLY:
getStaffOnly();
break;
case QUIT:
cout << "Program ending\n";
break;
}
} while (selection != QUIT);
system("pause");
return(0);
}
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void readFile(ifstream& inputFile, string data, Data employee[],int &count) {
inputFile.open(data);
if (!inputFile) {
cout << " Error in opening file\n";
exit(1);
}
else {
while (!inputFile.eof()) {
inputFile >> employee[count].first_name;
inputFile >> employee[count].last_name >> employee[count].employee_id >> employee[count].phone_number;
count++;
}
inputFile.close();
}
return;
};
void getEmployeeDetail( Data employee[], int& count) {
cout << "Firt Name" << "\t" << "Last Name " << "\t" << "Employee ID " << "\t" << "Phone Number \n";
cout << "--------------------------------------------------------------------------\n";
for(int i =0; i < count; i++)
cout <<employee[i].first_name<<"\t\t"<<employee[i].last_name<<"\t\t"<<employee[i].employee_id<<"\t\t"<<employee[i].phone_number<< "\n ";
cout << endl;
}
void getEmployeeLast(Data employee[], int& count) {
string searchName;
cout << "Please enter the last name of the employee you want to search for.\n";
cin >> searchName;
/*
for (int i = 0; i < count; i++)
if (searchName ==employee[i].last_name) {
cout << employee[i].last_name;
}
*/
string matchString = searchName;
for (int i = 0; i < count; i++) {
if (employee[i].last_name.find(matchString, 0) != std::string::npos) {
cout << employee[i].last_name << endl;
}
else {
cout << "No employee was located with that name.\n";
exit(1);
}
}
}
Data getAddEmployee(Data &employee, int& count) {
string firstName, lastName, phoneNumber;
int employeeID, size;
for (int i = 0; i < count; i++)
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
cout << count <<"\n";
size = count + 1;
cout << size << "\n";
cout << "Please enter the new employee First Name.\n";
cin >> firstName;
cout << "Please enter the new employee Last Name.\n";
cin >> lastName;
cout << "Please enter the new employee's ID.\n";
cin >> employeeID;
cout << "Please enter the new employee Phone Number.\n";
cin >> phoneNumber;
employee[10].first_name = firstName;
employee[10].last_name = lastName;
employee[10].employee_id = employeeID;
employee[10].phone_number = phoneNumber;
for (int i = 0; i < size; i++) {
cout << employee[i].first_name << "\t\t\t" << employee[i].last_name << "\t\t" << employee[i].employee_id << "\t\t" << employee[i].phone_number << "\n ";
cout << endl;
}
return employee;
}
First of all, your naming could be better. Like employeeList instead employee to specify its a list/array of employee, also addEmployee instead of getAddEmployee.
Second, instead of pasting whole code, it's better to paste the relevant block of code based on your question to make it clearer.
The solution is, your array is basically already on global scope, you don't need to pass it. Can just directly modify the array.
struct Data {
string first_name;
string last_name;
int employee_id;
string phone_number;
};
void addEmployee();
const int SIZE = 15;
Data employeeList[SIZE];
int current = 0;
int main(){
Data emp1 = {"John", "Doe", 100, "12345"};
employeeList[0] = emp1;
current++;
addEmployee();
for(int i=0; i<current; i++){
Data emp = employeeList[i];
cout<<i+1<<" "<<emp.first_name<<" "<<emp.phone_number<<endl;
}
}
void addEmployee(){
Data emp2 = {"Sam", "Smith", 200, "67890"};
employeeList[current] = emp2;
current++;
}
Can try it here: https://onlinegdb.com/drhzEOpis

Is there a way i could end a loop with a char in c++?

I am new to programming, and I am currently trying to figure my way around C++. I am working on a program that will display basic information about employees to the users, and I want the program to end when the users entered a char. However, while working through it, I encountered a problem. When I enter the char (x), it somehow looped from 1-120 (as you seen in the counter below), but when I entered its ASCII number (120), it ended the program as intended. Can anyone explain it to me and what are the possible solutions?
#include <iomanip>
#include <iostream>
using namespace std;
class Employee
{
public:
int Age;
string Name;
int ID;
void information()
{
cout << "Name: " << Name << endl;
cout << "Age: " << Age << endl;
cout << "ID: " << setfill('0') << setw(3) << ID << endl;
}
Employee(string name, int age, int id)
{
Name = name;
Age = age;
ID = id;
}
};
void createProfile()
{
int age;
int id;
string name;
cout << "Enter the Employee Name: ";
cin >> name;
cout << "Enter the Employee Age: ";
cin >> age;
cout << "Enter the Employee ID: ";
cin >> id;
}
int main()
{
int num, counter;
const char stop = 'x';
cout << "Choose an Employee " << endl;
cout << "001 Jack" << endl;
cout << "002 Susan" << endl;
cout << "003 to create profile" << endl;
cout << "Press x to Exit";
for (num = 0; num != stop; num++)
{
cout << "\n\nEnter the Employee ID: ";
cin >> num;
counter += 1;
if (num == 001)
{
Employee jack = Employee("Jack", 25, 001);
jack.information();
}
else if (num == 002)
{
Employee jack = Employee("Susan", 23, 002);
jack.information();
}
else if (num == 003)
{
createProfile();
}
else
{
cout << "Input invalid";
}
}
cout << "\n" << counter;
}
Yes, of course. In C/C++, char is a type that can be represented either by its character value ('A', for example) or its numeric value (65). However, a digit's numeric value does not equal to itself.
'1' == 49
120 is the ASCII value of lower case x and since you loop with an int, it is logical that it will end up working in ways you do not expect it to work. You can change your
for (num = 0; num != stop; num++)
to
for (num = 0; ch != stop; num++)
and of course ch should be declared as char before your loop. Also, make sure that you replace cin >> num; with cin >> ch;

Why is my copy constructor being called when I try to add an element to my vector?

I am trying to add a customer to my vector and when I run my program the copy constructor is called. I am doing an assignment where I need a vector of customers and have to be able to add customers, display customers, find customers and load/store the data. Have I created the vector wrong? I am only new to c++ and really unsure about vectors.
Code from Main.cpp:
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include "Customer.h"
using namespace std;
void OutputFileStream();
void parseLine(const string& str);
void InputFileStream();
void save(vector<Customer> customers);
void load(vector<Customer>& customers);
void addCustomer(vector<Customer>& vect);
void displayAll(vector<Customer>& customers);
//void printActions();
vector<Customer> customers;
void OutputFileStream()
{
cout << "Creating and writing to file: Customer.txt" << endl;
ofstream outStream("customers.txt"); // write mode (overwrites existing data)
if (outStream.good())
{
int customerID = 150033;
outStream << "This is a line of text.\n";
outStream << "This is another line of text.\n";
outStream << "This is a line of text.\n";
int numOfPurchases = 4;
int purchases = 0;
outStream << customerID << "Mr" << "Jack" << "New" << numOfPurchases << purchases << endl;
//int *purchases = customers[0].getPurchases();
outStream.close(); // close file
cout << "File written.\n" << endl;
}
else
cout << "Unable to open file";
}
void parseLine(const string& str) {
stringstream strStream(str); //create string stream from the string
// int customerID;
string title;
string name;
string type;
//int numOfPurchases;
//int purchases;
string s;
int customerID = 150033;
getline(strStream, s, ';');
customerID = stoi(s);
getline(strStream, title, ';');
getline(strStream, name, ';');
getline(strStream, type, ';');
int numOfPurchases = 4;
getline(strStream, s, ';');
numOfPurchases = stoi(s);
int purchases = 0;
getline(strStream, s, ';');
purchases = stoi(s);
int* purchasesArray = new int[3];
purchasesArray[0] = (purchases & (255 << 16)) >> 16;
purchasesArray[1] = (purchases & (255 << 8)) >> 8;
purchasesArray[2] = purchases & 255;
for (int i = 0; i < 3; i++)
{
cout << purchasesArray[i];
}
cout << " CustomerID: " << customerID << "Title:" << title << " Name: " << name << " Type:" << type << " Number of Purchases: " << numOfPurchases << "Purchases: " << purchases << endl;
}
void InputFileStream() {
cout << "Reading from a semi-colon delimited txt file" << endl;
string line;
ifstream inStream("customers.txt"); //opens file as an input file stream
if (inStream.good()) //if the file is opened successfully and not empty
{
while (getline(inStream, line)) //reads line until false return
{
parseLine(line);
}
inStream.close();
}
else
cout << "unable to open file or the file is empty!";
}
void save(vector<Customer> customers)
{
ofstream out("customers.txt");
if(out)
{
for (Customer& c : customers)
{
out << c.save();
}
out.flush();
out.close();
}
else
{
cout << "Error Writing to File" << endl;
}
}
void load(vector<Customer>& customers)
{
ifstream in("customers.txt");
if (in) {
string line;
while (!in.eof())
{
getline(in, line);
if (line != "")
{
Customer c;
c.parse(line);
customers.push_back(c);
}
}
}
}
void addCustomer(vector<Customer>& customers) {
Customer customer;
cin >> customer;
customers.push_back(customer);
}
void displayAll(vector<Customer>& customers)
{
cout << "\nvector contains:\n";
for (Customer c : customers)
cout << c.getCustomerID() << " " << c.getTitle() << c.getName() << c.getNumOfPurchases() << c.getPurchases() << c.getType() << endl;
cout << endl;; //same as calling customer
}
//
//int getCustomerByPurchaseNumber(int numOfPurchases) {
// vector<Customer> customers;
// int pos = -1;
// for (int i = 0; i < customers.size(); i++) {
// if (customers.at(i).getNumOfPurchases() == numOfPurchases) {
// return i;
// }
// }
// return pos;
//}
//
//void findCustomerByPurchaseNumber(vector<Customer>& customers) {
// vector<Customer> customers;
// int numOfPurchases;
// cout << "Please Enter Your Purchase Number:" << endl;
// cin >> numOfPurchases;
// int pos = customers.get(pos);
// getCustomerByPurchaseNumber(numOfPurchases);
// if (pos == -1) {
// cout << "Number of Purchase Not Found! " << endl;
// return customers;
// }
// else {
// cout << "Number Of Purchase Found! " << endl;
//
// return customers* = customers;
// }
//
//}
int main()
{
vector<Customer> customers;
Customer c1 = { 150031, "Mr", "John", 5, 333,362,341, "New" };
customers.push_back(c1);
//InputFileStream();
/* Customer customer;
customer.setCustomerID(150032);
customer.setTitle("Mr");
customer.setName("Joey");
customer.setNumOfPurchases(3);
customer.setPurchases(366, 352, 334);
customer.setType("New");
cout << customer.getCustomerID() << endl;
cout << customer.getTitle() << endl;
cout << customer.getName() << endl;
cout << customer.getNumOfPurchases() << endl;
cout << customer.getPurchases() << endl;
cout << customer.getType() << endl;
*/
return 0;
}
Code from Customer.cpp:
#include "Customer.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include<utility>
using namespace std;
//default constructor
Customer::Customer() {
}
//Full constructor
Customer::Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type)
{
this->customerID = customerID;
this->title = title;
this->name = name;
this->numOfPurchases = numOfPurchases;
purchases = new int[3];
purchases[0] = purchase1;
purchases[1] = purchase2;
purchases[2] = purchase3;
this->type = type;
}
Customer::Customer(const Customer& source) //copy constructor
{
cout << "copy constructor called" << endl;
this->customerID = source.customerID;
this->title = source.title;
this->name = source.name;
this->numOfPurchases = source.numOfPurchases;
this->purchases = new int[3];
purchases[0] = source.purchases[0];
purchases[1] = source.purchases[1];
purchases[2] = source.purchases[2];
this->type = source.type;
}
//overloaded assignment operator=
Customer& Customer::operator= (Customer& otherCustomer)
{
cout << "Overloaded assignment operator= called" << endl;
//self-assignment guard
if (this == &otherCustomer)
return *this; //refernce to the same object
// copy data from the source (rhs) to this object (the destination)
name = otherCustomer.name;
//must make a new scores object to store a copy of the other student
if (purchases != nullptr)
delete[] purchases;
purchases = new int[3];
for (int i = 0; i < 3; i++) {
purchases[i] = otherCustomer.purchases[i];
}
//return this existing object so we can chain this operator
return *this;
}
string Customer::save()
{
stringstream out;
out << this->customerID << ";";
out << this->title << ";";
out << this->name << ";";
out << this->type << ";\n";
out << this->numOfPurchases << ";";
int* purchases = 0;
out.flush();
return out.str();
}
void Customer::parse(string line)
{
stringstream in(line);
string customerIDLine;
getline(in, customerIDLine, ';');
customerID = stoi(customerIDLine);
getline(in, title, ';');
getline(in, name, ';');
getline(in, type, ';');
string numOfPurchases;
getline(in, numOfPurchases, ';');
int s = stoi(numOfPurchases);
int* purchasesArray = new int[3];
purchasesArray[0] = (s & (255 << 16)) >> 16;
purchasesArray[1] = (s & (255 << 8)) >> 8;
purchasesArray[2] = s & 255;
}
void Customer::addCustomer(vector<Customer>& customers )
{
//after read data
int customerID;
cout << "Please Enter Customer ID: " << endl;
cin >> customerID;
string title;
cout << "Please Enter Title: " << endl;
getline(cin, title);
string name;
cout << "Please Enter Name: " << endl;
getline(cin, name);
string type;
cout << "Please Enter Type: " << endl;
getline(cin, type);
int numOfPurchases;
cout << "Please Enter Number of Purchases: " << endl;
cin >> numOfPurchases;
int purchase1;
cout << "Please Enter First Purchase: " << endl;
cin >> purchase1;
int purchase2;
cout << "Please Enter Second Purchase: " << endl;
cin >> purchase2;
int purchase3;
cout << "Please Enter Third Purchase: " << endl;
cin >> purchase3;
Customer c;
customers.push_back(c);
//Customer c();
}
Customer::~Customer() {
cout << "Destructor ~Customer called" << endl;
delete[] purchases;
}
// Overloaded insertion operator (Outputs Character object data as an output stream)
// Defined in header file as a "friend" function, as it is not a member function
//
ostream& operator<<(ostream& out, Customer& customer)
{
cout << "Customer details ( output by insertion operator<< )" << endl;
cout << "Customer ID: " << customer.customerID << endl;
cout << "Title: " << customer.title << endl;
cout << "Name: " << customer.name << endl;
cout << "Number of purchases: " << customer.numOfPurchases << endl;
cout << "Purchases: ";
for (int i = 0; i < 3; i++)
{
if (i > 0) cout << ",";
cout << customer.purchases[i];
}
cout << "Type: " << customer.type << endl;
return out;
}
istream& operator>> (istream& in, Customer& customer)
{
cout << "Enter Customer details ( using the extraction operator>> )" << endl;
cout << "Enter Customer ID: " << endl;
cin >> customer.customerID;
cout << "Enter Title: " << endl;
getline(cin, customer.title);
cout << "Enter Name: " << endl;
getline(cin, customer.name);
cout << "Enter Number of Purchases: ";
cin >> customer.numOfPurchases;
cout << "Enter Purchases: ";
cin >> customer.purchases[0];
cin >> customer.purchases[1];
cin >> customer.purchases[2];
cout << "Enter Type";
getline(cin, customer.type);
cout << endl;
return in;
}
int Customer::getCustomerID()
{
return customerID;
}
string Customer::getTitle()
{
return title;
}
string Customer::getName()
{
return name;
}
int Customer::getNumOfPurchases()
{
return numOfPurchases;
}
int* Customer::getPurchases()
{
return purchases;
}
string Customer::getType()
{
return type;
}
void Customer::setCustomerID(int customerID)
{
if (customerID < 1) {
cout << "Customer ID has to be equal to 1 or more" << endl; //Changed all the "throw invalid_argument" messages to cout as they were causing an issue with my main.cpp file and an abort message kept appearing every time I ran my main.cpp file.
}
this->customerID = customerID;
}
void Customer::setTitle(string title)
{
if (title.length() < 2) {
cout << "Title has to be more than or equal to 2 characters" << endl;
}
this->title = title;
}
void Customer::setName(string name)
{
if (name.length() < 4) {
cout << "Length of name should be more than or equal to 4 characters" << endl;
}
this->name = name;
}
//Got help ith this on stack overflow as I was using "&&" instead of using "||" for the if statement
void Customer::setNumOfPurchases(int numOfPurchases)
{
if(numOfPurchases <0 || numOfPurchases > 10000){
cout << "Number of purchases should be between 0 to 10000" << endl;
}
this->numOfPurchases = numOfPurchases;
}
void Customer::setPurchases(int purchase1, int purchase2, int purchase3)
{
if (purchase1 < 0 || purchase2 < 0 || purchase3 < 0) {
cout << "Purchases must be more than or equal to zero" << endl;
}
}
//Got help from stack overflow on comparing strings as I originally didnt use "type.compare"
void Customer::setType(string type) {
if (type.compare("New") !=0 || type.compare("Either") !=0) {
cout << "Type of purchase has to be New or Either" << endl;
}
}
Code from Customer.h:
#pragma once
#include<iostream>
using namespace std;
#include<string>
#include <vector>
class Customer
{
private:
int customerID;
string title;
string name;
int numOfPurchases;
int* purchases;
string type;
public:
Customer(); // default constructor
Customer(int customerID, string title, string name, int numOfPurchases, int purchase1, int purchase2, int purchase3, string type);
//copy overload assignment
Customer& operator=(Customer& otherCustomer);
Customer(const Customer& source);
string save();
void parse(string line);
void addCustomer(vector<Customer>& customers);
~Customer(); //destructor
//Getters and Setters
void setCustomerID(int customerID);
void setTitle(string title);
void setName(string name);
void setNumOfPurchases(int numOfPurchases);
void setPurchases(int purchase1, int purchase2, int purchase3);
void setType(string type);
int getCustomerID();
string getTitle();
string getName();
int getNumOfPurchases();
int* getPurchases();
string getType();
void printCustomer() {
cout << customerID << "," << title << "," << name << "," << numOfPurchases << "," << purchases << "," << type << endl;
}
friend std::ostream& operator<<(std::ostream& out, Customer& customer); // overloaded operator<<
friend istream& operator>> (istream& in, Customer& customer); // overloaded operator >>
};
Vectors hold objects. If you have an object outside of the vector there is no way to have that same object inside the vector. You can move from one instance to one in the vector (that will move the instances inner parts, but there are still two instances). push_back does make a copy of its parameter when it cannot be moved from.
As you have a constructor that takes all necessary parameters, you can use emplace_back to avoid the copy and construct the instance right in place in the vector:
customers.emplace_back( customerID, title, name, numOfPurchases, purchase1, purchase2, purchase3, type);
If you check reference on std::vector<T,Allocator>::push_back object can be added to vector either by being copied (option1) or being moved (option 2).
So you can create a move constructor for your customer class:
class_name ( class_name && );
And then call push_back using that move consturctor (option 2) on vector:
void push_back( T&& value );
The std::vector<Customer> holds the element by value so just using std::vector::push_back will copy your local object into the vector.
To mitigate this you could either implement move semantics and move the the Customer object like this:
#include <utility>
....
Customer c;
c.parse(line);
customers.push_back(std::move(c));
or construct the object in-place:
// Post c++17 you could use `push_back()` here as well as
// c++17 has mandatory copy elision.
customers.emplace_back(Customer{}); // or customers.emplace_back(); only
customers.back().parse(line);
Both solutions require c++11.
You could also store a reference/pointer and allocate the object on the heap.
std::vector<std::unique_ptr<Customer>> customerVector;
customer_vector.push_back(std::make_unique<Customer>());
// or customer_vector.push_back(std::make_shared<Customer>());
Or
std::vector<Customer*> customerVector;
// Beware for memory leaks, needs to be deleted.
// Basically never use code like this post c++11).
customer_vector.push_back(new Customer{});

Array input to one class variable c++

I need to create a class of Students where I need to store their name, surname and subjects that they have in uni. How do I need to assign different subjects to different students? User should input it from console. What my class and input should look like? Heres is the code I have so far For example: there are two students Mark Jacobs and John Johny. Mark has 3 subjects: Math, Physics, Geography and John only has 2 Math and Economy.
#include <iostream>
using namespace std;
class Student{
private:
string name;
string surname;
int courseNo;
string subjects[100];
public:
Student(string name = "empty", string surname = "empty")
{
this->name = name + surname;
}
~Student(){
}
void setFullName(string name, string surname){
this->name = name;
this->surname = surname;
}
string getFullName(){
return name + " " + surname;
}
void setSubject(string subjects[100]){
this->subjects[90] = subjects[90];
}
string getSubject(){
return subjects[90];
}
string toString() const
{
return "Studentas: " + this->name;
}
};
int main() {
int number_of_students;
int number_of_subjects = 0;
int choice;
string subjects[90];
string name;
string surname;
cout << "Enter number of students: ";
cin >> number_of_students;
Student Studentas[number_of_students];
cout << "Enter " << number_of_students << " students names and surnames: " << endl;
for (int i = 0; i < number_of_students; i++) {
cin >> name >> surname;
Studentas[i].setFullName(name, surname);
}
for (int i = 0; i < number_of_students; i++) {
cout << i+1 << " Student: " << Studentas[i].getFullName() << endl;
}
cout << "Choose which students subjects you want to enter: ";
cin >> choice;
if(choice == 1){
cout << "Enter " << Studentas[choice-1].getFullName() << " number of subjects: ";
cin >> number_of_subjects;
for (int i = 0; i < number_of_subjects; i++) {
cin >> subjects[i];
Studentas[choice-1].setSubject(subjects);
}
cout << "Studying subjects are: " << endl;
for(int i = 0; i < number_of_subjects; i++){
cout << Studentas[choice-1].getSubject() << endl;
}
}
return 0;
}
I have taken your code changed a little bit, I hope this is what you are looking for
Code:
#include <iostream>
#include <vector>
using namespace std;
class Student {
private:
string name_;
string surname_;
int courseNo_;
std::vector<string> subject_list_;
public:
Student(string name = "empty", string surname = "empty")
{
name_ = name + surname;
}
void setFullName(string name, string surname) {
name_ = name;
surname_ = surname;
}
string getFullName() {
return name_ + " " + surname_;
}
void setSubject(string subject) {
subject_list_.push_back(subject);
}
const std::vector<string>& getSubjects() {
return subject_list_;
}
string toString() const
{
return "Student as: " + name_;
}
};
int main() {
std::vector<Student> student_list;
int number_of_students;
int number_of_subjects = 0;
int choice;
string subject;
string name;
string surname;
cout << "Enter number of students: ";
cin >> number_of_students;
cout << "Enter " << number_of_students << " students names and surnames: " << endl;
for (int i = 0; i < number_of_students; i++) {
cin >> name >> surname;
student_list.push_back(Student(name, surname));
}
int i = 1;
for (auto student : student_list) {
cout << i++ << " Student: " << student.getFullName() << endl;
}
cout << "Choose which students subjects you want to enter: ";
cin >> choice;
if (choice <= number_of_students) {
choice -= 1;
cout << "Enter " << student_list[choice].getFullName() << " number of subjects: ";
cin >> number_of_subjects;
for (int i = 0; i < number_of_subjects; i++) {
cin >> subject;
student_list[choice].setSubject(subject);
}
cout << "Studying subjects are: " << endl;
const auto& subject_list = student_list[choice].getSubjects();
for (auto& subject : subject_list){
cout << subject << endl;
}
}
return 0;
}

C++ Virtual Void

Okay, so I have a parent class called employee and 3 subclass called manager,researcher and engineer. I made a vector and want to list them. this is the how I process the making.
vector <Employee*,Manager*> EmployeeDB;
Employee *temp;
temp = new Manager(first, last, salary, meetings, vacations);
EmployeeDB.push_back(temp);
I have no problem in making the vector, my concern is listing the info. all 3 subclasses have firstname, lastname and salary but they're difference is that they have different data members which is unique, example the Manager has the int value vacation and the Engineer has the int value experience so on and so forth.
Employee.h:
#include <iostream>
#include <string>
using namespace std;
#ifndef EMPLOYEE_h
#define EMPLOYEE_h
class Employee
{
public:
Employee();
Employee(string firstname, string lastname, int salary);
string getFname();
string getLname();
int getSalary();
virtual void getInfo();
private:
string mFirstName;
string mLastName;
int mSalary;
};
#endif
Employee.cpp:
#include "Employee.h"
#include <iostream>
#include <string>
using namespace std;
Employee::Employee()
{
mFirstName = "";
mLastName = "";
mSalary = 0;
}
Employee::Employee(string firstname, string lastname, int salary)
{
mFirstName = firstname;
mLastName = lastname;
mSalary = salary;
}
string Employee::getFname()
{
return mFirstName;
}
string Employee::getLname()
{
return mLastName;
}
int Employee::getSalary()
{
return mSalary;
}
void Employee::getInfo()
{
cout << "Employee First Name: " << mFirstName << endl;
cout << "Employee Last Name: " << mLastName << endl;
cout << "Employee Salary: " << mSalary << endl;
}
Main:
#include <vector>
#include <iostream>
#include <string>
#include "Employee.h"
#include "Engineer.h"
#include "Manager.h"
#include "Researcher.h"
using namespace std;
vector <Employee*> EmployeeDB;
Employee *temp;
void add()
{
int emp, salary, vacations, meetings, exp, c;
string first, last, type, school, topic;
bool skills;
do
{
system("cls");
cout << "===========================================" << endl;
cout << " Add Employee " << endl;
cout << "===========================================" << endl;
cout << "[1] Manager." << endl;
cout << "[2] Engineer." << endl;
cout << "[3] Researcher." << endl;
cout << "Input choice: ";
cin >> emp;
system("cls");
} while (emp <= 0 || emp > 3);
cout << "===========================================" << endl;
cout << " Employee Info " << endl;
cout << "===========================================" << endl;
cout << "Employee First name: ";
cin >> first;
cout << "Employee Last name: ";
cin >> last;
cout << "Employee Salary: ";
cin >> salary;
switch (emp)
{
case 1:
cout << "Employee numbers of meetings: ";
cin >> meetings;
cout << "Employee numbers of vacations: ";
cin >> vacations;
temp = new Manager(first, last, salary, meetings,vacations);
EmployeeDB.push_back(temp);
delete temp;
break;
case 2:
cout << endl;
cout << "[1]YES [2]NO" << endl;
cout << "Employee C++ Skills: ";
cin >> c;
if (c == 1)
{
skills = true;
}
else
{
skills = false;
}
cout << "Employee Years of exp: ";
cin >> exp;
cout << "(e.g., Mechanical, Electric, Software.)" << endl;
cout << "Employee Engineer type: ";
cin >> type;
temp = new Engineer(first, last, salary, skills, exp, type);
EmployeeDB.push_back(temp);
delete temp;
break;
case 3:
cout << "Employee School where he/she got his/her PhD: ";
cin >> school;
cout << "Employee Thesis Topic: ";
cin >> topic;
temp = new Researcher(first, last, salary, school, topic);
EmployeeDB.push_back(temp);
delete temp;
break;
}
}
void del()
{
}
void view()
{
for (int x = 0; x < (EmployeeDB.size()); x++)
{
cout << EmployeeDB[x]->getInfo();
}
}
void startup()
{
cout << "===========================================" << endl;
cout << " Employee Database " << endl;
cout << "===========================================" << endl;
cout << "[1] Add Employee." << endl;
cout << "[2] Delete Employee." << endl;
cout << "[3] List Employees." << endl;
cout << "[4] Exit." << endl;
cout << "Please Enter Your Choice: ";
}
int main(int argc, char** argv)
{
bool flag = true;
int choice;
do {
do
{
system("cls");
system("pause>nul");
startup();
cin >> choice;
} while (choice < 0 || choice >4);
switch (choice)
{
case 1:
add();
break;
case 2:
del();
break;
case 3:
view();
break;
case 4:
flag = false;
system("EXIT");
break;
}
} while (flag == true);
return 0;
system("pause>nul");
}
I am getting error on the view() function.
It says no operator<< matches these operands
binary '<<': no operator found which takes a right hand operand of type void etc etc.
The problem is that the getInfo has return type void and you are trying to put that return value into cout.
It's important to understand that the code std::cout << val actually calls the function operator<<(ostream& out, const objectType& val) where objectType is the type of 'val'.
In your case the type is void, and there is simply no implementation of operator<< that takes void as a type. hence the error "no operator found which takes a right hand operand of type void...".
In order to fix your issue you have a few options:
Change view() to be
for (...)
{
EmployeeDB[x]->getInfo();
}
Change getInfo() to return a string the info as you'd like:
std::string getInfo()
{
std::string info;
info =...
return info;
}
Create an operator<< for Employee and change view to call it:
view()
{
for (...)
{
std::cout << EmployeeDB[x];
}
}