Exception handling trouble, why? - c++

Here is my main:
int main() {
Inventory Master;
bool flag;
Customer Bob("Bob", "CreditCard.txt");
Customer Joe("Joe", "CreditCard.txt" );
Master.firststock( "inventory.txt" );
vector<Food> temp = Master._Inv;
cout <<"Hi, What would you like to buy today?" << endl;
for(unsigned int i=0; i<temp.size(); i++ ) {
cout << temp[i].name << " " << temp[i].quant << " " << temp[i].price << endl;
}
cout <<"\n";
Food Apple("Apples", .99, 10);
Food Orange("Oranges", .99, 10);
Food Chip("Chips", 3.00, 10);
cout <<"\nHi Bob" << endl;
flag = Bob.addCart(Apple, 7, &Master);
cout <<"Bob's total purchases are Currently: \n";
Bob.report();
flag = Bob.addCart(Orange, 2, &Master);
flag = Bob.addCart(Chip, 2, &Master);
Bob.report();
flag = Bob.removeCart();
Bob.report();
cout <<"Bob, ";
flag = Bob.checkout(&Master);
here is the following i implemented to remove food from my vector _Cart:
bool Customer::removeCart() {
bool flag;
int q = 0;
unsigned int i=0;
string remove;
cout << "\nWhat would you like to remove and how much would you like to remove?" << endl;
cin >> remove >> q;
for (i =0; i < _Cart.size(); i++) {
if(remove == _Cart[i].name) {
if (q >= 0) {
_Cart[i].quant -= q;
//inv->_Inv[i].quant += q;
cout <<"\nYou removed " << q << " " << remove <<" In your cart\n" << endl;
return true;
}
if (q < 0) {
cout << "Invalid number of " << remove << " being removed.\n" << endl;
return true;
}
}
else {
try {
throw remove;
}
catch (string param) {
cout << "\n" << remove << " doesn't exist in your cart\n" << endl;
}
return true;
}
}
My header containing the the function removeCart:
class Customer {
public:
Customer(string n, string fileName);
~Customer() { _Cart.clear(); };
bool addCart(Food f, int q, Inventory* inv);
bool removeCart();
void report();
bool checkout(Inventory* inv);
protected:
string remove;
string name;
int q;
int card;
double balance;
CreditCard _CC(int card,double balance);
vector<Food> _Cart;
};
Now for some reason when i call removeCart, entering "Apples" works but i noticed i made a food object called Apple so not sure why typing "Apples" works for being removed instead of "Apple". Also when i try "Orange" or "Chip" the exception is shown but as you can see in main i added Chip and Orange to Bob's Cart. I could appreciate the help.

You are making an object called Apple containing a member of type std::string which holds characters "Apples". Only your compiler knows that you called an object Apple but your program compare string "Apples" with your input. Same with Orange and Chip.

You've declared an object called Apple somewhere in your code.
You've then instantiated an instance of an Apple class and set the Apple::name member to 'Apples', a string.
You're not comparing the input with the class name, you're comparing the input with the member data of the Apple class.

Related

vector pointers and retrieving data

I'm a beginner at coding in C++ and every other language. The problem I'm having here is in main() with the first (else if) where (UserInput == sell). I would like the function to print the data stored in the object #listPos to retrieve the cost and input it into my incomplete Profit() function, but every time I dereference the pointer (Search) I get an error code. There's something I'm missing big time please help!!
Ive already tried (*search) but there's a huge error code.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class UnSold{
public:
UnSold(string NameOfShoe, int PurchasePrice ){
name = NameOfShoe;
cost = PurchasePrice;
return;
}
void SetName(string NameOfShoe){
name = NameOfShoe;
return;
}
void SetCost(int PurchasePrice){
cost = PurchasePrice;
return;
}
string GetName() const {
return name;
}
int GetCost() const{
return cost;
}
void Profit();
void PrintItem();
private:
string name;
int cost;
};
void UnSold::Profit(){
static int profit = 0;
//profit += (sold-cost);
}
void UnSold::PrintItem(){
cout << "Name: " << this->name << " Cost: " << this->cost << endl;
}
void PrintEverything(vector<UnSold*> AllItems) {
unsigned int i;
for (i=0; i<AllItems.size(); ++i) {
cout<< i+1 << " ";
(*AllItems.at(i)).PrintItem();
}
}
int main(){
vector<UnSold*> Inventory;
string Name;
int Cost;
string UserInput;
unsigned int listPos;
UnSold* newItem = nullptr;
UnSold* search = nullptr;
while ( UserInput != "quit") {
cout << "Do you want to add, sell, print or quit?" <<endl;
cin >> UserInput;
if ( UserInput == "add") {
cout << "Enter item name: "<<endl;
cin >> Name;
cout << "Enter item cost: " << endl;
cin >> Cost;
newItem = new UnSold(Name, Cost);
Inventory.push_back(newItem);
}
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
}
else{
cout << "Error"<<endl;
}
}
else if ( UserInput == "print") {
PrintEverything(Inventory);
}
else if ( UserInput != "quit"){
}
}
return 0;
}
This is a compile error.
Remove line 85: newItem.at(listPos - 1); and it runs just fine in visual studio.
The issue is that newItem is a pointer to an element. I assume you meant to use Inventory here instead. However, that logic was already done on the previous line.
On a side note, I stongly advise against storing owning pointers like this. There's no good reason in this case not to just use vector<UnSold> instead.
else if ( UserInput == "sell") {
cout << "List Positon: ";
cin >> listPos;
if ( listPos < Inventory.size()){
cout << " Item Sold and Removed from list position " << listPos <<endl;
search = Inventory.at(listPos-1);
//cout<< "contents of Search: "<< search << endl;
delete search;
Inventory.erase(Inventory.begin() + (listPos -1));
Here you mix the use of listPos and listPos - 1.
If you're allowing the user to input position 0 indexed, then
Inventory.at(listPos-1) should be Inventory.at(listPos) and
Inventory.erase(Inventory.begin() + (listPos -1)) should be Inventory.erase(Inventory.begin() + (listPos)).
If you're letting them input the position with the indexing starting at 1, then
if (listPos < Inventory.size()) should be
if(listPos <= Inventory.size() && listPos > 0)

How to allow user input in objects and classes?

Consider the following code:
#include <iostream>
using namespace std;
class inventory
{
public:
~inventory()
{
cout << "This Object is being destroyed" << endl;
}
inventory()
{
itemNumber = 0;
quantity= 0;
cost= 0;
}
inventory(int itemNumber1, int quantity1, double cost1)
{
setItemNumber(itemNumber1);
setQuantity(quantity1);
setCost(cost1);
}
void setItemNumber(int itemNumber2)
{
itemNumber=itemNumber2;
}
bool setQuantity(int quantity2)
{
bool userTrue = true;
bool userFalse = false;
if (quantity2 < 0)
{
quantity = 0;
return userFalse;
}
else
{
quantity= quantity2;
return userTrue;
}
}
bool setCost(double cost2)
{
bool userTrue = true;
bool userFalse = false;
if (cost2 < 0.0)
{
cost = 0.0;
return userFalse;
}
else
{
cost= cost2;
return userTrue;
}
}
double getTotalCost(int quantity, double cost)
{
int total;
total = (quantity * cost);
return total;
}
private:
int itemNumber;
int quantity;
double cost;
};
int main()
{
int itemNumberInput;
int quantityInput;
double costInput;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput;
cout << "Enter the Cost : " << endl;
cin >> costInput;
inventory *pointerA, *pointerB;
pointerA = new inventory;
pointerB = new inventory(inventory(itemNumberInput , quantityInput , costInput));
inventory firstObject(itemNumberInput,quantityInput,costInput);
int itemNumberInput1;
int quantityInput1;
double costInput1;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput1;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput1;
cout << "Enter the Cost : " << endl;
cin >> costInput1;
inventory secondObject(itemNumberInput1,quantityInput1,costInput1); // not sure if thats correct
cout << secondObject.setItemNumber(); // not working
cout << secondObject.setQuantity(); // not working
cout << secondObject.setCost(); // not working
return 0;
}
The code above is supposed to take three user inputs, and send them to the classes, and the classes will do their job.
I'm currently stuck at the end where its giving me an error.
In the second object where the values are asked from the user, it should send these values to the classes.
Instead, I'm getting the error.
How can I resolve this problem?
Here is the fixed code:-
#include <iostream>
using namespace std;
class inventory
{
public:
~inventory()
{
cout << "This Object is being destroyed" << endl;
}
inventory()
{
itemNumber = 0;
quantity= 0;
cost= 0;
}
inventory(int itemNumber, int quantity, double cost)
{
this->itemNumber = itemNumber;
this->quantity = quantity;
this->cost = cost;
}
void setItemNumber(int itemNumber)
{
this->itemNumber=itemNumber;
}
bool setQuantity(int quantity)
{
bool userTrue = true;
bool userFalse = false;
if (quantity < 0)
{
this->quantity = 0;
return userFalse;
}
else
{
this->quantity= quantity;
return userTrue;
}
}
bool setCost(double cost)
{
bool userTrue = true;
bool userFalse = false;
if (cost < 0.0)
{
this->cost = 0.0;
return userFalse;
}
else
{
this->cost= cost;
return userTrue;
}
}
double getTotalCost(int quantity, double cost)
{
return quantity * cost;
}
private:
int itemNumber;
int quantity;
double cost;
};
int main()
{
int itemNumberInput;
int quantityInput;
double costInput;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput;
cout << "Enter the Cost : " << endl;
cin >> costInput;
inventory *pointerA, *pointerB;
pointerA = new inventory;
pointerB = new inventory(inventory(itemNumberInput , quantityInput , costInput));
inventory firstObject(itemNumberInput,quantityInput,costInput);
int itemNumberInput1;
int quantityInput1;
double costInput1;
cout << "Enter the Item Number: " << endl;
cin >> itemNumberInput1;
cout << "Enter the Quantity : " << endl;
cin >> quantityInput1;
cout << "Enter the Cost : " << endl;
cin >> costInput1;
// The below line is correct
// inventory secondObject(itemNumberInput1,quantityInput1,costInput1);
//Alternatively
inventory secondObject;
secondObject.setItemNumber(itemNumberInput1);
secondObject.setQuantity(quantityInput1);
secondObject.setCost(costInput1);
delete pointerA; // delete dynamically allocated memory to avoid memory leak
delete pointerB;
return 0;
}
Well you've constructed 'secondObject' object using the 3-arg constructor, using the user-entered values as parameters. Therefore, the member variables of this object are being set via the constructor and using the 'set' methods aren't really necessary. In your case, the set methods would be useful if you wanted to change the values later on. For example, lets pretend the user enters 10, 10, and 2.5 for the values. You're then using the constructor to construct the object with those values. The only difference is you're placing those values into variables first. But it works the same way. If you wanted to change the value of quantity later on, you could do secondObject.setQuantity(2); And the quantity for that object is now set to 2. The reason why your calls to .set aren't working is because you need to pass in parameters to these methods i.e. the value you want to set it to.
In regard to the destructor method being printed, objects are destroyed when they go out of scope so that the memory is released. Normally, nothing would happen in terms of output- the object would just go out of scope and the compiler would free up the memory and go about its' business. However, you've coded a custom destructor that prints out 'The Object is being destroyed', which it is at the end of the main. It's likely your constructor is working fine, I'm just not sure what you expect to be happening. I'd also suggest you read up on memory leaks in C++, especially in regard to the 'new' keyword.

Passing an object to a method C++

Sorry for grammar, not a native speaker.
So I've got an assignment to create a simple program where you should be able to create three people, pass in their name, country, occupation and phone number. You should be able to print out saved information as a spreadsheet.
So I came up with this kind of piece of code:
#include <iostream>
#include <iomanip>
using namespace std;
class Person {
public:
string surname;
string name;
string country;
string occupation;
string phone;
// Set default value
Person() {
surname = "empty";
name = "empty";
country = "empty";
occupation = "empty";
phone = "empty";
}
// SET PERSON'S DATA
void set_surname(string entered_surname) {
surname = entered_surname;
}
void set_name(string entered_name) {
name = entered_name;
}
void set_country(string entered_country) {
country = entered_country;
}
void set_occupation(string entered_occupation) {
occupation = entered_occupation;
}
void set_phone(string entered_phone) {
phone = entered_phone;
}
// RETURN PERSONS DATA
string get_surname() {
return surname;
}
string get_name() {
return name;
}
string get_country() {
return country;
}
string get_occupation() {
return occupation;
}
string get_phone() {
return phone;
}
};
void create_a_frankenstein(Person person) {
string entered_data;
cout << "Please, enter person's surname: \n";
cin >> entered_data;
person.set_surname(entered_data);
cout << "Please, enter person's name: \n";
cin >> entered_data;
person.set_name(entered_data);
cout << "Please, enter person's country: \n";
cin >> entered_data;
person.set_country(entered_data);
cout << "Please, enter person's occupation: \n";
cin >> entered_data;
person.set_occupation(entered_data);
cout << "Please, enter person's phone: \n";
cin >> entered_data;
person.set_phone(entered_data);
}
int main() {
Person fst;
Person snd;
Person trd;
Person group[3] = {fst, snd, trd};
int people_created = 0;
bool switch_on = true;
while (switch_on) {
cout << "What operation would you like to perform: \n";
cout << " 1) Create new person \n";
cout << " 2) Print out all of the available information \n";
cout << " 3) Quit \n";
//Get the number of operation to perform
int operation;
cout << "Please, enter a number: \n";
cin >> operation;
switch (operation) {
//Option 1: create a person
case 1:
if (people_created == 3) {
cout << "It is not possible to create more that three people";
}
else {
create_a_frankenstein(group[people_created]);
people_created++;
}
break;
//Option 2: print out all of the available information
case 2:
for (int i = 0; i < 3; i++) cout << setw(20) << setfill(' ') << left << group[i].get_surname();
for (int i = 0; i < 3; i++) cout << setw(20) << setfill(' ') << left << group[i].get_name();
for (int i = 0; i < 3; i++) cout << setw(20) << setfill(' ') << left << group[i].get_country();
for (int i = 0; i < 3; i++) cout << setw(20) << setfill(' ') << left << group[i].get_occupation();
for (int i = 0; i < 3; i++) cout << setw(20) << setfill(' ') << left << group[i].get_phone();
break;
// Option 3: quit
case 3:
switch_on = false;
break;
}
}
}
Everything seem to work just fine. Except it doesn't change information in object's variables.
My guess is that when I pass a Person-type object to create_a_frankenstein(), method creates a copy of an object and starts working with a copy without changing anything in the original object.
I've tried to use pointer. I manage to do what I intend to on simplier examples:
void first(int* a){
for (int i = 0; i < 7; i++) {
a[i] = a[i]+1;
}
}
int main() {
int a[7] = {0, 1, 2, 3, 4, 5, 6};
for (int i=0; i<7; i++) {
cout << a[i] << ' ';
}
}
But when I try to use it in the Lab, it doesn't work as easily.
Will be glad to receive any advices on how to solve the problem and what topics I should brush up or look deeper in. Thank you in advance!
Try to pass your Person objects by reference. You can find more here: passing object by reference in C++. Btw in your code example you don't call your function named 'first'.
The problem is on the void create_a_frankenstein(Person person) method.
You are passing a copy of the Person's object. If you want to keep the changes made to an object pass it as a reference: void create_a_frankenstein(Person& person)
Note:
Don't use arrays. Use std::vector instead if you want to store sequences of objects.
It would be nice if you define any getter member function as const --> return_type getter_name(params) const { //body here}

What is a deleted function, and why only my functions that I pass files into are considered deleted? [duplicate]

This question already has answers here:
Using fstream Object as a Function Parameter
(3 answers)
Closed 6 years ago.
#include <bits/stdc++.h>
using namespace std;
class contact {
private:
vector< pair<string, int> > contact_info;
public:
void add_contact(string contact_name, int contact_number) {
contact_info.push_back(make_pair(contact_name, contact_number));
sort(contact_info.begin(),contact_info.end());
}
void edit_contact(string contact_name) {
int found_at;
for (unsigned int i =0; i < contact_info.size(); i++) {
if (contact_info[i].first == contact_name) {
found_at = i;
}
}
if (contact_info[found_at +1].first == contact_name) {
int choice;
int counter = found_at;
int index = 1;
while (contact_info[counter].first == contact_name) {
cout << index << ". " << contact_info[counter].first << " " << contact_info[counter].second;
counter++;
index++;
}
cout << "Choose any please: ";
cin >> choice;
found_at = found_at - (choice - 1);
}
cout << "Enter the new number: ";
cin >> contact_info[found_at].second;
}
void show_all() {
for (unsigned int i =0; i < contact_info.size(); i++) {
cout << contact_info[i].first << " " << contact_info[i].second << endl;
}
}
void delete_contact(string contact_name) {
int found_at;
for (unsigned int i =0; i < contact_info.size(); i++) {
if (contact_info[i].first == contact_name) {
found_at = i;
}
}
if (contact_info[found_at +1].first == contact_name) {
int choice;
int counter = found_at;
int index = 1;
while (contact_info[counter].first == contact_name) {
cout << index << ". " << contact_info[counter].first << " " << contact_info[counter].second;
counter++;
index++;
}
cout << "Choose any please: ";
cin >> choice;
found_at = found_at - (choice - 1);
}
contact_info.erase(contact_info.begin()+found_at);
}
void writeFile(ofstream contact_file) {
for (unsigned int i =0; i < contact_info.size(); i++) {
contact_file << contact_info[i].first << " " << contact_info[i].second << endl;
}
}
void readFile(ifstream contact_file) {
string input;
while (!contact_file.eof()) {
contact_file >> input;
size_t pos = input.find(" ");
string name = input.substr(0,pos);
string number_str = input.substr(pos);
int number = stoi(number_str) ;
contact_info.push_back(make_pair(name,number));
}
}
};
int main()
{
int choice;
ifstream contacts_file_read;
contacts_file_read.open("contacts.txt");
ofstream contacts_file_write;
contacts_file_write.open("contacts.txt");
bool in_prog = true;
contact contacts;
string name;
int number;
while (in_prog) {
cout << "1. Add contacts" << endl
<< "2. Edit contact" << endl
<< "3. Delete contact" << endl
<< "4. Show all" << endl
<< "5. exit" << endl;
cout << "Your choice: ";
cin >> choice;
contacts.readFile(contacts_file_read);
if (choice == 1) {
cout << "Enter name & number separated by a space: ";
cin >> name >> number;
contacts.add_contact(name, number);
} else if (choice == 2) {
cout << "Enter name of contacts to be edited: ";
cin >> name;
contacts.edit_contact(name);
} else if (choice == 3) {
cout << "Enter name of contact to be deleted: ";
cin >> name;
contacts.delete_contact(name);
} else if (choice == 4) {
contacts.show_all();
} else if(choice == 5) {
contacts.writeFile(contacts_file_write);
} else {
cout << "Wrong choice" << endl;
}
}
return 0;
}
So, I was asked in my programming class to make a phone book application in C++ using only objects, so this is my attempt at it.
All functions are good, I did recompile the program after finishing each function at it gave me 0 errors, however whenever I try to call writeFile or readFile function that were previously working fine, now the compiler gave me an error of "error: use of deleted functions... "
I don't know what are deleted functions and why only functions that take file objects as an argument are treated as such.
Can anyone please help?
Thanks.
Objects of type std::ifstream are not copyable -- indeed, the object represents the unique handle of an open file, and it would be difficult to conceptualize what it would mean to copy such unique responsibility.
Indeed, this inability to copy an object is encoded by making the copy constructor deleted, which causes the error that you see when you do attempt to copy it.
Your code should pass the original ifstream, not a copy (by taking a reference parameter):
void readFile(ifstream & contact_file)
// ^^^^^^^^^^

removal of food in cart, but certain foods are not removing? why [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
Here is my main:
int main() {
Inventory Master;
bool flag;
Customer Bob("Bob", "CreditCard.txt");
Customer Joe("Joe", "CreditCard.txt" );
Master.firststock( "inventory.txt" );
vector<Food> temp = Master._Inv;
cout <<"Hi, What would you like to buy today?" << endl;
for(unsigned int i=0; i<temp.size(); i++ ) {
cout << temp[i].name << " " << temp[i].quant << " " << temp[i].price << endl;
}
cout <<"\n";
Food Apple("Apples", .99, 10);
Food Orange("Oranges", .99, 10);
Food Chip("Chips", 3.00, 10);
cout <<"\nHi Bob" << endl;
flag = Bob.addCart(Apple, 7, &Master);
cout <<"Bob's total purchases are Currently: \n";
Bob.report();
flag = Bob.addCart(Orange, 2, &Master);
flag = Bob.addCart(Chip, 2, &Master);
Bob.report();
flag = Bob.removeCart();
Bob.report();
cout <<"Bob, ";
flag = Bob.checkout(&Master);
here is the following i implemented to remove food from my vector _Cart:
bool Customer::removeCart() {
bool flag;
int q = 0;
unsigned int i=0;
string remove;
cout << "\nWhat would you like to remove and how much would you like to remove?" << endl;
cin >> remove >> q;
for (i =0; i < _Cart.size(); i++) {
if(remove == _Cart[i].name) {
if (q >= 0) {
_Cart[i].quant -= q;
//inv->_Inv[i].quant += q;
cout <<"\nYou removed " << q << " " << remove <<" In your cart\n" << endl;
return true;
}
if (q < 0) {
cout << "Invalid number of " << remove << " being removed.\n" << endl;
return true;
}
}
else {
try {
throw remove;
}
catch (string param) {
cout << "\n" << remove << " doesn't exist in your cart\n" << endl;
}
return true;
}
}
My header containing the the function removeCart:
class Customer {
public:
Customer(string n, string fileName);
~Customer() { _Cart.clear(); };
bool addCart(Food f, int q, Inventory* inv);
bool removeCart();
void report();
bool checkout(Inventory* inv);
protected:
string remove;
string name;
int q;
int card;
double balance;
CreditCard _CC(int card,double balance);
vector<Food> _Cart;
};
Now for some reason when i call removeCart, entering "Apples" works but i noticed i made a food object called Apple so not sure why typing "Apples" works for being removed instead of "Apple". Also when i try "Orange" or "Chip" the exception is shown but as you can see in main i added Chip and Orange to Bob's Cart. I have even tried "Oranges" and "Chips" and it still throws me the exception instead of working. I could appreciate the help.
Your for/if/else structure is broken. If you don't match on the first element in the cart, you throw an exception, which you immediately catch. Try something more like this:
for (i =0; i < _Cart.size(); i++)
{
if(remove == _Cart[i].name)
{
if (q >= 0)
{
_Cart[i].quant -= q;
//inv->_Inv[i].quant += q;
cout <<"\nYou removed " << q << " " << remove <<" In your cart\n" << endl;
}
else
cout << "Invalid number of " << remove << " being removed.\n" << endl;
return true;
}
}
cout << "\n" << remove << " doesn't exist in your cart\n" << endl;
return true;
Is it a homework? :)
Firstly, "Apple" is the name of the variable you created, but you are passing "Apples" to the constructor of Food, so I suppose that this value is being assigned to its "name" member which is used in comparison.
Secondly, as David noticed, your loop will work only if you try to remove the first element in the cart. In your case the first element is named "Apples", so typing "Apples" works.