0

I am trying to use nested if-else statements in order to implement or operator.
The problem is that the code only works outside the last nested else statement and I can't figure out why.

I added some notes marked with // that are not actually in the script to help you get a clue of what I am trying to do.

Here is my batch script:

:computerMakePick
setLocal
    set /a currentNumber= 15
    set /a addOne=%currentNumber%+1
    set /a addTwo=%currentNumber%+2

    //the next segment implements OR operator for two conditions using nested if-else statement
    if %addOne% == 7 (  //checking first condition.
        echo Computer chose: %addOne%
        set /a currentNumber= %addOne%
    )else (
        if %addTwo% == 8 ( // now checking: OR second condition
            echo Computer chose: %addTwo%
            set /a currentNumber= %addTwo%
        )else ( // if not both of the above then do this.  NOW this section below doesn't work
            set /a bottomlimit= 1
            set /a upperlimit= 2
            set /a limit=%upperlimit%-%bottomlimit%+1
            set /a randomChoice= %bottomlimit% + %RANDOM% %% %limit%
            set /a currentNumber= %currentNumber%+%randomChoice%        
            echo Computer chose: %currentNumber%
        )
    )

endLocal & set /a currentNumber= %currentNumber%
goto :eof

If I take the last else section to outside like this below, then it works:

:computerMakePick
setLocal
    set /a currentNumber= 15
    set /a addOne=%currentNumber%+1
    set /a addTwo=%currentNumber%+2

    //the next segment implements OR operator for two conditions using nested if-else statement
    if %addOne% == 7 (  //checking first condition.
        echo Computer chose: %addOne%
        set /a currentNumber= %addOne%
    )else (
        if %addTwo% == 8 ( // now checking: OR second condition
            echo Computer chose: %addTwo%
            set /a currentNumber= %addTwo%
        )else ( 
            echo.    // need to put something in here or else it doesn't work.
        )             // could also delete this last else-statment but it doesn't matter
    )    

//now this below works fine. and I don't understand why under second-else section it doesn't
set /a bottomlimit= 1
set /a upperlimit= 2
set /a limit=%upperlimit%-%bottomlimit%+1
set /a randomChoice= %bottomlimit% + %RANDOM% %% %limit%
set /a currentNumber= %currentNumber%+%randomChoice%        
echo Computer chose: %currentNumber%

endLocal & set /a currentNumber= %currentNumber%
goto :eof

By saying it's not working I mean if I print the values of each variable: bottomlimit, upperlimit, limit, etc. when they are defined inside the second else statement, for example for the command line echo value of limit is = %limit% I get blanks (nothing).

Why is this happening and how can I fix it to work inside the second else statement?

Mofi
  • 46,139
  • 17
  • 80
  • 143
David8988
  • 79
  • 1
  • 1
  • 7
  • for inline comments you can [`%= write like this in any places=%`](https://stackoverflow.com/a/12408045/995714) or just use [`& rem comment to end of line`. `&:: comment to end of line` also works](https://superuser.com/a/82244/241386). That way people don't need to remove `//` lines to try your code – phuclv Sep 23 '17 at 05:51

2 Answers2

2

Use the following code:

@echo off
:computerMakePick
setLocal

set "currentNumber=15"
set /a addOne=currentNumber + 1
set /a addTwo=currentNumber + 2

rem // the next segment implements OR operator for two conditions using nested if-else statement
if %addOne% == 7 (        rem // checking first condition.
    echo Computer chose: %addOne%
    set "currentNumber=%addOne%"
) else if %addTwo% == 8 ( rem // now checking: OR second condition
    echo Computer chose: %addTwo%
    set "currentNumber=%addTwo%"
) else ( rem // if not both of the above then do this.  NOW this section below doesn't work
    set "bottomlimit=1"
    set "upperlimit=2"
    set /a limit=upperlimit - bottomlimit + 1
    set /a randomChoice=bottomlimit + %RANDOM% %% limit
    set /a currentNumber+=randomChoice
    setlocal EnableDelayedExpansion
    echo Computer chose: !currentNumber!
    endlocal
)

endLocal & set "currentNumber=%currentNumber%"
goto :EOF
  1. Environment variables are always of type string. So even on using integers, the numbers are stored in memory as strings and not as integers. Therefore don't use set /a variable=number if there is no real reason to do so as this results in converting number from string to integer for the arithmetic expression, and converting it back from integer to string for assigning the result of this arithmetic expression to environment variable.

  2. Usage of environment variable expansion within an arithmetic expression which is the string after set /a is usually nonsense as Windows command interpreter automatically interprets each string not being a number or an operator as name of an environment variable whose current value has to be converted to an integer for evaluation of the expression.
    Yes, whether immediate nor delayed expansion is needed within an arithmetic expression even when the set /a command line is within a command block.

  3. And in batch files // is not a comment, use command REM and take into account that Windows command interpreter first parses the lines with command REM and then executes the command if there is no syntax error, see %~ in REM statement.

For more details:

  1. Run in a command prompt window set /? and really read carefully everything of output help.
    If you use any of the logical or modulus operators, you will need to
    enclose the expression string in quotes.  Any non-numeric strings in the
    expression are treated as environment variable names whose values are
    converted to numbers before using them.  If an environment variable name
    is specified but is not defined in the current environment, then a value
    of zero is used.  This allows you to do arithmetic with environment
    variable values without having to type all those % signs to get their
    values.
    
  2. Read the answer Why is no string output with 'echo %var%' after using 'set var = text' on command line?
  3. Read the answer on IF ELSE syntax error within batch file?
Graham
  • 7,431
  • 18
  • 59
  • 84
Mofi
  • 46,139
  • 17
  • 80
  • 143
-1

Variables within the else-statement are not expanded. Use setlocal enabledelayedexpansion instead and denote your variables with exclamation marks:

:computerMakePick
setLocal enabledelayedexpansion
    set /a currentNumber= 15
    set /a addOne=%currentNumber%+1
    set /a addTwo=%currentNumber%+2

    if %addOne% == 7 (
        echo Computer chose: %addOne%
        set /a currentNumber= %addOne%
    )else (
        if %addTwo% == 8 (
            echo Computer chose: %addTwo%
            set /a currentNumber= %addTwo%
        )else (
            set /a bottomlimit= 1
            set /a upperlimit= 2
            set /a limit=!upperlimit!-!bottomlimit!+1
            set /a randomChoice= !bottomlimit! + !RANDOM! %% !limit!
            set /a currentNumber= !currentNumber!+!randomChoice!        
            echo Computer chose: !currentNumber!
        )
    )

endLocal & set /a currentNumber= %currentNumber%
goto :eof
Regejok
  • 436
  • 2
  • 5
  • 1
    No, don't expand variables within an arithmetic expression at all. Use the variable names without `%` and without `!` in arithmetic expressions, except a variable name contains a space character or an operator like hyphen character which are both not good in environment variable names in general. – Mofi Jun 20 '17 at 14:48
  • @mofi That doesn't work, because it's still within an `else` statement. In any other case, you don't need expansion for arithmetic operations. – Regejok Jun 20 '17 at 14:52
  • 3
    Look on my answer which works fine. Look on block from help. Yes, the last line with `echo Computer chose: !currentNumber!` needs delayed expansion, but only this line, not the other lines with the arithmetic expressions. And this __ECHO__ line does most likely not exist in real code of questioner. – Mofi Jun 20 '17 at 14:55