0

[simple program that recieves an integer as input and prints if that number is trivial or not]

when i run this i get an error "( was unexpected at this time"

@echo off
set /a i=2
set /p input="enter an integer: "
set /a n=input
set /a t=n/2

:loop1      
    if %t% LSS %i% (
        goto trivial
    ) else (
        set /a t0=n%i
        if %t0%==0 (
            goto notTrivial
        ) else (
            set /a i=i+1
            goto loop1
        )
    )
:trivial
    echo %n% is trivial
    goto endd
:notTrivial
    echo %n% is not trivial
:endd
pause > nul

but when I remove else statement in loop1 (which is btw unnecessary (because of goto command in if block)) it works

:loop1      
    if %t% LSS %i% (
        goto trivial
    ) 
        set /a t0=n%i
        if %t0%==0 (
            goto notTrivial
        ) else (
            set /a i=i+1
            goto loop1
        )

(how) is this possible?

marko
  • 43
  • 6
  • @Paul, if you're talking about the `LSS` comparison, then it's a *bad* idea to prepend zeros as `if` interpretes such numbers as octal rather than decimal ones; when using comparison operators other than `==`, `if` does *numeric* comparisons anyway (as long as the arguments are not surrounded by `""`); but if something like `08` or `09` is encountered, which is not a valid octal number, string comparison is enforced, which might lead to unexpected results... – aschipfl Oct 15 '15 at 20:55
  • @aschipfl I was referring to this http://stackoverflow.com/a/17193616 – Paul Oct 15 '15 at 21:26
  • @Paul, because of the 32-bit limitation of numbers, which covers the range from -2147483648 to +2147483647, so greater numbers are not interpreted correctly and therefore not compared properly; so Jeb is using string comparison as a smart work-around... – aschipfl Oct 15 '15 at 22:10

2 Answers2

5

When you remove the else clause, the code inside it is now out of any block.

Why does it matter? Because in batch files, lines or blocks of lines (code inside parenthesis) are first parsed and then executed. While parsed variable read operations are removed, being replaced with the value inside the variable at parse time, before starting to execute the command (more here).

So, in this code

   ) else (
        set /a t0=n%i
        if %t0%==0 (
            goto notTrivial
        ) else (
            set /a i=i+1
            goto loop1
        )
    )

you change the value of the variable t0, but you can not retrieve this changed value inside the same block. But if you remove the else clause the code is not inside a block and everything works as intended (except syntax errors, try with set /a "t0=n %% i").

Community
  • 1
  • 1
MC ND
  • 69,615
  • 8
  • 84
  • 126
1

Firstly, you need to state the modulo operator % as %% in batch files.
Secondly, just move the command set /a t0=n%%i up before the if block begins, then it will work:

:loop1      
    set /a t0=n%%i
    if %t% LSS %i% (
        goto trivial
    ) else (
        if %t0% EQU 0 (
            goto notTrivial
        ) else (
            set /a i+=1
            goto loop1
        )
    )

So the change of variable t0 is moved outside of a command block ().


Alternatively, you could also enable delayed expansion:

setlocal EnableDelayedExpansion

rem INITIAL CODE PORTION...

:loop1      
    if %t% LSS %i% (
        goto trivial
    ) else (
        set /a t0=n%%i
        if !t0! EQU 0 (
            goto notTrivial
        ) else (
            set /a i+=1
            goto loop1
        )
    )

rem REMAINING CODE PORTION...

endlocal

You will notice the !t0! type expansion which, in contrast to %t0%, will expand t0 at execution time rather than parse time.
See also setlocal /? and endlocal /? for more information about these commands.

Community
  • 1
  • 1
aschipfl
  • 33,626
  • 12
  • 54
  • 99