Hi I'm making a menu in C++ for a sudoku puzzle solver program I've already wrote using switch setence.
I've wrote that code:

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<iostream.h>

int opcio1();
int opcio2();
int opcio3();


void main(){

    char sel;

 

    cout <<"Sudoku\n\n\n"<<endl;
    cout <<"1. How to\n\n"<<endl;
    cout <<"2. Sudoku generator\n\n"<<endl;
    cout <<"3. Play!\n\n"<<endl;
    cout <<"4. Exit\n\n"<<endl;
   
    cout <<"Select an option, please..."<<endl;

 

    do{

        sel=getch();

    }while((sel<'1' || sel>'4')&&sel!=27); //esc=ASCII 27 

 

    switch(sel){

        case '1':

            opcio1();

            break;

 

        case '2':

            opcio2();

            break;

 

        case '3':

            opcio3();

            break;

 


        case 27:

            return;

                
    }

}

 

 

void opcio1(){

    cout <<"How to\n\n"<<endl;

}

 

void opcio2(){

   cout <<"Sudoku generator\n\n"<<endl; 

}

 

void opcio3(){

    cout <<"Play\n\n"<<endl;

}

This code works.
My question is how to do a return to the menu option inside every option in the menu?
I've tried to use goto but it only works for inside the same function.
Thank you

Recommended Answers

All 19 Replies

Simplest is call main from every function you call in switch
ex

void opcio1(){

    cout <<"How to\n\n"<<endl;
    main();
}

However, this is not the best way, but I am sure it will give another idea of implimenting menu in a function.

Okay..
Try this

// Menu.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<iostream>
using namespace std;


void opcio1();
void opcio2();
void opcio3();


void main(){

	char sel = '0';


	while(sel != '4')
	{
		cout <<"Sudoku\n\n\n"<<endl;
		cout <<"1. How to\n\n"<<endl;
		cout <<"2. Sudoku generator\n\n"<<endl;
		cout <<"3. Play!\n\n"<<endl;
		cout <<"4. Exit\n\n"<<endl;

		cout <<"Select an option, please..."<<endl;



		do{

			sel=getch();

		}while((sel<'1' || sel>'4')&&sel!=27); //esc=ASCII 27 

		switch(sel){

		case '1':

			opcio1();

			break;

		case '2':

			opcio2();

			break;

		case '3':

			opcio3();

			break;

		case 27:
		case '4':
			return;
		
		default:
			cout << "Bad Option"<<endl; //Well it will never execute!
			break ;


		}
	}

}





void opcio1(){

	cout <<"How to\n\n"<<endl;

}



void opcio2(){

	cout <<"Sudoku generator\n\n"<<endl; 

}



void opcio3(){

	cout <<"Play\n\n"<<endl;

}

How about this?

// Menu.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<iostream>
using namespace std;


void opcio1();
void opcio2();
void opcio3();


void main(){

	char sel;
	do {
		cout <<"Sudoku\n\n\n"<<endl;
		cout <<"1. How to\n\n"<<endl;
		cout <<"2. Sudoku generator\n\n"<<endl;
		cout <<"3. Play!\n\n"<<endl;
		cout <<"4. Exit\n\n"<<endl;

		cout <<"Select an option, please..."<<endl;

again:
		sel=getch();
		switch(sel){
		  case '1':
			opcio1();
			break;
		  case '2':
			opcio2();
			break;
		  case '3':
			opcio3();
			break;
		  case 27:
		  case '4':
			return;
		  default:
			goto again;
			break ;
		}
	} while(true);

}

void opcio1() {
	cout <<"How to\n\n"<<endl;
}

void opcio2() {
	cout <<"Sudoku generator\n\n"<<endl; 
}

void opcio3() {
	cout <<"Play\n\n"<<endl;
}

dubeyprateek's second version is the best presented.

You should not ever call main( ) from within you program, that essentially restarts a new instance of the program!

Avoid using labels and goto's.

Personally, I'd use a do...while loop structure, so that you don't have to force the loop condition true before entering. The logic of a do...while is that you intend to show the menu and get a user choice at least once, and let the logic of the switch and loop condition take it from there.
Val

commented: Excellent points +12

>You should not ever call main( ) from within you program,
>that essentially restarts a new instance of the program!
No, it essentially doesn't compile. C++ doesn't allow recursive calls to main.

>You should not ever call main( ) from within you program, that essentially restarts a new instance of the program!
Calling main does not starts new instance of the program, you can verify it in task manager.

>No, it essentially doesn't compile. C++ doesn't allow recursive calls to main.

Is it compiler spesefic? I can very well call main recursive in my cpp program. At max you expect warning "C4717: 'main' : recursive on all control paths, function will cause runtime stack overflow" in Visual Studio 2005.

>I can very well call main recursive in my cpp program.
Undefined behavior includes working as you expect. That doesn't make it any more correct.

@Narue
Why do you think it is a undefined behavior ? main is just like any other function once you call it within the application.
What is so special with main ? apart from it is a conventional startup function called within mainCRTStartup.

0:001> ~* kp 100

0 Id: 3f04.1acc Suspend: 1 Teb: 7ffdf000 Unfrozen
ChildEBP RetAddr
001ff6e0 7671199a ntdll!KiFastSystemCallRet(void)
001ff6e4 767119cd USER32!NtUserGetMessage(int a1 = 2094884, int a2 = 0, int a3 = 0, int a4 = 0)+0xc
001ff700 0004149c USER32!GetMessageW(struct tagMSG * pmsg = 0x001ff724, struct HWND__ * hwnd = 0x00000000, unsigned int wMsgFilterMin = 0, unsigned int wMsgFilterMax = 0)+0x33
001ff740 00041971 notepad!WinMain(struct HINSTANCE__ * hInstance = 0x00040000, struct HINSTANCE__ * hInstPrev = 0x00000000, char * lpAnsiCmdLine = 0x00372577 "", int cmdShow = 10)+0xec
001ff7d0 76ca3833 notepad!__mainCRTStartup(void)+0x140

001ff7dc 76f7a9bd kernel32!BaseThreadInitThunk(unsigned long RunProcessInit = 0x8ab90, <function> * StartAddress = 0x00000118, void * Argument = 0x7ffd3000)+0xe
001ff81c 00000000 ntdll!_RtlUserThreadStart(<function> * StartAddress = 0x000431f8, void * Argument = 0x7ffd3000)+0x23

# 1 Id: 3f04.211c Suspend: 1 Teb: 7ffde000 Unfrozen
ChildEBP RetAddr
012cfd40 76fcf0a9 ntdll!DbgBreakPoint(void)+0x1
012cfd70 76ca3833 ntdll!DbgUiRemoteBreakin(void * Context = 0x00000000)+0x3c
012cfd7c 76f7a9bd kernel32!BaseThreadInitThunk(unsigned long RunProcessInit = 0, <function> * StartAddress = 0x76fcf06d, void * Argument = 0x00000000)+0xe
012cfdbc 00000000 ntdll!_RtlUserThreadStart(<function> * StartAddress = 0x76fcf06d, void * Argument = 0x00000000)+0x23

I don't see any problem calling main from any function. It is nothing special and not at all a compile time error.

If your logic can take care of stack overflow there is absolutely no problem calling main recursively.

Please let me know if I am wrong.

>Why do you think it is a undefined behavior ?
Because the C++ standard says it's undefined behavior. Allow me to quote the standard and explain why:

The function main shall not be used within a program.

Here's a hint for interpreting the standard: Anytime the word "shall" appears, it means that failing to shall results in undefined behavior or a diagnostic that stops undefined behavior by refusing to compile.

>Please let me know if I am wrong.
You're wrong, and your logic is flawed because you're using implementation details to prove a point that hinges on portable, standard C++ code.

#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<iostream.h>

int opcio1();
int opcio2();
int opcio3();


int main()
{

    char sel;

 
   for (;;)
{
    cout <<"Sudoku\n\n\n"<<endl;
    cout <<"1. How to\n\n"<<endl;
    cout <<"2. Sudoku generator\n\n"<<endl;
    cout <<"3. Play!\n\n"<<endl;
    cout <<"4. Exit\n\n"<<endl;
   
    cout <<"Select an option, please..."<<endl;

    cin >> sel;

if (sel<'1' || sel>'4')&&sel!=27); //esc=ASCII 27 

 {

    switch(sel){

        case '1':

            opcio1();

            break;

 

        case '2':

            opcio2();

            break;

 

        case '3':

            opcio3();

            break;

 


        case 27:

            return 0; // to exit

                
    }
else
{
cout << "Invalid";
continue; // reloop
}
}
}

 

 

void opcio1(){

    cout <<"How to\n\n"<<endl;

}

 

void opcio2(){

   cout <<"Sudoku generator\n\n"<<endl; 

}

 

void opcio3(){

    cout <<"Play\n\n"<<endl;

}

Hmmm, badly formatted code.

Anytime we see

}
}
}

we know we're not going to be able to follow the code easily. See this and format your code properly. And please don't post code without some kind of explanation. New people can't necessarily understand uncommented code without explanations.

> Please let me know if I am wrong.
If you're going to have any chance of winning these arguments, you need to quote "chapter and verse" from the relevant ANSI standard, not just demonstrate what your current "foo" compiler happens to do with one specific test case. Because there's no reason to assume that every other program, or any other "bar" compiler will behave the same.

People avoid using labels and goto's because of its ugliness and the difficulty of understanding the code and maintanance. As long as people can make their code look clean and understandable, I think it is not the case.

Anytime I see:
for ( ;; )
I cringe. First, if you want an infinite loop, just say so:
while( true )

More importantly, such usage implies a kludgy way of breaking out of the loop, such as the return( 0 ) used in TAG's sample. Loop exit condition should be evident in the loop's control - busting out prematurely should only be for irrecoverable problems.

OK, I'll admit to a common case of premature loop exit - search and sort functions, when they've completed their task prior to loop completion. Even these can be modified so the loop exits gracefully, then the function returns.

Just my 2 cents.
Val

@Narue

>Please let me know if I am wrong.
You're wrong, and your logic is flawed because you're using implementation details to prove a point that hinges on portable, standard C++ code.

I admit I was wrong. thanks for pointing me to standered C++ documentation.
The function main shall not be called from within a program. The linkage (3.5) of main is
implementationdefined.
A program that takes the address of main, or declares it inline or static is
illformed.

ftp://ftp.research.att.com/dist/c++std/WP/CD2/body.pdf

Thanks
Prateek

Anytime I see:
for ( ;; )
I cringe. First, if you want an infinite loop, just say so:
while( true )

for ( ; ; ) also says you want an infinite loop, you personally just don't like the syntax. The reason people use for ( ; ; ) , and the reason why I believe it's superior is that some compilers will give you a spurious warning with the while loop about a constant loop condition. I have yet to see such a warning with the infinite for loop. Some programmers like to have a clean compile.

>More importantly, such usage implies a kludgy way of breaking out of the loop
Loops in C++ only offer termination at the beginning and termination at the end. It's silly to suggest that one wouldn't need to terminate somewhere in the middle, and people who try to force that kind of logic when it's ill suited are the ones who end up with kludgy code.

Anytime I see:
for ( ;; )
I cringe. First, if you want an infinite loop, just say so:
while( true )
Val

This is totally different case from the avoid using goto label. People avoid using goto label because of its ugliness and the difficulty of understanding and mantaining the code. Moreover, all most of the code using goto label can be replaced with loop, which is much more clear. As long as I keep my code clear and understandable, why would you complain that what I have used is bad?. Could you please tell how terrible my code is?

the reason why you can't call main is because when you run a program you have a pointer at the current command that is being executed. When you call a function, the function code is copied onto the current stack (your program memory) and the pointer is jumped to the beginning of it. At the end of the function, its jumps back to main and the memory used by the function is returned to the OS. If you call main, the functions you called before are never ended and the memory is not reclaimed by the OS until the program is terminated. The problem is that if you keep calling main along with other functions, you will overflow the stack (run out of memory for your program to use). Although unlikely for small applications where the user probably wont keep going in and out of the functions, it is still bad and can cause a memory leak!

Sir,
Let me suggest that your 'Menu' itself should be a function, say , Menu(), for these lines:
cout <<"Sudoku\n\n\n"<<endl;
cout <<"1. How to\n\n"<<endl;
cout <<"2. Sudoku generator\n\n"<<endl;
cout <<"3. Play!\n\n"<<endl;
cout <<"4. Exit\n\n"<<endl;

This avoids the issue of using any 'goto and labels.'
As for calling main() within your program, many compilers will allow you to do so, but doing so shows a lack of proper software logic design for a true structured programming solution. In addition your code 'will' be prone to all the possible errors mentioned previously. Finally, unless your 3-functions to solve the puzzle either solve it completely or write their interim solutions to a a read/write file their data will almost certainly be lost at some important point.

If you worked for our shop and tried to pass code like this to our teams, there would be serious discussions about your methods. Programming can be an 'art' in conception, but it should be a science in implementation.

Go back to basics and design the solution before you write the code.
Please, try it again.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.