Basically, what is happening is my code continues to generate the same number. I have turned echo off to see the problem and the actual %random% variable is changing, but it seems like it does the math and says "No, it's really this number." Here's the code:
set /a num=(24 * %random%) / 32768 + 1
I have tested that code by itself and it works fine. However when I add my if statements* to the code, it goes all whack. So, the question is, how do I fix this and why is it happening?
*My if statements:
if "%num%"=="24" (
echo X
set /p ans=
if "%ans%"=="litin" (
echo.
echo Correct!
pause>nul
goto generate
)
)
All of my if statements look like that.
Sounds like you might have an issue with variable expansion. Assuming you are doing this stuff in a loop.
Try adding setlocal at the top of your program like this:
setlocal ENABLEDELAYEDEXPANSION
And endlocal at the end of your program:
endlocal
Now, when you need to use a variable that is changing inside a loop, use the ! syntax instead of %:
if "!num!"=="24" (
echo X
set /p ans=
if "!ans!"=="litin" (
echo.
echo Correct!
pause>nul
goto generate
)
)
You might want to use EQU for comparing numbers. So try this
if "%num%" EQU 24 (
...
)
Related
Hey does anyone know if there is a command or something that allows me to have all the letters, numbers and characters in one?
:start
set input=
set /p input=[Y / N]?
if %input%==Y goto y
if %input%==N goto n
if %input%==* goto this
:y
goto end
:n
exit
:this
#echo. Only J or N
:end
Here you can already see that I tried to get everything in one with "*" which unfortunately didn't work...
Thank you for trying to help me but I would like to point out again that I need help to find something that allows me to use all the characters, letters and symbols in one.
example:
if I take y then he goes on.
if I take n then it closes. and when i use g or h he says: "can't do,
just y and n (for yes and no)"
but things like "*" or "%word%" don't work and yes, I have "choice /?" Already tried but when I do it like this it doesn't work either:
for %%i in (
D o " you " k n o w " to " h e l p " me
) do (<nul set /p "=.%bs%%%~i" & >nul ping -n 1 localhost)
# echo ?
CHOICE
[I don't care about syntax errors or something. if it works then it fits, it's just this one thing to use all characters, letters and symbols in one.]
No hate <3
if has no wildcard, but as I already commented, you don't need the third if at all. If Y and N are already handled, it can only be "anything else"
:start
set "input="
set /p "input=[Y / N]? "
if "%input%"=="Y" goto y
if "%input%"=="N" goto n
echo it's Y or N, nothing else&goto :start
The quotes makes it a little bit safer, but note this still isn't safe at all.
Cmd handles several characters (so called "poison chars" like <>|&"!) different (and even more under certain conditions).
A more secure method:
#echo off
setlocal enabledelayedexpansion
:loop
set "input="
set /p "input="
>nul 2>&1 (
echo/!input!|findstr /x "Y" >nul && goto YES
echo/!input!|findstr /x "N" >nul && goto NO
)
echo FAIL
goto :loop
:YES
echo yeah
goto :eof
:NO
echo nope
goto :eof
(Disclaimer: I'm quite sure, someone will find an input-string to make it fail too)
Note: both if and findstr support the /i switch to make them case-insensitive.
And just for the sake of showing everyone else how to perform this task using the appropriate commands:
%SystemRoot%\System32\choice.exe
If ErrorLevel 2 Exit /B
Rem The code you had under :end replaces this line
i want to use my %variable% to manage the conditional clauses in a IF.. THEN.. ELSE in a batch file.
Something like the following:
set variable=%%homedrive%% EQU C:
if %variable% (
echo test ok
) else (
echo test fail
)
if i write on a cmd console:
set test=1 equ 1
if %test% echo OK
it works!
i'll use it in a for /f cicle:
this is my pseudo codethis is my pseudo code to correct
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
[..]
) > "%temp%\CSG_fs.tmp"
[..]
for /f "usebackq tokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set cond=!cond:~1!
set parm=%%b& set parm=!parm:~0,-1!
echo - cicle: "!cond!" --^> "!parm!"
call if !cond! call:CSG_sub_fs !parm!
echo - done
)
goto:eof
:CSG_sub_fs
[..]
goto:eof
--edit--
how can i use the variable !cond! to decide if execute the call to CSG_sub_fs?
call if !cond! call:CSG_sub_fs !parm!
does not work because it returns: "Can not find the batch label specified - IF"
and if i use
if !cond! call:CSG_sub_fs !parm!
it will say: "call:CSG_sub_fs not expected"
Well - there doesn't seem to be a question, so it's not that easy to answer.
You have a problem with
echo "^%COMPUTERNAME^% EQU [x];[some parameters1]"
because ^ does not escape % - % escapes % - use %%COMPUTERNAME%%...
(you should have been able to check this just by TYPEing "%temp%\CSG_fs.tmp"
Next problem is that
for /f "tokens=1-2* delims=; usebackq" %%a in (%temp%\CSG_fs.tmp) do (
may process the file %temp%\CSG_fs.tmp provided %temp%\CSG_fs.tmp contains no spaces, semicolons or commas. If it contains any of these deafult separators, or certain other characters with a special meaning, then you must enclose the filename in double-quotes "%temp%\CSG_fs.tmp"and use the usebackq option.
You've attempted to use usebackq but DELIMS must be the LAST option if it is used. Your code would set ";","","u","s","e","b","a","c","k" and "q" as delimiters.
Beyond that, perhaps if you explain what you intend to achieve, we'd be able to devise the appropriate code.
Try this:
#ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CLS
REM I'm setting these variables for testing.
REM That isn't ususally a good idea but the SETLOCAL
REM will ensure they are restored on exit
SET computername=[x]
SET logonserver=[z]
(
rem echo "%systemdrive%;;"
echo "%%COMPUTERNAME%% EQU [x];[some parameters1]"
echo "%%USERNAME%% NEQ [y];[some parameters2]"
echo "%%LOGONSERVER%% EQU [z];[some parameters3]"
) > "%temp%\CSG_fs.tmp"
for /f "usebackqtokens=1-2* delims=;" %%a in ("%temp%\CSG_fs.tmp") do (
set cond=%%a& set "cond=IF !cond:~1! CALL :csg_sub_fs "
set parm=%%b& set parm=!parm:~0,-1!
CALL :varcmd "!cond!" "!parm!"
)
GOTO :eof
:varcmd
%~1 %~2
GOTO :eof
:csg_sub_fs
ECHO parameters supplied to csg_sub_fs were: %*
GOTO :eof
I've forced the variablenames to match the conditions you've used in order to trigger the subroutine calls. Change as you need to prove your concept.
And dont worry about imperfect English. I'm sure I wouldn't do as well in your language!
As per my corrected answer to another question it seems that Windows XP doesn't strip <cr>'s from for /f output.
How can I test for the existance of <cr>'s in the output?
What I currently have is:
for /f "tokens=1,2,3* %%a in ('ping -n 1 example.com') do (
if not "x%%a"=="¶" ( echo %%a ) else ( echo.>null )
)
but no matter what I do:
2) delims= ¶
3) if not "x%%a"==""
4) if not "x%%a"=="
"
5) if not "x%%a"==" "
... I cannot seem to get the if to match the in the var with any combination of the above.
Using the FOR statement, there really is no way that I know of to consistently check for empty lines.
The FOR statement actually skips blank lines, which is what a carriage-return only is, just a blank line.
If it is able to check, you just need to check for an empty string. Like if "%%x"=="" echo Yes!
But try this at the command line:
for /f "tokens=*" %x in ('for /?') do #echo %x
Then compare it to the output of:
for /?
And you will see that (usually*) FOR does not include empty lines.
*I have seen it happen on occasion (usually when it's a pain), but I've never been able to reproduce it consistently.
Edited Answer
I'm trying to create a simple number-guessing game with batch. However, I have never been able to use parentheses correctly. The code is:
#echo off
::This is a game that has you guess a random number.
Title Random Number Game
set number=%random%
:guess
set /p guess1= Guess the number I'm thinking of!
if %guess1%LSS%number% (
echo Higher!
goto guess
)
if %guess1%GTR%number% (
echo Lower!
goto guess
)
echo You got it! Awesome Job!
Whether my guess is higher or lower than the number, after entering it, cmd returns, "( was not expected at this time." How do I fix this?
You almost had everything correct. You just need a space around the comparison operators
if %guess1% LSS %number% (
echo Higher!
goto guess
)
if %guess1% GTR %number% (
echo Lower!
goto guess
)
The following DOS script snippet has a bug:
if not exist %MyFolder% (
mkdir %MyFolder%
if %errorlevel% GEQ 1 (
rem WARNING: the line above has a bug!
rem %errorlevel% will be the errorlevel
rem of the if statement because of the (parentheses)
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
)
The fix is to use setlocal enabledelayedexpansion as follows:
setlocal enabledelayedexpansion
if not exist %MyFolder% (
mkdir %MyFolder%
if !errorlevel! GEQ 1 (
rem WARNING: the line above has a bug!
rem !errorlevel! will be the errorlevel
rem of the if statement because of the (parentheses)
echo Error: Could not create folder %MyFolder%
endlocal & goto AnErrorOccurred
)
)
endlocal
A full explanation of why is available here: Batch file fails to set environment variable within conditional statement
I want to audit my code to find instances of this bug, I figure a Regex would be an appropriate match, but haven't managed to get one working...
I think the ingredients should be:
Match an environment variable surrounded with %percentsigns%
That is inside (parentheses)
Any suggestions?
grepWin
I would use grepWin. Depending on the number of instances you have to find, you could write a regex that will give you all of them, plus some false positives.
Example: bug.bat
if not exist %MyVar% echo Hi!
if not exist %MyFolder% (
mkdir %MyFolder%
if %errorlevel% GEQ 1 (
rem WARNING: the line above has a bug!
rem %errorlevel% will be the errorlevel
rem of the if statement because of the brackets
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
)
Then use a regular expression to match all lines that start with if and have an open parenthesis:
$ grep "^[ \t]*if.*(" bug.bat
if not exist %MyFolder% (
if %errorlevel% GEQ 1 (
grepWin will show you all the files that match.
Percent Symbols
By request:
grep "^[ \t]*if.*%.*%.*(" bug.bat
You can't solve it with Regex, because you can't count the parenthesis with a regular language. For example:
Stuff (
More Stuff (
Less Stuff )
A %var%
Less Stuff )
There is no ( between the last ) and the variable. Since I can't count how many `( appear before to know if there's one open, I can't do this with regular expressions.
As you can see, he is using ! rather than % even in the rootlevel of the batch.
So basically you should be able to alternate every % to an ! for your environmental variables.
One other way is to use the AND (&&) and OR (||) tests for success (errorlevel 0) or error (errorlevel > 0), as in:
if not exist %MyFolder% mkdir %MyFolder%|| (
echo Error: Could not create folder %MyFolder%
goto AnErrorOccurred
)
I hope this can help.
And by the way, you do not fail to set the variable, you fail to read it back.
What happen is, within parenthesis, using %%'s give you the states which was before you entered the said parenthesis. The only thing I knows work well is the math "set /a toto+=1" which will correctly increment the variable. Otherwise you have two options:
Either use a called function to set the variable or use the setlocal ENABLEDELAYEDEXPANSION statement, as previously stated, and use !!'s within the parenthesis.