-3

I am trying to make a menu but it doesn't close the program if you type nothing then press enter it will go to the menu again and you can try again with a number that works

:menu
echo.
echo 1- Tools
echo 2- Setting
echo 3- Games
echo 4- Info
echo x- Exit
set /p menu=?
if %menu%==1 (
goto tool
) else (
if %menu%==2 (
goto settings
) else (
if %menu%==3 (
goto game
) else (
if %menu%==4 (
goto info
) else (
if %menu%==x )
goto exits
) else (
goto menu

:tool
title tools by gloxidia
pause
:settings
title settings by gloxidia
pause
:game
title game by gloxidia
pause
:exits
title exit by gloxidia
exit

I can't get it to work in my program I am working on

Magoo
  • 77,302
  • 8
  • 62
  • 84
Gloxidia
  • 1
  • 5
  • at the moment it just crashes when you type eny number then press enter – Gloxidia Dec 23 '20 at 19:29
  • Does this answer your question? [set /p empty answer crash](https://stackoverflow.com/questions/27489804/set-p-empty-answer-crash) – aschipfl Dec 23 '20 at 21:58
  • 2
    This would be a good time to use `Choice` doing so will allow you to limit the responces to only those presented as acceptable answers, Check out the options `choice /?` – Ben Personick Dec 24 '20 at 04:24

3 Answers3

2

The daily "menu" question.

Two items with your code as it stands:

  1. If you use parenthesised code (code blocks) in an if statement, then each ( must be balanced by a ). You have many more ( than ) so your if statement will fail as it is invalid syntax.

  2. If you press just Enter then the variable (in this case, menu) remains unchanged, it is not automatically set to nothing.

It's very possible that menu will in fact be empty when you start the batch, but to make sure, put

set "menu="

before the set /p statement.

BUT the downside of this is that if menu is empty when the if is processed, for instance,

if %menu%==2 (

will be interpreted as

if ==2 (

which is invalid syntax.

The classic cure, generally, is to code

if "%menu%"=="2" (

where the quotes are both included in the comparison and partially-sanitise the input so that a value that contains spaces will now be correctly interpreted.

BUT (again) there are problems. The input is uncontrolled, so you could enter "hello" or hello or %hello% or he"llo, which will all cause problems with the if statement, even if the if "%menu%"=="2" syntax is used.

Hence, the solution is to use choice - there are many examples available on SO - just use the search facility.

Also please consider your code structure and logic. A long cascaded if/then sequence is a nightmare.

Consider

if "%menu%"=="2" (goto somewhere)
rem MENU must be "not 2" to reach here
if "%menu%"=="3" (goto somewhereelse)
rem MENU must be "neither 2 nor 3" to reach here
if "%menu%"=="4" (goto somewhereelseagain)
rem MENU must be "neither 2,3 nor 4" to reach here

But really, you're far better off with choice.

Magoo
  • 77,302
  • 8
  • 62
  • 84
0

The main problem, is with all of your unnecessary if / else blocks. I added some indentation to hopefully more clearly show you what's happening, but essentially you opened many parentheses without closing them.

:Menu
Set "MenuItem="
Echo=
Echo 1- Tools
Echo 2- Setting
Echo 3- Games
Echo 4- Info
Echo X- Exit
Set /P "MenuItem=?"
If "%MenuItem%" == "1" (
    GoTo Tools
) Else (
    If "%MenuItem%" == "2" (
        GoTo Settings
    ) Else (
        If "%MenuItem%" == "3" (
            GoTo Games
        ) Else (
            If "%MenuItem%" == "4" (
                GoTo Info
            ) Else (
                If /I "%MenuItem%" == "X" (
                    GoTo Exits
                ) Else (
                    GoTo Menu
                )
            )
        )
    )
)

:Tools
Title Tools by Gloxidia
Pause
GoTo Exits

:Settings
Title Settings by Gloxidia
Pause
GoTo Exits

:Games
Title Games by Gloxidia
Pause
GoTo Exits

:Info
Title Info by Gloxidia
Pause

:Exits
Title Exits by Gloxidia
Pause
Exit /B

To help protect the variable, with regards some poison characters and empty input, I've added doublequotes on either side of the If comparison. Additionally in order to prevent the code from cycling through all remaining commands and exiting before you've had time to notice it, I've added some GoTo commands, and changed Exit to Exit /B.

Here it is with again without the unnecessary If / Else command blocks.

:Menu
Set "MenuItem="
Echo=
Echo 1. Tools
Echo 2. Settings
Echo 3. Games
Echo 4. Info
Echo X. Exit
Set /P "MenuItem=?"
If "%MenuItem%" == "1" GoTo Tools
If "%MenuItem%" == "2" GoTo Settings
If "%MenuItem%" == "3" GoTo Games
If "%MenuItem%" == "4" GoTo Info
If /I "%MenuItem%" == "X" GoTo Exits
GoTo Menu

:Tools
Title Tools by Gloxidia
Pause
GoTo Exits

:Settings
Title Settings by Gloxidia
Pause
GoTo Exits

:Games
Title Games by Gloxidia
Pause
GoTo Exits

:Info
Title Info by Gloxidia
Pause

:Exits
Title Exits by Gloxidia
Pause
Exit /B

The biggest issue, with the above code, is that it is using the wrong command, set /p is not the correct command to use for accepting known single character input from a short list.

What you should be using is the choice command utility:

:Menu
Echo=
Echo 1. Tools
Echo 2. Settings
Echo 3. Games
Echo 4. Info
Echo X. Exit
%SystemRoot%\System32\choice.exe /C 1234X
If ErrorLevel 5 GoTo Exits
If ErrorLevel 4 GoTo Info
If ErrorLevel 3 GoTo Games
If ErrorLevel 2 GoTo Settings

:Tools
Title Tools by Gloxidia
Pause
GoTo Exits

:Settings
Title Settings by Gloxidia
Pause
GoTo Exits

:Games
Title Games by Gloxidia
Pause
GoTo Exits

:Info
Title Info by Gloxidia
Pause

:Exits
Title Exits by Gloxidia
Pause
Exit /B
Compo
  • 36,585
  • 5
  • 27
  • 39
0

The exact answer to your question is that you use else ( but never close the parenthesis.

You could just fix rhis but I suggest you follow some of the advice in this q and others.

To simply fix your existing batch script:

umber that works

:menu
 echo.
 echo 1- Tools
 echo 2- Setting
 echo 3- Games
 echo 4- Info
 echo x- Exit
set /p "menu=?"
if "%menu%" EQU "1" ( goto :tool ) else (
  if "%menu%" EQU "2" ( goto :settings ) else (
    if "%menu%" EQU "3" ( goto :game ) else (
      if "%menu%" EQU "4" ( goto :info ) else (
        if /I "%menu%" EQU "x" ( goto :exits )
      )
    )
  )
)

Goto :Menu

:tool
  title tools by gloxidia
  pause
Goto :eof

:settings
  title settings by gloxidia
  pause
Goto :eof

:game
  title game by gloxidia
  pause
Goto :eof

:exits
  title exit by gloxidia
  Echo=I can't get it to work
  Pause
Goto :eof

Alternatives:

You could forgo the GOTO :label portion and write your code insise the nested if statements

Probably you have rhem for a good reason though, so:

You could simply call the labels directly and ignore the bested IF making it much more streamlined.

This is rhat streamlined alternative





UGH even my edits saying I'm annoyed seem to have screwed up, its very late and I am on mobile, I just need to relax and not spend all night qriting this



Ben Personick
  • 3,074
  • 1
  • 22
  • 29