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
)
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
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 (
...
)
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
What is the simplest and/or most readable method to IF with AND in a CMD shell? In pseudo code:
IF EXIST file1 AND file2:
then do stuff
ELSE:
do something else
this Q has to be somewhere on SO but my search-fu isn't working for this one. sorry
Assuming you are talking about DOS/Windows batch files, I think you want something like this:
SET do_stuff=false
IF EXIST file1 IF EXIST file2 SET do_stuff=true
IF "%do_stuff%"=="true" (
REM do stuff
) ELSE (
REM do something else
)
The source of the ugliness is that DOS batch file if statements do not have and and or operators, so you have to either write nested if statements (which can lead to duplicated code in the then and else clauses), or capture the expression result into a variable and then do an if statement on its value (lots more lines). I favor the second approach to avoid duplication of code. Perhaps this is all a security feature. :)
I found some good examples here and here (SO, even). But you can also just use the help system built into the shell (help if or if /? IIRC).
An alternative to the rather nice suggestion by #Randall Cook could be going like this:
IF EXIST file1 IF EXIST file2 (
do stuff
GOTO cont
)
do something else
:cont
get on with other stuff
IF EXIST A (
IF EXIST B (
ECHO A and B exist
)
)
I've learned a bit since #RandallCook's answer was the best for me. This is what I'd use now:
#echo off
IF EXIST "File1" IF EXIST "File2" GOTO :do_stuff
GOTO :not_exist
GOTO :EOF
:do_stuff
echo File1 and File2 exist.
echo -- Doing stuff here...
goto :EOF
:not_exist
echo Condition not met, not doing stuff.
goto :EOF
:EOF a predefined label that will exit the current subroutine or script.
For those that prefer CALL over GOTO because it leads to cleaner code in longer scripts, we need to complicate things a little bit, but is still readable:
#echo off
:: Successful CD resets errorlevel to 0, in case it was already set this shell
cd
IF EXIST "File1" IF EXIST "File2" CALL :do_stuff
IF ERRORLEVEL 10 GOTO :EOF
CALL :not_exist
GOTO :EOF
:do_stuff
echo File1 and File2 exist.
echo -- Doing stuff here...
exit /b 10
goto :EOF
:not_exist
echo Condition not met, not doing stuff.
goto :EOF
set /p k="Please enter Choice : "
if "%k%" == "A" goto A
if "%k%" == "B" goto B
:A
echo "Hello from A"
:B
echo "Hello from B"
Why won't this code work correctly?
I am sorry I couldn't understand how to post the code, so here is an image of the code:
![enter image description here][1] (also, please click the link because I am a new user and I can't post images yet)
Is Command Prompt even capable of executing this "branched IF commands" correctly?
If so, what am I doing wrong? Anyone knows? Please, reply!
:STARTEXITING
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_1.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_1.txt
if %error1eve1%==0 (
SLEEP 2
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_2.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_2.txt
if %error1eve1%==0 (
SLEEP 3
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_3.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_3.txt
if %error1eve1%==0 (
process -q uTorrent.exe 15
:STARTSTARTING
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_1.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_1.txt
if %error1eve1%==0 (
SLEEP 2
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_2.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_2.txt
if %error1eve1%==0 (
SLEEP 3
"D:\dbStatusChecker\dbFi1estatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_3.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_3.txt
if %error1eve1%==0 (
D:
cd\
cd Dropbox
cd uTorrent
start uTorrent.exe
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTSTARTING
) else (
SLEEP 1
GOTO STARTEXITING
) else (
SLEEP 1
GOTO STARTEXITING
) else (
SLEEP 1
GOTO STARTEXITING
For great justice: This text was OCR-ed from http://i.stack.imgur.com/RgsId.png
cmd can handle nested ifs just fine. Your problem is a different one. As it stands all your if checks, except for the first will not do what you want.
Use delayed expansion by putting a
setlocal enabledelayedexpansion
at the top of your batch file and use !errorlevel! instead of %errorlevel%.
However, since you only check for Errorlevel being 0 you can just as well do
if not errorlevel 1 ...
instead of
if %errorlevel%==0
Joey has diagnosed one problem concerning delayed expansion. You have another - you should not put a label within an IF ELSE block - you most likely will not get your desired result. See https://stackoverflow.com/a/8481978/1012053.
Christian has a great suggestion to restructure your code to get rid of the nesting.
Since you are simply executing the same commands with increasing sleep intervals, you can use a FOR /L loop to further simplify your code.
#echo off
:startExiting
set started=
for /l %%N in (1 1 3) do (
if defined started sleep %%N
set started=1
"D:\dbStatusChecker\dbFileStatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Exit_Pass_%%N.txt
findstr /m "up to date" dbstatus_uTorrent_Exit_Pass_%%N.txt || goto :startExiting
)
process -q uTorrent.exe 15
:startStarting
set started=
for /l %%N in (1 1 3) do (
if defined started sleep %%N
set started=1
"D:\dbStatusChecker\dbFileStatus.exe" "D:\Dropbox" > dbstatus_uTorrent_Start_Pass_%%N.txt
findstr /m "up to date" dbstatus_uTorrent_Start_Pass_%%N.txt || goto :startStarting
)
d:
cd \Dropbox\uTorrent
start uTorrent.exe
Since all the else clauses end with a goto, why not reverse them all, then you will eliminate the nesting.
If the code works, job done. If it still doesn't work, well that's one less factor to think about.