0

The switch can call the DisplayMenuChoice function, but any choice just ends the program.

All functions work fine independently, I think it has to do with my argument and return from DisplayMenuChoice

void GoblinSickDays();

void DisplayCoolMessage();

int DisplayMenuGetChoice (int)

{

   int menu_choice;

   cout << "Please select the following menu items: \n"  << endl; 

   cout << "1. Enter Sick days." << endl;

   cout << "2. Display Something cool." << endl;

   cout << "3. End program \n" << endl;

   cin >> menu_choice;

}



int main()

{

   int menu_choice;

   DisplayMenuGetChoice(menu_choice);

   switch (menu_choice)

   {

      case 1: GoblinSickDays();
             break;

      case 2: DisplayCoolMessage();
             break;

   }
}

Keeps ending program after entering the a value from cin statement

Shekhar Rai
  • 2,008
  • 2
  • 22
  • 25
  • Possible duplicate of [Changing address contained by pointer using function](https://stackoverflow.com/questions/13431108/changing-address-contained-by-pointer-using-function) – John3136 Oct 22 '19 at 04:03
  • 1
    You aren't actually setting the `menu_choice` you use for your `switch`. – Elliott Frisch Oct 22 '19 at 04:03
  • 1
    When you pass `menu_choice` in `DisplayMenuGetChoice(menu_choice);`, the function receives a **copy** of the variable. Any changes made in the function to it are not being made to the original back in `main()`. You can pass a pointer, or since this is C++, a reference to the original and update the value directly in your function, e.g. `int DisplayMenuGetChoice(int& menu_choice) {...}` or simply `return menu_choice;` and assign the return back in `main()`. – David C. Rankin Oct 22 '19 at 04:14
  • I tried using the return statement, but I end up getting an error that says " declaration of 'int menu_choice' shadows a parameter" – Sky Smith Oct 22 '19 at 04:30
  • 1
    @SkySmith Maybe only call one thing `menu_choice` instead of several different things. – David Schwartz Oct 22 '19 at 04:33

2 Answers2

1

Continuing from the comments above, when you pass a variable as a parameter, it is passed by value. Meaning the function receives a copy of the variable and any changes made to the variable in the function are not being made to the original back in main(), but instead are being made to the local copy within your function.

In C++ you have three basic ways of handling this:

  1. pass a pointer to the variable as you would in C and update the value at that address within your function, e.g.

    int DisplayMenuGetChoice (int *menu_choice) { ...
    

and call the function in main() as:

    DisplayMenuGetChoice(&menu_choice);
  1. you pass a reference to menu_choice and update the value directly within your function, e.g.

    int DisplayMenuGetChoice (int& menu_choice) { ...
    

and call it as:

    DisplayMenuGetChoice(menu_choice);
  1. or finally don't worry about passing menu_choice at all. You have declared your DisplayMenuGetChoice as type int, so simply return menu_choice; from the function and assign the return back in main(), e.g.

    int DisplayMenuGetChoice (void)
    {
        int menu_choice;
        ...
        return menu_choice;
    }
    

in main(),

    int menu_choice = DisplayMenuGetChoice();

Putting it altogether in a couple of examples (ignoring the C solution), you could do:

Pass A Reference

int DisplayMenuGetChoice (int& menu_choice)
{
    std::cout << "\nPlease select the following menu items: \n\n" 
                    " 1. Enter Sick days.\n"
                    " 2. Display Something cool.\n"
                    " 3. End program\n\n"
                    "choice: ";

    if (!(std::cin >> menu_choice)) {
        std::cerr << "error: invalid integer input.\n";
        exit (EXIT_FAILURE);
    }

    return menu_choice;
}

int main() {

    int menu_choice;

    DisplayMenuGetChoice(menu_choice);

    switch (menu_choice) {
        case 1: GoblinSickDays(); break;
        case 2: DisplayCoolMessage(); break;
        case 3: std::cout << "(bye)\n"; break;
        default: std::cerr << "invalid choice.\n"; break;
    }
}

Assign the Return

int DisplayMenuGetChoice (void)
{
    int menu_choice;

    std::cout << "\nPlease select the following menu items: \n\n" 
                    " 1. Enter Sick days.\n"
                    " 2. Display Something cool.\n"
                    " 3. End program\n\n"
                    "choice: ";

    if (!(std::cin >> menu_choice)) {
        std::cerr << "error: invalid integer input.\n";
        exit (EXIT_FAILURE);
    }

    return menu_choice;
}

int main() {

    int menu_choice = DisplayMenuGetChoice();

    switch (menu_choice) {
        case 1: GoblinSickDays(); break;
        case 2: DisplayCoolMessage(); break;
        case 3: std::cout << "(bye)\n"; break;
        default: std::cerr << "invalid choice.\n"; break;
    }
}

Edit Per-Comment Re: do {...} while();

You can use any of the methods above to make the menu repeatedly redisplay until the user chooses to exit the program. For example, using any of the methods that return menu_choice you could do:

#include <iostream>

void GoblinSickDays()
{
    std::cout << "Goblin is sick.\n";
}

void DisplayCoolMessage()
{
    std::cout << "Cool Message.\n";
}

int DisplayMenuGetChoice (void)
{
    int menu_choice;

    std::cout << "\nPlease select the following menu items: \n\n" 
                    " 1. Enter Sick days.\n"
                    " 2. Display Something cool.\n"
                    " 3. End program\n\n"
                    "choice: ";

    if (!(std::cin >> menu_choice)) {
        std::cerr << "error: invalid integer input.\n";
        exit (EXIT_FAILURE);
    }

    return menu_choice;
}

int main() {

    int done = 0;

    do {
        switch (DisplayMenuGetChoice()) {
            case 1: GoblinSickDays(); break;
            case 2: DisplayCoolMessage(); break;
            case 3: std::cout << "(bye)\n";
                    done = 1;
                    break;
            default: std::cerr << "invalid choice.\n"; break;
        }
    } while (!done);
}

(note: while the code above simply exits on a bad input, you should handle the error (whether it is cin.fail(), cin.bad() or cin.eof()) and so long as the error is recoverable, use std::basic_istream::ignore to remove the offending characters from stdin before the next time the menu is displayed)

Example Use/Output

$ ./bin/goblindays3

Please select the following menu items:

 1. Enter Sick days.
 2. Display Something cool.
 3. End program

choice: 1
Goblin is sick.

Please select the following menu items:

 1. Enter Sick days.
 2. Display Something cool.
 3. End program

choice: 2
Cool Message.

Please select the following menu items:

 1. Enter Sick days.
 2. Display Something cool.
 3. End program

choice: 3
(bye)

Give that a try and let me know if you have further questions. Look things over and let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I got the return statement to work, my only question after that would be how would I be able to get a different return value if I were to put the switch statement in a do-while loop? Regardless of menu choice chosen, it will only display the initial choice after the menu. – Sky Smith Oct 22 '19 at 16:36
1

It may be worth having a more in-depth understanding about the language syntax. Let me explain a few things in your code.

A typical function definition is as follows:

returnType FunctionName(paramType paramName)
{
    returnType a = value;
    return a;
}

To suit your current implementation, the function DisplayMenuGetChoice would likely be the following:

int DisplayMenuGetChoice()
{
    int menu_choice;
    {add your main logic here}
    return menu_choice;
}

To break this down, it is:

  • A function named DisplayMenuGetChoice, callable by using DisplayMenuGetChoice()
  • Has a return type of int

By instead calling menu_choice = DisplayMenuGetChoice(); in your main() function, you will assign your menu_choice the value returned from DisplayMenuGetChoice().

An alternate approach (which seems to be what you are trying to achieve) is called Pass By Reference.. A parameter name is prefixed by an ampersand (&) to indicate this, for example:

void DisplayMenuGetChoice(int &menu_choice)
{
    {add your main logic here}
}

This, by comparison:

  • We return void, which essentially means no return type.
  • We pass an int named menu_choice by reference. This is absolutely something you should read about.
  • We don't return anything as we modify menu_choice directly.

Now in the main function, you can instead use DisplayMenuGetChoice(menu_choice) instead.

As another small mention, by prefixing a variable with an ampersand (like you do in your function call), you are instead passing a pointer to the variable. This is a whole other topic that you may need to read up on.

Chris
  • 185
  • 1
  • 14