0

I'm trying to loop through structures, not the fields to create a vending machine like program. I don't understand why this doesn't work:

//create a structure to hold data on the items in the vending machine
struct snack{

    string description; //this will hold data on what the item is
    int quantity;       //this will hold data on how many of the item are left in the vending machine
    double cost;        //this will hold the cost of this item

};

//...

//create the specific snack structures of type snack and initialize them
snack specificSnack[CHIPS]={"Plain Potato Chips", 15, 1.00};
snack specificSnack[SNICKERS]={"Snickers", 10, 0.75};
snack specificSnack[PEANUTS]={"Peanuts", 15, 1.00};
snack specificSnack[JOLLYRANCHER]={"Jolly Rancher", 10, 0.75};
snack specificSnack[APPLE]={"Apple", 5, 0.50};

//...

//print a header
cout<<"\n#  |cost  |quantity |item"<<endl:

//display all the items in the menu
for(int i=CHIPS; i<EXIT; i++)
    displayMenu(specificSnack[i], i); //call the display for a specific item

Please note that we haven't covered classes and objects in my class yet so i can't use them yet except for some simple i/o stuff and the string class.

EDIT: CHIPS, SNICKERS, etc.. are enumerated variables.

//create an enumerated variable of type treat to make the code more readable and select choices
enum treat{CHIPS, SNICKERS, PEANUTS, JOLLYRANCHER, APPLE, EXIT};

Sure, here's the full code[UPDATED]:

//This is a simple vending machine emulator
//Developed by [NAME WITHHELD]
//created on: 3/19/2016 8:30 AM
//last updated on: N/A

//library includes
#include <iostream>     //in/out functionality
#include <iomanip>      //used for in/out manipulators such as endl
#include <string>       //used to process string objects
#include <cstring>      //used to process c style strings
using namespace std;    //this tells the compiler that the libraries are located in the standard location

//create a structure to hold data on the items in the vending machine
struct snack{

    string description; //this will hold data on what the item is
    int quantity;       //this will hold data on how many of the item are left in the vending machine
    double cost;        //this will hold the cost of this item

};

//create an enumerated variable of type treat to make the code more readable and select choices
enum treat{CHIPS, SNICKERS, PEANUTS, JOLLYRANCHER, APPLE, EXIT};


void vend(int choice, snack & specificSnack);
void finalOutputDisplay(long double totalCost);
treat getChoice();
void displayMenu(snack selection, int i);

//program starts here
int main()
{
    //pre-configure cout for numerical output
    cout<<fixed;


    snack specificSnack[APPLE];

    //create the specific snack structures of type snack and initialize them
    specificSnack[CHIPS]={"Plain Potato Chips", 15, 1.00};
    specificSnack[SNICKERS]={"Snickers", 10, 0.75};
    specificSnack[PEANUTS]={"Peanuts", 15, 1.00};
    specificSnack[JOLLYRANCHER]={"Jolly Rancher", 10, 0.75};
    specificSnack[APPLE]={"Apple", 5, 0.50};

    //create a variable to hold the total amount the user is going to spend in this session
    long double totalCost=0;

    //create and enumerated variable called choice, of type treat
    treat choice=CHIPS;

    //begin looping until we see the EXIT sentinel
    while(choice!=EXIT)
    {
        //print a header
        cout<<"\n#  |cost  |quantity |item"<<endl;

        //display all the items in the menu
        for(int i=CHIPS; i<EXIT; i++)
            displayMenu(specificSnack[i], i); //call the display for a specific item

        //get the user's selection
        choice=getChoice();

        //skip the vending code if we are exiting
        if(choice!=EXIT)
        {
            //make sure the item isn't sold out
            if(specificSnack[choice].quantity!=0)
                totalCost=specificSnack[choice].cost;//add the cost of the item chosen to the running total

            //run the vending code to decrement the quantity of the item and display
            //a message confirming the selection
            vend(choice, specificSnack[choice]);

        }
    }//return to the start of the loop and run a check to see if we break on EXIT

    //display the total cost of items bought in this session and
    finalOutputDisplay(totalCost);

    return 0;   //return to the OS
}

void displayMenu(snack selection, int i)
{
    //print out one line/option of the menu

    //print the cost of the item
    cout<<i<<". |"<<setprecision(2)<<setw(6)<<selection.cost<<"|";

    //check if we are sold out
    if(selection.quantity!=0)
        cout<<setprecision(0)<<setw(9)<<selection.quantity<<"|";    //print the amount left
    else
        cout<<"Sold Out |";  //tell the user we're sold out

    //give the item
    cout<<selection.description<<endl;

    return; //exit function
}

treat getChoice()//get the user's choice, decide if it's valid and what it is, and return it in the proper format
{
    //create variables
    string usrInput;
    treat choice;
    int i;
    bool continueLoop;

    //begin a loop to catch invalid input
    do
    {
        cout<<"\nPlease select an item: ";  //prompt the user
        i=0;    //reset the loop control variable for the uppercase letter to lowercase letter conversion loop
        continueLoop=0; //reset the flag to break out of the do-while loop

        //get & store user input
        getline(cin, usrInput);

        //loop through the string
        while(usrInput[i]!='\0')
        {
            //check if the letter is a capital
            if(isupper(usrInput[i]))
                tolower(usrInput[i]);//convert the character to a lowercase letter
            i++;//increment out loop control variable and proceed to the next character in the string
        }

        //check if the user entered a valid choice and set choice appropriately
        if(usrInput=="1" || usrInput=="one" || usrInput=="chips" || usrInput=="plain potato chips")
            choice=CHIPS;
        else if(usrInput=="2" || usrInput=="two" || usrInput=="snickers")
            choice=SNICKERS;
        else if(usrInput=="3" || usrInput=="three" || usrInput=="peanuts")
            choice=PEANUTS;
        else if(usrInput=="4" || usrInput=="four" || usrInput=="jolly rancher")
            choice=JOLLYRANCHER;
        else if(usrInput=="5" || usrInput=="five" || usrInput=="apple")
            choice=APPLE;
        else if(usrInput=="6" || usrInput=="six" || usrInput=="exit")
            choice=EXIT;
        //catch invalid input
        else
        {
            //throw an error message
            cout<<"\aERROR! Please enter a valid choice!"<<endl;

            //flip the flag to continue the loop again
            continueLoop=1;
        }

    }while(continueLoop);//check if the flag was flipped


    return choice;//return the user's choice in the proper format.
}

void vend(int choice, snack & specificSnack)//tell the user what we are vending, or display sold out
{
    //give the items name
    cout<<"\nITEM: "<<specificSnack.description<<endl;
    //give the items price
    cout<<"COST: $"<<specificSnack.cost<<endl;
    //check if we are sold out and if we aren't run the following code
    if(specificSnack.quantity>0)
    {
        //tell the user we are vending
        cout<<"Vending..."<<endl;

        //remove one item from the machine
        specificSnack.quantity--;
    }
    //if we are sold out do this:
    else
    {
        //display a sold out message
        cout<<"\a\n!SOLD OUT!: "<<specificSnack.description<<endl;
    }

    return; //exit function
}

void finalOutputDisplay(long double totalCost)  //display a final message to the user including their total
{
    //be polite & friendly to our customer
    cout<<"\nThank you for using this vending machine!  Have a nice day!"<<endl;
    //display the total spent by the user in this session
    cout<<"\nYour total is: "<<totalCost<<endl;
    //display a message saying the session is ending
    cout<<"\nNow exiting session..."<<endl;

    return; //exit function
}

EDIT: IT now compiles, but it crashes displaying the second item in the vending machine

  • can you give your full code.. – Kishan Kumar Mar 20 '16 at 09:12
  • 1
    You do know that `snack specificSnack[CHIPS]` creates an array of `CHIPS` number of `snack` structures? And considering that `CHIPS` is zero that won't work very well. Maybe you want a [`std::map`](http://en.cppreference.com/w/cpp/container/map), or possibly a [`std::vector`](http://en.cppreference.com/w/cpp/container/vector)? What you definitely seem to need is [The Definitive C++ Book Guide and List](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – Some programmer dude Mar 20 '16 at 09:15
  • 1
    your code makes no sense And won't compile.. what do you expect `snack specificSnack[CHIPS]={"Plain Potato Chips", 15, 1.00};` to do?? you are not constructing snacks here, you are defining an array of snacks and then try to initialise it with the arguments you would normally pass to the constructor of a single snack... Then `for(int i=CHIPS; i – Marinos K Mar 20 '16 at 09:18
  • oh, so I should initialize it with `snack specificSnack[APPLE]` and then set them each like this? `specificSnack[CHIPS]={"Plain Potato Chips", 15, 1.00}; specificSnack[SNICKERS]={"Snickers", 10, 0.75}; specificSnack[PEANUTS]={"Peanuts", 15, 1.00}; specificSnack[JOLLYRANCHER]={"Jolly Rancher", 10, 0.75}; specificSnack[APPLE]={"Apple", 5, 0.50};` – The Villain In Glasses Mar 20 '16 at 09:18
  • If you insist on that array you can only put pointers to each structure on it. Then you can loop through that. You could associate indices with ENUM but that's not good at all. If you can use `std::map` as [Joachim](http://stackoverflow.com/users/440558/joachim-pileborg) says you're golden – zdim Mar 20 '16 at 09:21
  • My teacher requires me to use `enum` – The Villain In Glasses Mar 20 '16 at 09:29
  • They can be used as `int` so you can use them to index into an array. But see answer by [Peter](http://stackoverflow.com/users/4706785/peter) below, same as comment by [Joachim](http://stackoverflow.com/users/440558/joachim-pileborg). And start reading up on the language. – zdim Mar 20 '16 at 09:35
  • I've made the change and it appears to compile. – The Villain In Glasses Mar 20 '16 at 09:39
  • You should not use floating-point numbers for currency. Use `int` and make the number represent the smallest unit (e.g. cents). Consider bigger units (e.g. euro) only when you *display* the number. – Christian Hackl Mar 20 '16 at 11:53

2 Answers2

1

snack specificSnack[CHIPS]={"Plain Potato Chips", 15, 1.00};

Think about what this means in C++.

It defines specificSnack as an array with CHIPS elements of type snack. It does not create a single snack that is identified as specificSnack[CHIPS].

After doing this - assuming it compiles - the next declaration

snack specificSnack[SNICKERS]={"Snickers", 10, 0.75};

defines specificSnack as an array with SNICKERS elements of type snack. C++ has a "one definition rule" which means, when defining any array, exactly one definition is permitted. Two definitions of an array - particularly with different dimensions - breaks that rule.

The most you can do is define the array once, and then initialise it.

For example;

enum treat{CHIPS=0, SNICKERS=1, PEANUTS=2, JOLLYRANCHER=3, APPLE=4, EXIT=5, number_of_treats = 5};    // assuming EXIT is not deemed to be a treat

 snack specificSnack[number_of_treats] = {
            {"Plain Potato Chips", 15, 1.00},
            {"Snickers", 10, 0.75}, 
            {"Peanuts", 15, 1.00},
            {"Jolly Rancher", 10, 0.75},
            {"Apple", 5, 0.50}};
Peter
  • 35,646
  • 4
  • 32
  • 74
  • 1
    Yes, I know. I haven't examined what else your code is doing but - since you guessed wrong on something this fundamental - I wouldn't bet that the rest of your code works as intended. You're going to need to debug on your own - this format is not suited to a repeated "please get my code working and I'll edit the question each time someone helps with one problem until I get my code working" approach. – Peter Mar 20 '16 at 09:37
  • ok, thanks. do you know any site's where that format would be acceptable? And yes I know it's fundamental, but I've only been coding a few months and it's my first time working with structures and enumerators. – The Villain In Glasses Mar 20 '16 at 09:40
  • Generally, no. Sites don't tend to provide a "debug your code for free" service - simply because people who know enough to help in that way don't believe in doing people's homework for them. If you want that, you'll need to find a paid service. – Peter Mar 20 '16 at 10:00
0

I think what you mean is:

...
enum treat{CHIPS=0, SNICKERS=1, PEANUTS=2, JOLLYRANCHER=3, APPLE=4, EXIT=5};
...
int main() {
    ...
    snack specificSnack[6];
    specificSnack[CHIPS]       ={"Plain Potato Chips", 15, 1.00};
    specificSnack[SNICKERS]    ={"Snickers", 10, 0.75};
    specificSnack[PEANUTS]     ={"Peanuts", 15, 1.00};
    specificSnack[JOLLYRANCHER]={"Jolly Rancher", 10, 0.75};
    specificSnack[APPLE]       ={"Apple", 5, 0.50};
    ...
}
AuThor
  • 29
  • 2