How Do I Deal With This C++ Multimap Issue? - c++

I am a beginner in C++ working on simple program and I ran into an issue which left me stumped... Basically I created a multimap that accepts a part of string person name and a pointer to a person object.
So My first function to work with was the "Add()" function. I basically construct a new person with a name and age and then set a pointer to that object. Then I insert the name and the object into the multimap as a pair.
The problem happens when I run the find() function... My output only gives me a valid name but for the age I get what seems like a truncated memory address or a random number? Since i'm a beginner I am pretty sure I am doing something very simple yet very stupid. I don't think you will need to run the code since it's so simple. All help is appreciated. Thank you!
My runnable file:
#include "Person.h"
#include <map>
using namespace std;
multimap<string, Person*> personMap;
multimap<string, Person*>::iterator counter;
void add()
{
string name;
int age;
cout << "Please enter the name of the person: ", cin >> name;
cout << "Please enter the age of the person: ", cin >> age;
Person generatedPerson(name, age);
// Avoid dynamic class pointers for memory optimization.
// Avoided: Person* pointer = new Person(name, age).
Person *pointer = &generatedPerson;
personMap.insert({name, pointer});
}
void find()
{
string personToBeFound;
cout << "Who do you wish to find, friend: ", cin >> personToBeFound;
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->first == personToBeFound)
{
cout << "\nName: " << counter->first << " Age: " << counter->second->getAge() << endl;
}
else if (counter->first != personToBeFound)
{
cout << "Error 404, person does not exist..." << endl;
}
}
}
// Experimental....
int main(int argc, char* argv[])
{
int menuChoice = -1;
while (menuChoice != 0)
{
cout << "\nPlease enter: "
"\n1 - to add a person "
"\n2 - to find a person"
"\n0 - to quit\n" << endl;
cin >> menuChoice;
switch(menuChoice)
{
case 1: add();
break;
case 2: find();
break;
case 0: menuChoice = 0;
}
}
}
HEADER FILE:
#ifndef PERSON_H
#define PERSON_H
#include <string>
#include <vector>
#include <iostream>
class Person {
public:
// Constructors
/**
* Create a Person with the given name and age.
*
* #param name name of the person
* #param age age of the person - defaults to 0
*/
Person(const std::string& name, unsigned short age = 0);
// No explicit destructor necessary
// Mutators
/**
* Set the name attribute
*
* #param name name of the person
*/
void setName(const std::string& name);
/**
* Set the age attribute
*
* #param age age of the person
*/
void setAge(unsigned short age);
/**
* Increment the age attribute
*/
void growOlder();
/**
* Add a person to our list of children
*
* #param child Person to add as a child
*/
void addChild(const Person& child);
// Accessors
/**
* #return the Person's name
*/
const std::string& getName() const;
/**
* #return the Person's age
*/
unsigned short getAge() const;
/**
* #return a list of this Person's children
*/
const std::vector<const Person *>& getChildren() const;
/**
* Define the ostream's << operator as a friend of this class
* to allow this object to be printed to an output stream
*
* #param output the stream to print to
* #param p the Person to print
*
* #return the output stream printed to
*/
friend std::ostream& operator<< (std::ostream& output, const Person& p);
private:
// 0-arg Constructor
Person();
// Private attributes
std::string _name;
unsigned short _age;
std::vector<const Person *> _children;
}; // Person
#endif
METHOD DEFINITIONS:
#include "Person.h"
Person::Person(const std::string& name, unsigned short age) :
_name(name) , _age(age) {
}
void Person::setName(const std::string& name) {
_name = name;
}
void Person::setAge(unsigned short age) {
_age = age;
}
void Person::growOlder() {
_age++;
}
void Person::addChild(const Person& child) {
_children.push_back(&child);
}
const std::string& Person::getName() const {
return _name;
}
unsigned short Person::getAge() const {
return _age;
}
const std::vector<const Person *>& Person::getChildren() const {
return _children;
}
std::ostream& operator<< (std::ostream& output, const Person& aPerson) {
// Print our attributes to the output stream
return output << "Name: '" << aPerson._name << "', Age: " << aPerson._age;
}

Hi the comment of #1201ProgramAlarm is absolutely right, however, I thought by myself, how would I go about "rescuing" the program (a) with minimal effort, (b) to get a correct version and (c) very much in terms of the original version.
So here's a new main.cc version (Person.h, Person.cc needn't be changed):
#include "Person.h"
#include <map>
using namespace std;
multimap <string, Person *> personMap;
multimap <string, Person *>::iterator counter;
void add()
{
string name;
int age;
cout << "Please enter the name of the person: ", cin >> name;
cout << "Please enter the age of the person: ", cin >> age;
personMap.insert({ name, new Person(name, age) });
}
void find()
{
string personToBeFound;
cout << "Who do you wish to find, friend: ", cin >> personToBeFound;
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->first == personToBeFound)
{
cout << "\nName: " << counter->first
<< " Age: " << counter->second->getAge() << endl;
}
else
{
cout << "Error 404, person does not exist..." << endl;
}
}
}
int main(int argc, char* argv[])
{
int menuChoice = -1;
while (menuChoice != 0)
{
cout << "\nPlease enter: "
"\n1 - to add a person "
"\n2 - to find a person"
"\n0 - to quit\n" << endl;
cin >> menuChoice;
switch(menuChoice)
{
case 1:
add();
break;
case 2:
find();
break;
case 0:
menuChoice = 0;
break;
}
}
// -- How to go about clearing the heap? --
for (counter = personMap.begin(); counter != personMap.end(); counter++)
{
if (counter->second) {
delete counter->second;
counter->second = nullptr;
}
}
}
I compiled using g++ -o main Person.cc main.cc. Regards, M.
Update after this question:
Why shouldn't I just delete the keys instead of just the values of the multimap <string, Person *> entries?
Answer:
I just wanted to show what could be done to prevent orphaned Person objects on the heap when the multimap went out of (local) scope and would thus be destroyed automatically by the C++ system. More specifically:
(a) As in C, what is malloc-ed needs to be free-ed again later, the equivalent is true in C++: what is new-ed needs to be delete-ed later. This is best practice to prevent memory leaks in the long run.
(b) Now, back to our multimap <string, Person *>. Here, the keys are strings and the values are pointers to Person objects. These Person pointers are the only way left to get a hold on the corresponding Person objects allocated on the heap in calls to the add() function.
(c) In our case, the whole program is going to stop anyway after the multimap gets destroyed automatically, so delete-ing the Person objects using that extra for-loop isn't as important here, because Person objects remaining on the heap are garbage-collected by the operating system after the corresponding process has terminated, anyway.

Related

Program won't return count of names matching search

Hi I need some help on this C++ lab.
I need to get user input for names and then search for names matching that input. I can't seems to figure out the issue in my code. I feel like it is somewhere between these lines
Person searchPerson(searchLastName, searchFirstName, 0);
Person* sPerson = &searchPerson;
// get count of such persons
int cntPersons = persSet.count(sPerson);
cout << "Number of people with this name= " << cntPersons;
I need to output the names matching the inputted names by the user but it keeps returning 0. I need some fresh eyes on this because I feel like it is a simple fix that I just can't see. Full code posted below
#pragma warning (disable:4786) // for set (Microsoft only)
#include <iostream>
#include <set>
#include <iterator>
#include <string>
#include <functional>
using namespace std;
class Person
{
private:
string lastN, firstN;
long phoneNum;
public:
Person()
{
lastN = "blank";
firstN = "blank";
phoneNum = 0;
}
Person(string lastName, string firstName, long number)
{
lastN = lastName;
firstN = firstName;
phoneNum = number;
}
//operator == for person class
friend bool operator==(const Person& p1, const Person& p2)
{
return (p1.lastN == p2.lastN &&
p1.firstN == p2.firstN) ? true : false;
}
friend bool operator<(const Person& p1, const Person& p2)
{
if (p1.lastN == p2.lastN)
return (p1.firstN < p2.firstN) ? true : false;
return (p1.lastN < p2.lastN) ? true : false;
}
void display() const //display person's data
{
cout << endl << lastN << ",\t" << firstN;
cout << "\t\tPhone: " << phoneNum;
}
};
int main()
{
string searchLastName, searchFirstName;
Person* ptrP1 = new Person("KuangThu", "Bruce", 4157300);
Person* ptrP2 = new Person("Deauville", "William", 8435150);
Person* ptrP3 = new Person("Wellington", "John", 9207404);
Person* ptrP4 = new Person("Bartoski", "Peter", 6946473);
Person* ptrP5 = new Person("Fredericks", "Roger", 7049982);
Person* ptrP6 = new Person("McDonald", "Stacey", 7764987);
Person* ptrP7 = new Person("KuangThu", "Bruce", 4157300);
Person* ptrP8 = new Person("Deauville", "William", 8435150);
// multiset of persons
multiset<Person*, less<Person*> > persSet;
// iterator to a multiset of persons
multiset<Person*, less<Person*> >::iterator iter;
persSet.insert(ptrP1); // put persons in multiset
persSet.insert(ptrP2);
persSet.insert(ptrP3);
persSet.insert(ptrP4);
persSet.insert(ptrP5);
persSet.insert(ptrP6);
persSet.insert(ptrP7);
persSet.insert(ptrP8);
cout << "Number of Entries= " << persSet.size();
iter=persSet.begin(); //display contents of multiset
while (iter != persSet.end())
{
(*iter++)->display();
}
cout << endl<<"Enter the last name of person to search for: ";
cin >> searchLastName;
cout << endl<<"Enter their first name: ";
cin >> searchFirstName;
//creating a search for a person with this name
Person searchPerson(searchLastName, searchFirstName, 0);
Person* sPerson = &searchPerson;
// get count of such persons
int cntPersons = persSet.count(sPerson);
cout << "Number of people with this name= " << cntPersons;
//output all the matches to the name
iter = persSet.lower_bound(sPerson);
while (iter != persSet.upper_bound(sPerson))
{
(*iter++)->display();
}
cout << endl;
return 0;
}

Why is my derived class showing as abstract?

Getting an error that says
..\src\CS20 Lab 2 Part 2.cpp:75:38: error: invalid new-expression of abstract class type 'CS_Student'
Base Class:
/*
* Student.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
enter code here
#ifndef STUDENT_H_`#define STUDENT_H_
#include <string>
using namespace std;
class Student {
protected:
string *name;
int *age;
public:
Student();
void setName(string s) ;
void setAge(int i);
string getName() const;
int getAge() const;
virtual void print() = 0;
virtual ~Student();
};
#endif /* STUDENT_H_ */
Student.cpp:
/*
* Student.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
#ifndef STUDENT_H_
#define STUDENT_H_
#include <string>
using namespace std;
class Student {
protected:
string *name;
int *age;
public:
Student();
void setName(string s) ;
void setAge(int i);
string getName() const;
int getAge() const;
virtual void print() = 0;
virtual ~Student();
};
#endif /* STUDENT_H_ */
Derived Class:
/*
* CSStudent.cpp
*
* Created on: Jan 23, 2020
* Author: Student
*/
#include <string>
#include <iostream>
#include "CS_Student.h"
#include "Student.h"
using namespace std;
CS_Student::CS_Student() {
favProgLang = new string;
cout << "CS_Student object created!" << endl;
}
void CS_Student::setFavProgLang(string s){
*favProgLang = s;
}
string CS_Student::getFavProgLang() const{
return *favProgLang;
}
void CS_Student::print() const{
cout << "\nPRINT REPORT FOR CS_STUDENT OBJECT" << endl;
cout << "\tName: " << *name << endl;
cout << "\tAge: " << *age << endl;
cout << "\tFavorite Programming Language: " << *favProgLang << endl;
}
CS_Student::~CS_Student() {
delete favProgLang;
cout << "CS_Student object destroyed!" << endl;
}
/*
void setFavProgLang(string s);
string getFavProgLang() const;
void print() const;
*/
Derived header:
/*
* CSStudent.h
*
* Created on: Jan 23, 2020
* Author: Student
*/
#ifndef CS_STUDENT_H_
#define CS_STUDENT_H_
#include <string>
#include "Student.h"
#include <iostream>
using namespace std;
class CS_Student: public Student {
private:
string *favProgLang;
public:
CS_Student();
void setFavProgLang(string s);
string getFavProgLang() const;
void print() const;
virtual ~CS_Student();
};
#endif /* CS_STUDENT_H_ */
Main:
#include "CS_Student.h"
#include "EnglishStudent.h"
/*******************************************************************************
* Function Prototypes
*******************************************************************************/
#include <iostream>
#include <string>
using namespace std;
void getInput(CS_Student**, const int);
void getInput(EnglishStudent**, const int);
void display(Student*);
/*******************************************************************************
* int main()
* Starting point of the program.
*
* Output:
* An integer to signal to the OS the exit code.
*******************************************************************************/
int main() {
// variables
const int CS_SIZE = 2;
const int ENG_SIZE = 3;
CS_Student* csArray[CS_SIZE];
EnglishStudent* engArray[ENG_SIZE];
// call the getInput method overloads for both arrays
getInput(csArray, CS_SIZE);
getInput(engArray, ENG_SIZE);
// call the polymorphic display function for both arrays
for (int i = 0; i < CS_SIZE; i++) {
display(csArray[i]);
}
for (int i = 0; i < ENG_SIZE; i++) {
display(engArray[i]);
}
// release the dynamic memory for objects inside both arrays
for (int i = 0; i < CS_SIZE; i++) {
delete csArray[i];
}
for (int i = 0; i < ENG_SIZE; i++) {
delete engArray[i];
}
// terminate
return 0;
}
/*******************************************************************************
* void getInput(CS_Student** objArray, const int SIZE)
* Use a for loop to create dynamic CS student objects. Prompt the user for the
* name/age/favorite programming language of each CS student. Store the
* information in the dynamic object.
*
* Inputs:
* objArray - a double-pointer that should be treated as an array of dynamic
* CS student objects
* SIZE - a constant integer that represents the size of the array
*******************************************************************************/
void getInput(CS_Student** objArray, const int SIZE) {
// variables
string name = "", fpl = "";
int age = 0;
// for each CS student
for (int i = 0; i < SIZE; i++) {
// create the dynamic CS student object
objArray[i] = new CS_Student();
// prompt and store the name of the current CS student
cout << "Enter the name for CS student #" << i + 1 << ": ";
getline(cin, name);
// prompt and store for the age of the current CS student
cout << "Enter the age for CS student #" << i + 1 << ": ";
cin >> age;
// need to ignore the newline in the buffer
cin.ignore();
// prompt and store the favorite programming language of the current
// CS student
cout << "Enter the favorite programming language for CS student #"
<< i + 1 << ": ";
getline(cin, fpl);
// add the data to the dynamic object
objArray[i]->setName(name);
objArray[i]->setAge(age);
objArray[i]->setFavProgLang(fpl);
}
}
/*******************************************************************************
* void getInput(EnglishStudent** objArray, const int SIZE)
* Use a for loop to create dynamic English student objects. Prompt the user
* for the name/age/favorite book of each English student. Store the
* information in the dynamic object.
*
* Inputs:
* objArray - a double-pointer that should be treated as an array of dynamic
* English student objects
* SIZE - a constant integer that represents the size of the array
*******************************************************************************/
void getInput(EnglishStudent** objArray, const int SIZE) {
// variables
string name = "", book = "";
int age = 0;
// for each English student
for (int i = 0; i < SIZE; i++) {
// create the dynamic English student object
objArray[i] = new EnglishStudent();
// prompt and store the name of the current English student
cout << "Enter the name for English student #" << i + 1 << ": ";
getline(cin, name);
// prompt and store for the age of the current English student
cout << "Enter the age for English student #" << i + 1 << ": ";
cin >> age;
// need to ignore the newline in the buffer
cin.ignore();
// prompt and store the favorite book of the current English student
cout << "Enter the favorite book for English student #"
<< i + 1 << ": ";
getline(cin, book);
// add the data to the dynamic object
objArray[i]->setName(name);
objArray[i]->setAge(age);
objArray[i]->setFavBook(book);
}
}
/*******************************************************************************
* void display(Student* obj)
* A polymorphic function. Simply calls the (virtual) print method. Used to
* demonstrate polymorphism. Any derived class that inherits from the Student
* class can be used as an argument.
*
* Input:
* obj - a pointer to an object that inherits from the Student class
*******************************************************************************/
void display(Student* obj) {
obj->print();
}
Really confused because Student is my base class which has the pure virtual function
virtual void print() = 0;
and it's overridden in CS_Student
void CS_Student::print() const
I've also tried changing CS_Student here to Student and it doesn't change anything. Thanks in advance
Base: virtual void print() = 0;
Derived: void print() const;
That extra const in the derived version changes the signature of the derived function, the instance variable this is const, so that it doesn't match the base function. Either the base must be const or the derived must not be const. Prefer the former.
Eg.
virtual void print() = 0;
becomes
virtual void print() const= 0;
In C++ and more recent standard revisions you can catch this more easily by marking all functions you expect to override a base class function with the override keyword. This almost always results in a more easily understood error message.
Eg.
void print() const override;
results in (on my tool chain)
error: 'void CS_Student::print() const' marked 'override', but does not override
void print() const override;

Why is my elements in my vector of objects not updating upon calling one of the objects member function?

I have been trying to do debug this for a long time using visual studio debugger but I can't figure out why my function emp.setHoursWorked(hWorked); in recordHoursWorkedForEmployee only seems to be update numOfHoursWorked while in recordHoursWorkedForEmployee, as soon the program exits the function the numOfHoursWorked of all Employees in the vector go back to 0. Below is the code in question. Any help would be appreciated.
#ifndef PAYROLLSYSTEM
#define PAYROLLSYSTEM
#include "Employee.h"
#include "Paycheck.h"
#include <string>
#include <vector>
using namespace std;
class PayRollSystem
{
public:
//custom constructor gets company name
PayRollSystem(string);
void createEmployee(string, string,string, double);
void removeEmployee(string);
void recordHoursWorkedForEmployee(string);
void issuePaychecks();
private:
string companyName;
vector<Employee> companyEmployees;
};
#endif
void PayRollSystem::createEmployee(string empId, string fName, string lName, double hWage)
{
Employee temEmp = Employee(empId, fName, lName, hWage);
companyEmployees.push_back(temEmp);
}
void PayRollSystem::recordHoursWorkedForEmployee(string empId)
{
for (Employee emp : companyEmployees)
{
if (emp.getEmployeeId() == empId)
{
int hWorked = 0;
cout << "What are the hours the worked for " + emp.getEmployeeId() + " during current pay period?" << endl;
cin >> hWorked;
//TODO: For some reason this line is not updating the hours worked. Must fix!
emp.setHoursWorked(hWorked);
cout << "Hours for " + emp.getEmployeeId() + " have been changed to " << emp.getHoursWorked() << endl;
}
}
}
I excluded the header file here in order to not paste too many things not relevant to the problem i'm facing, only implementations of member functions relevant to the problem provided
//Overloaded constructor to be used with PayRollSystem
Employee::Employee(string empId, string fName, string lName, double hWage)
{
employeeId = empId;
firstName = fName;
lastName = lName;
hourlyWage = hWage;
numOfHoursWorked = 0;
}
void Employee::setHoursWorked(int hWorked)
{
if (hWorked >= 0)
numOfHoursWorked = hWorked;
else
{
cout << "Invalid number of hours worked." << endl;
exit(EXIT_FAILURE);
}
}
string Employee::getEmployeeId() const
{
return employeeId;
}
This line makes a copy of each employee:
for (Employee emp : companyEmployees)
The variable emp is a copy of the object in the container. So if you update this you are only updating the copy. Each iteration you get a new value copied into emp but any changes are not reflected in the original object.
You probably meant:
for (Employee& emp : companyEmployees)
^^^
Here emp is a reference to the object inside the vector. If you modify this you are modifying the original value inside the vector.

Using pointers from one class of an array to another class of an array

The goal of my program is to allow the user to enter up to 100 names for people and 100 names for cars. Then the user can "register" a car to as many people as s/he wishes by having those people point to that car.
I guess my first question would be, what's the best way to take a user's input string and place it into the array? Then what would be the best way to use a register function so that the user-specified person points to a specific car? Any help is much much appreciated!
(Vectors are not allowed for this assignment)
class Person{
public:
Person();
void Register(Car& theirCar);
private:
string personName;
};
class Car{
public:
Car();
private:
string carName;
};
Person::Person()
{
//Set to null
}
Car::Car()
{
//Set to null
}
int main()
{
Car cars[101];
Person persons[101];
char selection;
while(1)
{
cout << "Currently looking at:\n";
cout << "Person: " << endl;
cout << "In car: " << endl;
cout << "Do you want to (p) make a new person, (c) make a new car,\n";
cout << "(f) find a person, (r) register a person to a car, or (q) quit\n";
cin >> selection;
if(selection == 'p')
{
cout << "What is this person's name?\n";
}
if(selection == 'c')
{
cout << "What is this car's name?\n";
}
if(selection == 'f')
{
cout << "Which person do you want to find?\n";
}
if(selection == 'r')
{
cout << "Which car do you wish to register to this person?\n";
}
if(selection == 'q')
{
return(0);
}
}
}
This is not a complete answer, but based on the discussion in the comments is a place to start. It attempts to provide a relatiely minimal (but complete) example of how an instance of an object may store a pointer to another object.
#include <string>
class Car {
public:
Car(std::string name) : name(name) {}
private:
std::string name {};
};
class Person {
public:
Person(std::string name) : name(name) {}
void registerCar(Car* car) {
this->car = car;
}
private:
Car* car {nullptr};
std::string name {};
};
int main() {
// Create a car and a person
Car jaguar("Jaguar");
Person mrJagger("Mr. Jagger");
// Associate the jaguar with the person by taking its address and
// passing that to a Person object's registerCar method.
mrJagger.registerCar(&jaguar);
return 0;
}

Pointers to class fields

My task is as follows :
Using pointers to class fields, create menu allowing selection of ice, that Person can buy in Ice shop. Buyer will be charged with waffel and ice costs.
Selection of ice and charging buyers account must be shown in program.
Here's my Person class :
#include <iostream>
using namespace std;
class Iceshop {
const double waffel_price = 1;
public:
}
class Person {
static int NUMBER;
char* name;
int age;
const int number;
double plus, minus;
public:
class Account {
int number;
double resources;
public:
Account(int number, double resources)
: number(number), resources(resources)
{}
}
Person(const char* n, int age)
: name(strcpy(new char[strlen(n)+1],n)),
number(++NUMBER), plus(0), minus(0), age(age)
{}
Person::~Person(){
cout << "Destroying resources" << endl;
delete [] name;
}
friend void show(Person &p);
int* take_age(){
return &age;
}
char* take_name(){
return name;
}
void init(char* n, int a) {
name = n;
age = a;
}
Person& remittance(double d) { plus += d; return *this; }
Person& paycheck(double d) { minus += d; return *this; }
Account* getAccount();
};
int Person::
Person::Account* Person::getAccount() {
return new Account(number, plus - minus);
}
void Person::Account::remittance(double d){
resources = resources + d;
}
void Person::Account::paycheck(double d){
resources = resources - d;
}
void show(Person *p){
cout << "Name: " << p->take_name() << "," << "age: " << p->take_age() << endl;
}
int main(void) {
Person *p = new Person;
p->init("Mary", 25);
show(p);
p->remittance(100);
system("PAUSE");
return 0;
}
How to change this into using pointers to fields ?
class Iceshop {
const double waffel_price;
int menu_options;
double[] menu_prices;
char* menu_names;
char* name;
public:
IceShop(char*c)
: name(strcpy(new char[strlen(n)+1],n)),
waffel_price(1), menu(0)
{}
void init(int[] n){
menu_options = n;
}
void showMenu(Iceshop &i){
int list;
list = &i
char* sorts = i->menu_names;
int count=0;
while(count < list){
cout << count+1 << ")" << sorts[count] << endl;
++count;
}
}
void createMenu(Iceshop *i){
for(int j=0; j <(i->menu_options), ++j){
cout << "Ice name: ";
cin >> i->menu_names[j];
endl;
cout << "Ice cost: "
cin >> i->menu_prices[j];
endl;
}
}
void chargeClient(Person *p, Iceshop* i, int sel){
p->remittance( (i->menu_prices[sel])+(i->waffel_price) );
}
};
You could try to build a menu driven UI.
Something like this (copy paste from a forum, for more examples search for 'C++ console' menu' or something like it on google.
int choice = 0;
while (choice != 4)
{
cout <<"Enter choice:"<< endl <<
"1) ice 1" << endl <<
"2) ice 2" << endl<<
"3) ice 3" << endl <<
"4) exit" << endl;
cin >> choice;
switch(choice)
{
case 1:
//show menu to buy or cancel
break;
case 2:
//show menu to buy or cancel
break;
}
//etc
}
Here is what I would do. Note that it's not exactly what you're looking for and, well, abstract situation modelling is always tough :)
But I hope this code would make you understand what you have to do.
Also, I am not exactly sure about using pointers to class fields, because this tends to be a situation where pointer usage is superflous.
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
// Some abstract type used to measure prices
typedef size_t money_t;
struct Item {
// Item's name and price
std::string name;
money_t price;
// Could also have something that makes
// it an item, but this is not necessary
// This could be anything, because we're actually
// modelling an abstract situation
// (...)
// Note that we don't allow unnamed items
Item(const std::string& name, const money_t& price = 0) : name(name), price(price) { }
// Note here that items are treated as 'same' only by names
// This means we're actually talking about 'logical groups' of items
bool operator==(const Item& item) const { return name == item.name; }
bool operator==(const std::string& item_name) const { return name == item_name; }
};
class Store {
private:
// Store's item storage
// Note that items actually represent infinite groups
// of items (in our case store is an abstract store
// which items simply can't end)
std::vector<Item> items;
public:
// Initialize a store that doesn't sell anything
Store() { }
// Initialize a store that could sell specified types of items
Store(const std::vector<Item>& items) : items(items) { }
// Show what we actually sell in this store
void EnumerateItems() const {
for (size_t i = 0; i < items.size(); ++i)
std::cout << items[i].name << " : " << items[i].price << "\n";
}
Item Sell(const std::string& name) const {
// Find appropriate item in the item list
std::vector<Item>::const_iterator what = std::find(items.begin(), items.end(), name);
// If nothing found, throw an exception
if (what == items.end()) {
throw std::domain_error("Store doesn't sell this type of item");
}
// Return item as a sold one
return (*what);
}
};
class Person {
private:
// Person's name (identity)
std::string name;
// Item's that are currently possesed
// by this person
std::vector<Item> owned_items;
// Amount of cash that this person has
money_t cash;
public:
// Note that we don't allow unnamed persons
Person(const std::string& name, const money_t& cash = 0) : name(name), cash(cash) { }
void Buy(const Item& what) {
owned_items.push_back(what);
cash -= what.price;
}
};
void GoShopping(Person& person, const Store& store) {
// Let's simulate buying one item
// You could easily make a loop and determine what to buy in
// every loop iteration
store.EnumerateItems();
person.Buy(store.Sell("Shoes"));
}
int main() {
// Initialize our store that sells only shoes
std::vector<Item> items;
items.push_back(Item("Shoes", 25));
Store grocery(items);
// Initialize our person
Person jim_carrey("Jim Carrey", 500);
// The yummy part
GoShopping(jim_carrey, grocery);
return 0;
}