Switch Statements over different functions.

Hello Everyone,
I am having trouble seeing what I am doing wrong in my program. We just started functions, so I suspect I have a misunderstanding there. Anyways, the program has a Main Menu showing options calculate area and calculate volume. Everything is good with the area, but when I try to go into my calculate volume submenu, the flow stops after I try to open the submenu. It is like it wants an input where I didn't ask for one. If I put in a random input, say one that would trigger an "invalid option," only then does the volume sub menu pop up.
Here's some code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
[code]#include <iostream>
#include <iomanip>

using std::cin;
using std::cout;
using std::endl;

int menuChoice = 0;
char areaChoice;
char volumeChoice;
int MainMenu();
int AreaMenu();
int VolumeMenu();

int main()
{
	MainMenu();
	AreaMenu();
	VolumeMenu();
	


}

int MainMenu()
{
	
	cout << "--Main Menu--"
		 << "\n1) Calculate Area"
		 << "\n2) Calculate Volume"
		 << "\nEnter a menu choice: ";
	cin >> menuChoice;

	switch (menuChoice)
	{
	case 1:
		cout << "You chose the Calculate Area option.";
		break;
	case 2:
		cout << "You chose the Calculate Volume option." << endl;
		break;
	default:
		cout << "\nInvalid menu option." << endl;

		return menuChoice;
	}
}

int AreaMenu()
{
	if (menuChoice == 1)
		cout << "\n\n--Area Menu--"
			 << "\na) Rectangle"
			 << "\nb) Circle"
			 << "\nc) Right Triangle"
			 << "\nEnter a menu choice: ";
		 cin >> areaChoice;

	switch (areaChoice)
	{
	case 'a':
		cout << "You chose the Rectangle option.";
		break;
	case 'b':
		cout << "You chose the Circle option.";
		break;
	case 'c':
		cout << "You chose the Right Triangle option.";
		break;
	default:
		cout << "Please enter a valid option.";
	}
	int AreaMenu = 0;
	return AreaMenu;
}

int VolumeMenu()
{
	if (menuChoice == 2)     // The issue is here I believe.
		cout << "\n\n--Volume Menu--"
		<< "\na) Cylinder"
		<< "\nb)Sphere"
		<< "\nEnter a menu choice: ";
	cin >> volumeChoice;

	switch (volumeChoice)
	{
	case 'a':
		cout << "You chose the Cylinder option.";
		break;
	case 'b':
		cout << "You chose the Sphere option.";
		break;
	default:
		cout << "Please enter a valid option.";
	}
	char VolumeMenu = 0;
	return VolumeMenu;
}

Last edited on
Hello runningbear,

I like that name. While I look into your program have a look at this.

PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button. This will not automatically indent your code. That part is up to you.

You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.



Andy
Hello runningbear,

Looking at your program the using statements are better than the alternative. At least the focus is more narrow to just what you will be using. I did add 1 using std::cerr; That I like to use for error messages.

You should avoid using global variables. Just as easy as they are to use in the whole file they arr just as easily changed be any line of code that follows and trying to track down where it went wrong can be difficult and time consuming. Better to define these variables in main or the functions that need them.

In "main" you start by calling the "MainMenu" function. This function returns a value that you never capture or use, of course you are wanting to use the global variable and even that 1 you never use in "main".

The idea you need to work on is that "main" is there to direct the program flow. Since you are using menus the menu choice should be directing the flow.

The idea I have is that the return value of "MainMenu" should drive a switch to call the next menu. The returned value of the next menu can drive a switch to call the proper function.

Here is an idea for consideration:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int MainMenu()
{
    int menuChoice{};  // <--- Is local to the function and is destroyed when the function looses scope.

    do
    {
        cout <<
            "--Main Menu--"
            "\n1) Calculate Area"
            "\n2) Calculate Volume"
            "\n3) Exit"
            "\nEnter a menu choice: ";
        cin >> menuChoice;

        switch (menuChoice)
        {
            case 1:
                cout << "\nYou chose the Calculate Area option.\n";
                break;
            case 2:
                cout << "\nYou chose the Calculate Volume option.\n";
                break;
            case 3:
                std::cout << "\n\n     Good By\n\n";
                break;
            default:
                cerr << "\n     Invalid menu option.\n\n";
        }
    } while (menuChoice < 1 || menuChoice > 3);
            
    return menuChoice;
}

I like this idea because you only return a valid choice, so you do not have to worry about an invalid choice later.

In the "cout" statement when each line is a quoted string you do not need the insertion operator. Only when you mix a quoted string and a variable do you need the insertion operators to bring everything together.

I did add to the menu and switch for "Exit". The "Exit" should be a given choice for any menu. Although once in awhile you may not want an "Exit" from a sub-menu.

I would start with getting "main" to get a menu choice and then process it. Maybe something like:
1
2
3
4
5
6
7
8
9
10
11
int main()
{
    switch (MainMenu())
    {
        case 1:
            AreaMenu();
            break;
    }

    VolumeMenu();
}

I would get this working before yo starting the other parts.

Andy
Hello runningbear,

It is about time ofr bed since I am 3 hours ahead of you.

I did manage to get the program to give this output:

--Main Menu--
1) Calculate Area
2) Calculate Volume
3) Exit
Enter a menu choice: 0

     Invalid menu option.

--Main Menu--
1) Calculate Area
2) Calculate Volume
3) Exit
Enter a menu choice: 5

     Invalid menu option.

--Main Menu--
1) Calculate Area
2) Calculate Volume
3) Exit
Enter a menu choice: 1

You chose the Calculate Area option.


--Area Menu--
a) Rectangle
b) Circle
c) Right Triangle
Enter a menu choice: a

You chose the Rectangle option.

  This is in the "main" function. You chose case a. This is where you call a function to do something.

--Main Menu--
1) Calculate Area
2) Calculate Volume
3) Exit
Enter a menu choice:


Just to give you an idea.

Andy
Hello runningbear,

Since the only thing I have seen is fixing the code tags in your OP. I will cover a few points about what is there.

25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
int MainMenu()
{
    cout << "--Main Menu--"
        << "\n1) Calculate Area"
        << "\n2) Calculate Volume"
        << "\nEnter a menu choice: ";
    cin >> menuChoice;

    switch (menuChoice)
    {
        case 1:
            cout << "You chose the Calculate Area option.";
            break;
        case 2:
            cout << "You chose the Calculate Volume option." << endl;
            break;
        default:
            cout << "\nInvalid menu option." << endl;

            return menuChoice;
    }
}

The "cout" statement is good, although I would add 3 for exit.

Line 31 sends the input to a global variable before the switch has a chance to check the input.

The switch has no real use except to tell you what choice you made or if it was wrong.

The "default" prints an error message if the choice is invalid, but since the choice was put into a global variable it is to late and you do nothing to change the value of the global variable. The "default" case returns a global variable, which is unnecessary, because the global variable has been changed even if it is wrong. It really does not matter because you never capture the returned value or do anything with it back in "main".

The Function I showed you works much better because it only returns a valid choice. Also the variable defined in the function "menuChoice" is local to the function and after it returns its value it is destroyed until it is needed again.

In the function:
49
50
51
52
53
54
55
56
57
int AreaMenu()
{
    if (menuChoice == 1)
        cout << "\n\n--Area Menu--"
        << "\na) Rectangle"
        << "\nb) Circle"
        << "\nc) Right Triangle"
        << "\nEnter a menu choice: ";
    cin >> areaChoice;

73
74
75
    int AreaMenu = 0;
    return AreaMenu;
}

The first problem is line 51. Should "menuChoice " not == 1 the only line controlled by the if statement is line 52. Line 57 is past the if statement. Which means that it will be waiting for a menu choice even if a menu is not displayed.

The If statement does not include enough nor does it have an else if anything is wrong.

Also you are setting a global variable which could have an invalid menu choice.

I left out the switch because like the "MainMenu" function it has no real use. You are checking the input to a global variable after it has been given a value even if it is wrong and there is no way to change it.

Lines 73 and 74 I have no idea what you are trying to do here, but it does not work. First you are trying to create a variable with the same name as the function. Not sure if that would even work, but it is not a good idea to define a variable with the same name as the function name.

It really does not matter because you do not use the returned value of the function.

The last part I came to realize is that in the first 2 menu functions the switch only demonstrates that you know how to use it. The "cout" statements can be placed in a switch in "main.

The menu functions should just print the menu and accept a choice followed by verifying that the choice is valid before returning to "main".

I have shown you a start to the "mainMenu" function, but now I would change the switch to an if statement to print the error message and the loop would keep going until you enter a valid choice.

Andy
Hello runningbear,

Before I forget.

The "mainMenu" lists the choices and is expecting a number to be entered. The "AreaMenu" lists the choices and expects a letter to be entered.

To avoid any mistakes or problems all menus should use the same choices either numbers or letters. I would suggest using numbers because they are easier to deal with especially if you enter a wrong number.

That said my "MainMenu" function now looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int MainMenu()
{
    int menuChoice{};  // <--- Does not need to be a global variable.

    do
    {
        cout <<
            "--Main Menu--"
            "\n1) Calculate Area"
            "\n2) Calculate Volume"
            "\n3) Exit"
            "\nEnter a menu choice: ";
        cin >> menuChoice;

        if (!std::cin || (menuChoice < 1 || menuChoice > 3))
        {
            if (!std::cin)
            {
                std::cerr << "\n     Invalid input!  Must be a number.\n\n";

                std::cin.clear();
                std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.
            }
            else if (menuChoice < 1 || menuChoice > 3)
            {
                cerr << "\n     Invalid menu option.\n\n";
            }

        }
    } while (menuChoice < 1 || menuChoice > 3);

    return menuChoice;
}

This will deal with a number outside the proper range and also anything that is not a number.

See what you think.

Andy
Topic archived. No new replies allowed.