Shady Programmer
Shady Programmer

Reputation: 824

How to increment for loop variable in batch script?

::Compare with available valid arguments
FOR /L %%i IN (1,1,!avArgc!) DO (
    FOR /L %%j IN (1,1,!argc!) DO (
        IF !avArgv[%%i]!==!argv[%%j]! (
            echo Match: !avArgv[%%i]!

            ::Check the next option
            SET /A nextArg=%%j
            SET /A nextArg+=1
            FOR /L %%n IN (!nextArg!,1,!nextArg!) DO ( 
                IF !nextArg! LEQ !argc! ( 
                    echo next arg: !argv[%%n]!
                    call :CheckSubOption
                )
            ) 
        )
    )
)

In my above code example - How do I take for loop variable like %%j and increment itself within the for loop like this %%j++ ? Current solution that I have (which is messy and I don't like it) is to create a new variable and set it to the value of %%j and then increment that variable and start using that variable like this:

::Check the next option
SET /A nextArg=%%j
SET /A nextArg+=1

Upvotes: 4

Views: 8992

Answers (2)

Jouster500
Jouster500

Reputation: 772

Observing your code and your intention, it would seem that you would want to skip numbers during the loop structure. The way you want to change it though would be destabilizing. In most scripting languages such as matlab,bash, and batch, the variable that is used in for-loops serves as a frame of reference within the loop. When you tell the code to run a particular for-loop, it will run that computation regardless if the parameters of it changed. A real world example of this is the professor who is using outdated figures to solve a problem and it isnt until the next day he receives the new figures. The professor cant change his answer accordingly because he doesnt have the new data yet.

This does not mean this problem is unsolvable. In fact there are a variety of ways to approach this. The first one which is a little more complicated involves a nested For structure.

@echo off
set /p maxLength=[Hi times?]
set skip=0

FOR /L %%i IN (1,1,%maxLength%) DO (call :subroutine %%i)

echo alright im done.
pause 
GOTO :eof

rem the below code uses a for loop structure that only loops 1 time based on the passed argument from the overall for loop as so to make changes to how its run.

:subroutine
set /a next=%1+%skip%
 FOR /L %%r IN (%next%,1,%next%+1) DO (call :routine %%r)
 GOTO :eof

:routine
if %1==3 (set /a skip=1)
echo %skip%
echo %next%
echo %1
pause
GOTO :eof

When running the program, the variable next will skip the value of 3 if the maxlength variable is greater than 3.

  • The reason this is so is because the nested for-loop only runs once per iteration of the overall for loop

. This gives the program time to reset the data it uses, thanks to the call command which serves as a way to update the variables. This however is extremely inefficient and can be done in much less lines of code.

The second example uses GOTO's and if statements.

@echo off
set jump=1
:heyman
set /A "x+=%jump%"
if %x%==4 (set /A "jump=2")
echo %x%
if %x% LSS 10 goto heyman
echo done!

This code will essentially echo the value of x thats incremented each time until it reaches the value of 10. However when it reaches 4, the increment increases by 1 so each time it runs the loop increments the x value by 2. From what you wanted, you wanted to be able to change the way the value of %%j increments, which can not be done as %%j is a statement of where the for-loop is in its computation. There is no difference in what can be accomplished with for-loops and goto statements except in how they are handled.

While i unfortunately don't have the correct form of your code yet, i know that code examples i have given can be utilized to achieve your particular desire.

Upvotes: 1

dolmen
dolmen

Reputation: 8696

The general solution for thoses case is to not rely on blocks inside loops/if but instead to use subroutines where you are not blocked by the level of evaluation.

FOR /L %%i IN (1,1,!avArgc!) DO call :Loop1 %%i
goto :EOF

:Loop1
FOR /L %%j IN (1,1,!argc!) DO call :Loop2 %1 %%j
goto :EOF

:Loop2
IF !avArgv[%1]!==!argv[%2]! (
            echo Match: !avArgv[%1]!

            ::Check the next option
            SET /A nextArg=%2+1
            call :CheckOpt %nextArg%
)
goto :EOF

:CheckOpt
IF %1 LEQ %argc% ( 
    echo next arg: !argv[%1]!
    call :CheckSubOption
)

Upvotes: 1

Related Questions