0

I'm creating a menu generator that takes in inputs from a .txt file that has info, such as the type of dish ("appetizers", "entrees", etc), the price, and the name of the dish.

I made a class called Dish and added some getters/setters I would use. I made a while loop that takes in the info from the .txt file. And I made a vector that would store the price and name of the dish, depending on the type of dish it is.

I have what was stored in those vectors be printed onto the output file. It does print out those dishes and prices, but they are all grouped up in one section (ie, all the dishes are under "Entrees"). Here's some of my code below.

Part of my code in main() that prints out the menu:

// Taking in the info
while (fin >> type >> price >> ws && getline(fin, name)) {
    dishType = menu.get_dish_type();
    menu.add_dish(type, price, name);
}

// Printing out the Menu
fout << "Menu\n\n";
fout << "Appetizers\n\n";
if (dishType == 0) {
    for (const auto& dish : menu.appetizer) {
        fout << dish.first << "($" << dish.second << ")" << endl;
    }
}

fout << "\nEntrees\n\n";
if (dishType == 1) {
    for (const auto& Dish : menu.entree) {
        fout << Dish.first << "($" << Dish.second << ")" << endl;
    }
}

fout << "\nDesserts\n";
if (dishType == 2) {
    for (const auto& Dish : menu.dessert) {
        fout << Dish.first << "($" << Dish.second << ")" << endl;
    }
}

// Closing the Files
fin.close();
fout.close();

My implementation file:

#include "Dish.h"

Dish::Dish() : dish_type(0), dish_price(0), dish_name("") {}

// The Getters
unsigned int Dish::get_dish_type() const {return dish_type;}

unsigned int Dish::get_dish_price() const {return dish_price;}

string Dish::get_dish_name() const {return dish_name;}

// The Setters
void Dish::set_dish_type(string type) {
    if (type == "appetizer") {dish_type = 0;}
    if (type == "entree") {dish_type = 1;}
    if (type == "dessert") {dish_type = 2;}
}

void Dish::set_dish_price(unsigned int new_price) {dish_price = new_price;}

void Dish::set_dish_name(string new_name) { dish_name = new_name; }

void Dish::add_dish(string type, unsigned int price, string name) {
    if (dish_type == 0) {
        appetizer.push_back(make_pair(name, price));
    }
    else if (dish_type == 1) {
        entree.push_back(make_pair(name, price));
    }
    else if (dish_type == 2)
        dessert.push_back(make_pair(name, price));
}

I used to have my vectors be in the private part of the class, but I moved them to the public, which helped with an error I was getting in the printing part of main().

At first, nothing was printed, but I changed the if conditions in the add_dish() part of my header file, and it got the dishes to print. I'm thinking it's the way I get/use the "type of dish" but I can't think of a way to fix it.

What my code is printing out:

Menu

Appetizers

Pan-Seared Halibut with Sauteed Spinach($28)
Thai Green Curry Chicken Wings($9)
Char-Grilled Shrimp Skewers($10)
Angus Beef Burger with Aged Cheddar($10)
Gluten-Free Carrot Cake($5)
Linguine with White Clam Sauce($19)
12-oz Ribeye Steak with Cumin Pepper($23)
Chilled Cucumber Soup($4)
Jam and Peanut Butter Cookie($5)
Grilled Artichokes($10)

Entrees


Desserts

What my code is supposed to print out:

Menu

Appetizer

Thai Green Curry Chicken Wings ($9)
Char-Grilled Shrimp Skewers ($10)
Chilled Cucumber Soup ($4)
Grilled Artichokes ($10)

Entree

Pan-Seared Halibut with Sauteed Spinach ($28)
Angus Beef Burger with Aged Cheddar ($10)
Linguine with White Clam Sauce ($19)
12-oz Ribeye Steak with Cumin Pepper ($23)

Dessert

Gluten-Free Carrot Cake ($5)
Jam and Peanut Butter Cookie ($5)
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • @RemyLebeau so I should use ```menu.set_dish_type()``` instead of what I have? – Yoseph Hamid Mar 08 '23 at 05:05
  • In short: you are not using `dishType`. You should let the compiler warn on unused variables. – Joop Eggen Mar 08 '23 at 05:07
  • @YosephHamid No, because you are not storing `Dish` objects in your vectors to begin with, so your entire `Dish` class makes no sense. – Remy Lebeau Mar 08 '23 at 05:08
  • @JoopEggen how do I get the compiler to do that? It just tells me when an error occurs – Yoseph Hamid Mar 08 '23 at 05:28
  • 1
    @YosephHamid: That depends on which compiler you are using. If you are using gcc or clang, then you can compile with the `-Wall -Wextra` command-line options to activate most warnings. You may want to read this: [Why should I always enable compiler warnings?](https://stackoverflow.com/q/57842756/12149471) – Andreas Wenzel Mar 08 '23 at 05:56

1 Answers1

1

You are completely ignoring the dish type value that is stored in the file, and instead basing all of your decisions on whatever menu.get_dish_type() returns, which is only 1 value that doesn't differentiate between your 3 menu types, at least not in the way you are using it. menu.get_dish_type() is likely returning 0, since I'm guessing you never call menu.set_dish_type() beforehand. So menu.add_dish() ends up adding every dish into the appetizer vector only, and you don't even attempt to print out the entree and dessert vectors at all.

Your set_dish_type() method has logic to convert the type values from the file into the dish_types values that you are making decisions on, but you are not making use of that logic in this code.

Try something more like this instead:

// Taking in the info
while (fin >> type >> price >> ws && getline(fin, name)) {
    menu.add_dish(type, price, name);
}

// Printing out the Menu
fout << "Menu\n\n";
fout << "Appetizers\n\n";
for (const auto& dish : menu.appetizer) {
    fout << dish.first << "($" << dish.second << ")" << endl;
}

fout << "\nEntrees\n\n";
for (const auto& Dish : menu.entree) {
    fout << Dish.first << "($" << Dish.second << ")" << endl;
}

fout << "\nDesserts\n";
for (const auto& Dish : menu.dessert) {
    fout << Dish.first << "($" << Dish.second << ")" << endl;
}

// Closing the Files
fin.close();
fout.close();
void Dish::add_dish(string type, unsigned int price, string name) {
    if (type == "appetizer") {
        appetizer.push_back(make_pair(name, price));
    }
    else if (type == "entree") {
        entree.push_back(make_pair(name, price));
    }
    else if (type == "dessert")
        dessert.push_back(make_pair(name, price));
}

That being said, your add_dish() code makes no sense. You are not storing Dish objects in your vectors, and a dish should not have sub-dishes in the first place. add_dish() doesn't belong in the Dish class at all, it should be moved to a separate Menu class instead, which should store vectors of Dish objects, not pairs.

For example, try this:

Main.cpp

#include "Menu.h"

...

Menu menu;

...

// Taking in the info
fin >> menu;

// Printing out the Menu
fout << menu;

// Closing the Files
fin.close();
fout.close();

Dish.h

#ifndef DISH_H
#define DISH_H

#include <iostream>
#include <string>

class Dish {
private:
    unsigned int type;
    int price;
    std::string name;

public:
    Dish();
    Dish(std::string dish_type, unsigned int dish_price, std::string dish_name);

    unsigned int get_type() const;
    unsigned int get_price() const;
    std::string get_name() const;

    void set_type(std::string new_type);
    void set_price(unsigned int new_price);
    void set_name(string new_name);
};

std::istream operator>>(std::istream &in, Dish &dish);
std::ostream operator<<(std::ostream &out, const Dish &dish);

#endif

Dish.cpp

#include "Dish.h"
#include <iomanip>

Dish::Dish() : type(0), price(0), name("") {}

Dish::Dish(std::string dish_type, unsigned int dish_price, std::string dish_name) {
    set_type(dish_name);
    set_price(dish_price);
    set_name(dish_name);
}

unsigned int Dish::get_type() const { return type; }

unsigned int Dish::get_price() const { return price; }

std::string Dish::get_name() const { return name; }

void Dish::set_type(std::string new_type) {
    if (new_type == "appetizer") { type = 0; }
    else if (new_type == "entree") { type = 1; }
    else if (new_type == "dessert") { type = 2; }
    else { type = -1; } // or throw an exception...
}

void Dish::set_price(unsigned int new_price) { price = new_price; }

void Dish::set_name(std::string new_name) { name = new_name; }

std::istream& operator>>(std::istream &in, Dish &dish) {
    std::string type, name;
    unsigned int price;

    if (in >> type >> price >> std::ws && std::getline(in, name)) {
        dish.set_type(type);
        dish.set_price(price);
        dish.set_name(name);
    }

    return in;
}

std::ostream& operator<<(std::ostream &out, const Dish &dish) {
    out << dish.get_name() << " ($" << dish.get_price() << ")";
    return out;
}

Menu.h

#ifndef MENU_H
#define MENU_H

#include <iostream>
#include <vector>
#include <string>
#include "Dish.h"

class Menu {
public:
    std::vector<Dish> appetizers, entrees, desserts;

    void add_dish(std::string type, unsigned int price, std::string name);
};

std::istream& operator>>(std::istream &in, Menu &menu);
std::ostream& operator<<(std::ostream &out, const Menu &menu);

Menu.cpp

#include "Menu.h"

void Menu::add_dish(std::string type, unsigned int price, std::string name) {
    Dish dish(type, price, name);

    switch (dish.get_type()) {
        case 0:
            appetizers.push_back(dish);
            break;
        case 1:
            entrees.push_back(dish);
            break;
        case 2:
            desserts.push_back(dish);
            break;
    }
}

std::istream& operator>>(std::istream &in, Menu &menu) {
    Dish dish;
    while (in >> dish) {
        menu.add_dish(dish);
    }
    return in;
}

std::ostream& operator<<(std::ostream &out, const Menu &menu) {

    out << "Menu\n\n";

    out << "Appetizers\n\n";
    for (const auto& dish : menu.appetizers) {
        out << dish << '\n';
    }

    out << "\nEntrees\n\n";
    for (const auto& dish : menu.entrees) {
        out << dish << '\n';
    }

    out << "\nDesserts\n";
    for (const auto& dish : menu.desserts) {
        out << dish << '\n';
    }

    return out;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • Just tried that, completely erased all of the dishes. Just left the title and categories – Yoseph Hamid Mar 08 '23 at 05:12
  • @YosephHamid then either you didn't apply it to your code correctly, or else your code has other problems that are not shown here. – Remy Lebeau Mar 08 '23 at 05:13
  • May I ask how the objects aren't getting stored into the vectors? Is it because I'm basically just having the method read what objects the loop is giving it, thus not storing anything? – Yoseph Hamid Mar 08 '23 at 05:26
  • @YosephHamid I already explained why you are not storing dishes in the correct vectors – Remy Lebeau Mar 08 '23 at 05:43