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;
}
Related
So I've been learning how friendly classes work, and I created two classes, both being friendly to one another. Howewer, as soon as I write a method to modify a value in another class's field, I get a compilator error, and Visual Studio refuses to elaborate on how to fix it. Here is the code:
#include <iostream>
#include <cstring>
using namespace std;
class Human;
class Apple;
class Human
{
public:
Human();
Human(int bitepower, string& name);
void BiteApple(Apple& other)
{
other.weight -= this->bitepower;
}
void Print()
{
cout << "Имя = " << this->name << " Сила укуса = " << this->bitepower << " id = " << this->id << endl;
}
~Human();
private:
friend Apple;
int bitepower;
string name;
int id;
static int num;
};
Human::Human()
{
bitepower = 0;
num++;
id = num;
name = string("Unidentified " + id);
}
Human::Human(int test, string& name)
{
this->bitepower = test;
num++;
id = num;
this->name = name;
}
int Human::num = 0;
Human::~Human()
{
}
class Apple
{
public:
Apple();
Apple(int weight);
void Print()
{
cout << "Apple id = " << this->id << " Weight = " << this->weight << endl;
}
~Apple();
private:
friend Human;
int weight;
static int num;
int id;
};
Apple::Apple()
{
weight = 0;
num++;
id = num;
}
Apple::Apple(int weight)
{
this->weight = weight;
num++;
id = num;
}
int Apple::num = 0;
Apple::~Apple()
{
}
int main()
{
//Apple apple1(80);
//Human egor(20, "Егор");
//egor.Print();
//apple1.Print();
//egor.BiteApple(apple1);
//egor.Print();
//apple1.Print();
return 0;
}
And this is the exact method that causes everything to stop working:
void BiteApple(Apple& other)
{
other.weight -= this->bitepower;
}
After I've localised the problem, I've tried moving the announcements of the classes around, and outlining the very function to be friendly, but to no effect. I just can't seem to find the answer nowhere.
Here is the exact error I get:enter image description here
This reads as: Compilation error occured. Continue and load the last succsessfully built version?
I have also tried moving the declaration of Apple class below the declaration of Human class as suggested, but it had no effect. I would be grateful to be advised if this can be solved without creating a header file as I have not learned this yet, and if not, I'll need to learn file structure and return to friendly classes later.
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;
}
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.
I am new to OOP and I have encountered a problem while writing my first code. I do not understand why I can not use one class as a part of another. And no I do not want that class to inherit another. One of the requirements is that I prevent object copying.
#pragma once
#include<iostream>
#include<string>
using namespace std;
class Pilot
{
public:
Pilot(/*string x*/)
{
setName();
flight_hours = 0;
set_status(0);
}
void setName(/*string x*/)
{
cout<<"Unesi ime pilota: ";
getline(cin,name);
}
string getName()
{
return name;
}
void increase_flight_hours(int n)
{
flight_hours += n;
}
int get_flight_hours()
{
return flight_hours;
}
void set_status(bool b)
{
status;
}
bool get_status()
{
return status;
}
void display_pilot()
{
cout << name;
cout << "(", flight_hours, ")";
if (status)
cout << "-L" << endl;
else
cout << "-N" << endl;
}
Pilot (const Pilot&) = delete;
void operator=(const Pilot&) = delete;
private:
string name;
int flight_hours;
bool status;
};
#pragma once
#include"Pilot.h"
class Avion
{
public:
Avion ()
{
setName();
set_capacity();
}
void setName(/*string x*/)
{
cout << "Unesi ime aviona: ";
getline(cin, name);
}
string getName()
{
return name;
}
void set_capacity()
{
cout << "Unesite kapacitet aviona: ";
cin >> capacity;
}
int get_capacity()
{
return capacity;
}
Pilot get_captain()
{
return captain;
}
private:
string name;
Pilot captain;
Pilot copilot;
int capacity;
};
I get this error :
function "Pilot::Pilot(const Pilot &)" (declared at line 50 of "C:\Users\mjova\source\repos\Project1\Project1\Pilot.h") cannot be referenced -- it is a deleted function Project1 C:\Users\mjova\source\repos\Project1\Project1\Planes.h 36
One problem is here:
Pilot get_captain()
{
return captain;
}
which returns a copy of the captain, and you have expressly disallowed copying.
Return a const reference instead:
const Pilot& get_captain()
{
return captain;
}
(and don't try to copy what it returns).
There could also be some other copying-related code in "Planes.h"; it's not clear whether Avion is defined in that file or not.
Side note: since you can't copy Pilots, the captain and copilot members of Avion are problematic (you can't implement set_captain, for instance).
I suspect that you're going to want to change them to be pointers in the future, and let pilots exist without planes and vice versa.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
I don't know why but when i create an object with my class and use the default constructor, when i try to pass the variable named cash to the accessor user2.setCash(cash) which purpose is to primary set cash equal to new_cash, it gives a large value like 1.222256e+461 or something like that. Why does that happen? If i use my overload constructor it works fine.
main.cpp
#include <iostream>
#include <string>
#include "Bank.h"
using namespace std;
int main()
{
string name;
int id;
double cash;
bank user2;
cout << "\n\nPlease type your name: ";
getline(cin >> ws, name);
user2.setName(name);
cout << "Enter an id number: ";
cin >> id;
user2.setID(id);
cout << "Enter your cash: ";
cin >> cash;
cout << cash << endl;
user2.setCash(cash);
cout << "\nAlright " << user2.getName() << ", current cash: " << user2.getCash();
cout << "\nChoose how much would you like to Deposit: ";
cin >> cash;
user2.deposit(cash);
cout << "New amount is: " << user2.getCash() << " For user ID: " << user2.getID() << "\n\n";
bank::printStatic();
return 0;
}
Bank.h
#ifndef BANK_H
#define BANK_H
#include <iostream>
#include <string>
using namespace std;
class bank
{
public:
// Default Constructor
bank();
// Overload Constructor
bank(string, int, double);
// Destructor
~bank();
// Accessor Functions
string getName() const;
int getID() const;
double getCash() const;
// Mutator Functions
void setName(string);
void setID(int);
void setCash(double);
// Functions
void withdraw(double);
void deposit(double);
static void printStatic();
private:
// Member Variables
string new_name;
int new_id;
double new_cash;
// Static Member Variables
static int num_of_accounts;
static double total_cash;
};
#endif
Bank.cpp
#include "Bank.h"
// Static Variables
int bank::num_of_accounts = 0;
double bank::total_cash = 0.0;
// Default Constructor
bank::bank()
{
int new_id = 0;
double new_cash = 0.0;
++num_of_accounts; // New object is created e.g. a person so total accounts must be increased.
}
// Overload Constructor
bank::bank(string name, int id, double cash)
{
new_name = name;
new_id = id;
new_cash = cash;
++num_of_accounts; // New object is created e.g. a person so total accounts must be increased.
total_cash += new_cash; // New object is created e.g. a person so his/hers cash must be added to the total cash of the bank.
}
// Destructor
bank::~bank()
{
--num_of_accounts; // When Destructor is called to destroy an object (e.g. a person) then the id must be dropped by 1 cause the person e.g. (left).
total_cash -= new_cash; // And the balance he had to be removed so it is not counted in total cash avaliable in the bank cause he e.g. (left).
}
// Accessor Functions
string bank::getName() const
{
return new_name;
}
int bank::getID() const
{
return new_id;
}
double bank::getCash() const
{
return new_cash;
}
// Mutator Functions
void bank::setName(string name)
{
new_name = name;
}
void bank::setID(int id)
{
new_id = id;
}
void bank::setCash(double cash)
{
cout << new_cash << endl;
total_cash -= new_cash; // We must remove his prior cash which we holded in the total so we can then use the new value suplied.
new_cash = cash;
total_cash += new_cash; // Here we add the new cash (balance) he/she has.
}
void bank::withdraw(double cash)
{
new_cash -= cash;
total_cash -= cash;
}
void bank::deposit(double cash)
{
new_cash += cash;
total_cash += cash;
}
void bank::printStatic()
{
cout << "Total users are: " << num_of_accounts << endl;
cout << "Total cash in bank is: " << total_cash << endl;
}
You need to initialize all primitive type members in the constructor.
Otherwise you get indeterminate values
Also, the non-default constructor is buggy:
// Default Constructor
bank::bank()
{
int new_id = 0;
double new_cash = 0.0;
....
^ sets values of local variables, not the member variables
I'd suggest to use the initilization lists:
// Default Constructor
bank::bank() : new_name(), new_id(0), new_cash(0.0)
{
++num_of_accounts;
}
// Overload Constructor
bank::bank(string name, int id, double cash)
: new_name(name), new_id(id), new_cash(cash)
{
++num_of_accounts;
total_cash += new_cash;
}
You could also combine the two:
bank::bank(string name = "", int id = 0, double cash = 0.0)
: new_name(name), new_id(id), new_cash(cash)
{
++num_of_accounts;
total_cash += new_cash;
}
In your default constructor, you're declaring local variables with the same names as the member variables. Then you're setting these local variables instead of assigning the members. Get rid of the type declarations so they're normal assignments.
bank::bank()
{
new_id = 0;
new_cash = 0.0;
++num_of_accounts; // New object is created e.g. a person so total accounts must be increased.
}