So I've just about finished a really complicated batch file (first big one I've wrote) and i'm stuck at the last part. The program needs variables to be generated as the user needs them. I figured that part out, but now i'm having trouble calling them.
This is what i have (sorry its easier to show you than explain)
set /A mquanto=%mquant%
:varmakerstart
set /p compname=Machine Number:
echo set /A comp%mquanto%=\\LAB-%compname%
set /A mquanto=%mquanto%-1
if %mquanto% lss 1 goto startloop
goto varmakerstart
:startloop
set /A mquanto=%mquant%
:loop
set /A tcomp=
What i need is a way to set one of the variables created in the 4th line to the variable tcomp, and i can't have more or less variables than the value of mquant. I'm sorry about any vagueness and i will try to explain any thing that is needed.
if your going to set a variable to equal another then this is an easy solution....
set a=
set b=1
set /p a=?:
if %a%==%b% goto :NEXT
:NEXT
you have entered the correct number! The number was %b%.
ping localhost -n 3 >nul
I hope this helps a bit!
Related
I have a bit of (Bad) Code for encrypting text, but to be able to decrypt it needs to have something inbetween the numbers. I want to fit random letters inbetween the numbers so it looks less obvious, this is where i got to:
#echo off
setlocal enableDelayedExpansion
set /p code=Text:
set chars=0123456789abcdefghijklmnopqrstuvwxyz
for /L %%N in (10 1 36) do (
for /F %%C in ("!chars:~%%N,1!") do (
Set _Alphanumeric=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Set _count=0
set _RNDLen=%random%
Set /A _RNDLen=_RNDLen%%4
If !_count! leq %_RNDLen% call :loop
set "code=!code:%%C=-%%N!"
)
)
echo !code!
echo !_str!
pause
:loop
Set /a _count+=1
set _RND=%random%
Set /A _RND=_RND%%51
SET _str=!_str!!_Alphanumeric:~%_RND%,1!
EXIT /B %ERRORLEVEL%
The problem is that the program just quits before giving any output, even if i remove the exit /b statement. Thanks for help
I've no idea what principle you're using for your algorithm, but fundamentally you need to understand delayed expansion.
When your outer loop, for %%N is parsed, every %var% is replaced by the contents of that variable at that time, hence
set _RNDLen=%random%
If !_count! leq %_RNDLen% call :loop
are replaed by
set _RNDLen=a specific random number
If !_count! leq call :loop
The first line here will set _rndlen to the same number every time (for ny run) and since _rndlen is undefined at the start of the loop, it willl be replaced by nothing, hence the if statement has faulty syntax and hence cmd objects and would display a message.
You can use !random! with delayed expansion invoked to select a rendom number each time, and you need !_rndlen! to access the changed value of _rndlen (changed from its original value of nothing to some random value and then mod-4'd)
Personally, I'd assign _alphanumeric outside of the (outer) loop since its value isn't varied by the loop operation.
And naturally, you know that when you hit Return following the pause, the loop code will be executed before the routine terminates (by flow-through) and you should include a
goto :eof
line after the pause to skip this last operation.
I'm trying to set 2 variables in 3 categories, 6 variables total, copying out the categories three times seems like a poor option especially because my real code is much larger than this with almost 10 categories with 30 variables each.
First I ask which category to set variable (constant) and then asked to set the two variables in that category.
Which is fine, until I want to do something with the combined variable.
#echo off
cls
:start
cls
echo which variable do you want to set?
echo (1),(2),(3)
choice /c 123 /n
if ERRORLEVEL 3 goto :3
if ERRORLEVEL 2 goto :2
if ERRORLEVEL 1 goto :1
:1
set const=one
goto :wizard
:2
set const=two
goto :wizard
:3
set const=three
goto :wizard
:wizard
set /p %const%_varA= set %const% variableA:
set /p %const%_varB= set %const% variableB:
:: this line is the problem
echo %%const%_varA%
echo %%const%_varB%
::
echo.
pause
goto :filewrite
echo.
:filewrite
echo one varA %one_varA%
echo one varB %one_varB%
echo two varA %two_varA%
echo two varB %two_varB%
echo three varA %three_varA%
echo three varB %three_varB%
pause
goto :start
I have played around a bit and the problem you have is the fact that in batch-files the way to escape a % is another one. So your code will eventually look like echo %const%_varA% and as %var_A% is empty/does not exist, the only thing you should be getting is %const as output.
Luckily there is a way to bring another character into the game to prevent this from happening. Adding setlocal EnableDelayedExpansion under the first line will make variables accessable using exclamation marks. This is usually used to access variables in closed sets of parenthesis but comes in handy for this one:
#echo off
setlocal EnableDelayedExpansion
set const=three
set %const%_varA=foo
echo Without exclamationmarks: %%const%_varA%
echo With exclamationmarks : !%const%_varA!
pause
Is a tiny example that demonstrates the problem.
The upper line is what you currently have and not working. The lower one however uses above explaned delayed expansion.
Meaning: First (%) the value of %const% is calculated, changing the line to echo [...] !three_varA! and after (!) comes the whole thing!
Feel free to ask questions :)
::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
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.
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
)
What's the syntax of the command that could abstract a variable from a basic, integered number?
For example
by executing a batch file, a variable (like a flag) is automaticaly set to 0, grows by 1 each time another specific command is executed and peaks at 10.
I want to know at any given point, how many times this flag-variable has grown, so I could get the exact times that the affiliated command has been executed and most importantly how many times this variable still has to grow.
So, thinking purely mathematicaly, I thought of abstracting 10 out of the variable to get my answers. But i can't make this to work on CMD.
I used this exact line in the code :
set /a 10-variable & ( echo executions of that command left )
But this only ends up showing executions of that command left without showing any number what so ever.
You have a logical quirk. set doesn't work the way you do it.
#echo off
set /a variable=0
:loop
set /a variable+=1
set /a left=10-%variable%
echo %left% executions left.
if %left% gtr 0 goto :loop
echo done.
Alternative (using only one variable instead of two):
set /a left=10
:loop2
set /a left-=1
echo %left% executions left.
if %left% gtr 0 goto :loop2
echo done.
Note: set /a var+=1 is just a short form of set /a var=%var%+1
I am new to game programming in batch, and I am trying to make a variable equal to another one, and if the operator adds or subtract another variable that is not the max value, it won't add or subtract anymore. My batch file is:
if %num1% geq %num2% set /a num1=%num1% == %num2%
echo number: %num1%/%num2%
echo 1) add number
echo 2) quit
set /p input=
if %input% == 1 set /a num1=%num1%+1
if %input% == 2 exit
if there's a similar question to that one, please go nice on me.
Here's a sample that might help:
#echo off
set max=50
set num=20
:loop
set /p "input=Enter number to add - you now have %num% units: "
set /a t=num + input
if %t% LEQ %max% (
set num=%t%
) else (
echo That's too high - %max% is the limit!
)
echo %num%
goto :loop
Not sure on batch unless you mean shell programs or DOS mode shell programs for batch, however you can use an atomic variable with a C++ class and overload the =, + and - operator to use test and set, making sure that assign it correctly, you can then create mini programs performing you're operations that you can access using eval or system functions in you're program or with %fct% or fct