Something Similar but better

Pages: 12
Hello to everyone,
I have a question: there is something similar to the label goto? I don't want to use it because I know that is not very appreciate and at the same time in the programme that I wrote there are lots of menus and I don't want to use others do while.
Thanks you in advance
Flow control structures are what you want to use.
http://www.cplusplus.com/doc/tutorial/control/

Note that there is one valid use case for goto in C++; when you need to break out of deeply nested loops. Java has labeled break/continue, but C++ does not, so goto is a necessary evil in this one specific case.
Damn it. Ok, thank you :)
And if I would like to come back of only one level in a series ( two or more) of nested switch case, which is the solution? How can I apply the do while loop substituting goto's ?
There are possible errors but it is not the point, I want just to show my situation and try to make better this code without using goto but I find very difficult going back from the submenus to the previous levels of the entire menu.
Of course there are instructions in every case of the switches but I rase them because the code was too long

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
100
ret:switch (condition)
	{
	case('c') :
	case ('C'):
	{
	
		options_c :switch ( choice)
		{
		case (1):
		{
			switch (choice_r)
			{
			case (0) :
			{
				goto menu;
				break;
			}
			case (1):
			{
				break; 
			}

			case (2):
			{
				break;
			}
			case(3):
			}
				break;
			}
			case (4):
			{
				break;
			}
			}
			break;
		}
		case (2):
		{
			break;
		}
		case (3):
		{

			break;
		}
		default:
		{
			goto options_c;
		}
		}
		break;
	}
	case('r') :
	case ('R') :
	{
		
	options_r:switch (choice)
	{
	case (1) :
	{
			goto menu_restaurant;
		break;
	}
	case (2) :
	{
				goto menu_restaurant;
		break;
	}
	case (3) :
	{
		if (ch == 1) goto set_c; else goto menu_restaurant;

		break;
	}
	case (4) :
	{
		
	{
		 else goto menu_restaurant;
		break;
	}
	case(5) :
	{
		
		goto ret;

		break;
	}
	default:
	{
		goto options_r;
	}
	}
		break;
	}
	
		break;
	}
	}
Last edited on
It looks like you want to use functions instead of goto.
http://www.cplusplus.com/doc/tutorial/functions/
It seems a great idea!
However I've just one question: what would you suggest to come back to the superior level menu from a sub-menu: just calling the function of the superior level menu or using instructions such as return?
After some trials I found out that the first option seems working whereas the second one seems not.
Thanks of course for the help
You should return to go back up out of menus. Don't call the function of the menu you want to go to, that just eats up more memory as you use the program longer.
However I've just one question: what would you suggest to come back to the superior level menu from a sub-menu: just calling the function of the superior level menu or using instructions such as return?
After some trials I found out that the first option seems working whereas the second one seems not.
Thanks of course for the help

I'd either create a function or class for each menu.

Here's the function version, it's much more simple and shorter than the other one.

Note: I used recursion here in a bad way, see my next post for a better alternative.
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
#include <iostream>

int choose() {
    std::cout << "> ";
    int choice;
    std::cin >> choice;
    
    return choice;
}

void sub_menu_1()
{
    // print
    std::cout << "Sub Menu 1\n\n<0> Back\n\n";
    
    // choose
    int choice = choose();
    switch(choice)
    {
        case 0: break;
        default:
            std::cout << "<" << choice << ">" << " is invalid\n\n";
            break;
    }
    if(choice != 0)
        sub_menu_1();
}
void sub_menu_2()
{
    // print
    std::cout << "Sub Menu 2\n\n<0> Back\n\n";
    
    // choose
    int choice = choose();
    switch(choice)
    {
        case 0: break;
        default:
            std::cout << "<" << choice << ">" << " is invalid\n\n";
            break;
    }
    if(choice != 0)
        sub_menu_2();
}

void main_menu() {
    // print
    std::cout << "Main Menu\n\n<0> Back\n<1> SubMenu1\n<2> SubMenu2\n\n";
    
    // choose
    int choice = choose();
    switch(choice)
    {
        case 0: break;
        case 1: sub_menu_1(); break;
        case 2: sub_menu_2(); break;
        default:
            std::cout << "<" << choice << ">" << " is invalid\n\n";
            break;
    }
    if(choice != 0)
        main_menu();
}

int main()
{
    main_menu();
    
    return 0;   
}
Last edited on
I recommend not using recursion like that, Gamer2015. It's a bad habit that can cause big issues if applied to a large application.
Okey, yeah, it makes sense, if i were to stay in the main menu for to long I'd reach a pretty deep recursion level and therefore the call stack would grow very big...

How about this way?
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
#include <iostream>

int choose() {
    std::cout << "> ";
    int choice;
    std::cin >> choice;
    
    return choice;
}

void sub_menu_1() {
    int choice;
    do {
        // print
        std::cout << "Sub Menu 1\n\n<0> Back\n\n";
        
        // choose
        choice = choose();
        switch(choice)
        {
            case 0: break;
            default:
                std::cout << "<" << choice << ">" << " is invalid\n\n";
                break;
        }
    } while(choice != 0);
}
void sub_menu_2() {
    int choice;
    do {
        // print
        std::cout << "Sub Menu 2\n\n<0> Back\n\n";
        
        // choose
        choice = choose();
        switch(choice)
        {
            case 0: break;
            default:
                std::cout << "<" << choice << ">" << " is invalid\n\n";
                break;
        }
    } while(choice != 0);
}

void main_menu() {
    int choice;
    do {
        // print
        std::cout << "Main Menu\n\n<0> Back\n<1> SubMenu1\n<2> SubMenu2\n\n";
        
        // choose
        choice = choose();
        switch(choice)
        {
            case 0: break;
            case 1: sub_menu_1(); break;
            case 2: sub_menu_2(); break;
            default:
                std::cout << "<" << choice << ">" << " is invalid\n\n";
                break;
        }
    } while(choice != 0);
}

int main()
{
    main_menu();
    
    return 0;   
}
Last edited on
That works, but I like to use a more state-machine-like approach, where each function returns the next function to be called:
https://ideone.com/DUZONx (designed to run without interactive input)
Last edited on
How does this represent a menu/submenu structure?
I mean, you don't know the previous menu with that approach, right?
Gamer, refering to the second code that you've posted, does it work with a lot of level of nested sub-menus?
Gamer, refering to the second code that you've posted, does it work with a lot of level of nested sub-menus?
Yes, practically as many as you want.

Theoretically the deepest you can go is the maximum size of the call stack but that should not be of concern.
Gamer2015 wrote:
How does this represent a menu/submenu structure?
Don't use the word 'sub', it distracts from what is really going on.
Gamer2015 wrote:
I mean, you don't know the previous menu with that approach, right?
The functions in my example can take any parameters, if the previous menu is important for some reason you can pass it as a parameter (though really it shouldn't be important).
LB wrote:
though really it shouldn't be important
I think that's not up to you to decide and he clearly stated that he wanted that:
amidaraxar wrote:
what would you suggest to come back to the superior level menu from a sub-menu


LB wrote:
The functions in my example can take any parameters, if the previous menu is important for some reason you can pass it as a parameter
yeah, that's true, but wouldn't this cause the call stack to grow if you'd call the parent menu instead of just letting the function end?
You also said:
You should return to go back up out of menus.

Wouldn't that violate your own advice?


But well, I think OP allready found what he searched for
Thanks to both of you. I'm trying what you've said and, for the moment, is going well.
Thank you again :)
Gamer2015 wrote:
I think that's not up to you to decide and he clearly stated that he wanted that:
It is up to me if I want to give my personal opinion on what I believe proper design is. You don't come to a forum asking for people to tell you what you already believe.
Gamer2015 wrote:
yeah, that's true, but wouldn't this cause the call stack to grow if you'd call the parent menu instead of just letting the function end?
You also said: "You should return to go back up out of menus."
Wouldn't that violate your own advice?
The functions do not call each other, instead they return a std::function object which gets called by main. Please read the code more closely before criticising me.
The functions do not call each other, instead they return a std::function object which gets called by main. Please read the code more closely before criticising me.
I'm sorry, but I can't figure out how you can have any number of parent menus that way, could you show me?
It doesn't even require any parameters to be passed around: https://ideone.com/Bbv93E
Try running it yourself in your own IDE. Step through it in the debugger if you're still confused.
Last edited on
Pages: 12