Task description
Prompt the user to enter their age in years, save the users response as a variable
age
.
- If the user did not provide a response like an empty string or letters or characters echo a message
invalid
and exit with script with anecho
message:not ok
- However if the user's age is greater than or equal to 16, output the message:
You may drive
- If the user's age is less than 16 then subtract their input age with 16 and output:
You may not drive for
(whatever the result of the 16 subtracted by their input age)year
- Exit at the end of the script with an
echo ok
.
Batch script
@echo off
setlocal
:: Prompt the user to enter their age
set /p age="Enter your age in years: "
:: Check if the age is a valid number (not empty and contains only digits)
for /f "delims=0123456789" %%a in ("%age%") do set "invalid=1"
if "%invalid%"=="1" (
echo invalid
echo not ok
exit /b
)
:: Check if age is greater than or equal to 16
if %age% geq 16 (
echo You may drive
) else (
set /a yearsLeft=16-%age%
echo You may not drive for %yearsLeft% year(s)
)
:: Exit with a message
echo ok
exit /b
Issue description
I was expecting the script to work, but it keeps outputting on repeated execution from within a command prompt window:
Enter your age in years: 2
invalid
not ok
Why does the if
condition below the for
loop always evaluate to true?
Task description
Prompt the user to enter their age in years, save the users response as a variable
age
.
- If the user did not provide a response like an empty string or letters or characters echo a message
invalid
and exit with script with anecho
message:not ok
- However if the user's age is greater than or equal to 16, output the message:
You may drive
- If the user's age is less than 16 then subtract their input age with 16 and output:
You may not drive for
(whatever the result of the 16 subtracted by their input age)year
- Exit at the end of the script with an
echo ok
.
Batch script
@echo off
setlocal
:: Prompt the user to enter their age
set /p age="Enter your age in years: "
:: Check if the age is a valid number (not empty and contains only digits)
for /f "delims=0123456789" %%a in ("%age%") do set "invalid=1"
if "%invalid%"=="1" (
echo invalid
echo not ok
exit /b
)
:: Check if age is greater than or equal to 16
if %age% geq 16 (
echo You may drive
) else (
set /a yearsLeft=16-%age%
echo You may not drive for %yearsLeft% year(s)
)
:: Exit with a message
echo ok
exit /b
Issue description
I was expecting the script to work, but it keeps outputting on repeated execution from within a command prompt window:
Enter your age in years: 2
invalid
not ok
Why does the if
condition below the for
loop always evaluate to true?
2 Answers
Reset to default 1Here is a rewritten working code:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
goto UserPrompt
:InvalidAge
echo You have not entered a valid age as number in whole years
echo using only the digits 0 to 9 like 20 or 36 or 57.
echo(
echo "thirteen" is incorrect, the number 13 would be correct.
echo "12.5" is incorrect, the number 12 would be correct.
echo "16¼" is incorrect, the number 16 would be correct.
rem Prompt the users to enter their age.
:UserPrompt
echo(
set "age="
set /P "age=Enter your age as number in years: " || goto UserPrompt
rem Remove all double quotes from user input string.
set "age=%age:"=%"
if not defined age goto UserPrompt
rem Check if the age is a valid number, i.e. has only digits.
for /F delims^=0123456789^ eol^= %%I in ("%age%") do goto InvalidAge
for /F "tokens=* delims=0" %%I in ("%age%") do set "age=%%I"
if not defined age set "age=0"
if %age% GTR 120 goto InvalidAge
if %age% GEQ 16 goto Process
set /A YearsLeft=16-age
if %YearsLeft% == 1 (set "PluralS=") else set "PluralS=s"
echo You may not drive for %YearsLeft% year%PluralS%.
exit /B
:Process
echo Okay! You may drive.
endlocal
For an explanation of the code read:
- How to stop Windows command interpreter from quitting batch file execution on an incorrect user input?
- Safe number comparison in Windows batch file
To understand the commands used and how they work, open a command prompt window, execute there the following commands, and read the displayed help pages for each command, entirely and carefully.
echo /?
endlocal /?
exit /?
for /?
goto /?
if /?
rem /?
set /?
setlocal /?
PS: The character ¼
must be character encoded according to the code page used by default in command prompt windows by the user accounts using this batch file like OEM 850 or OEM 437.
Given that we are dealing with user input that does not include unbalanced rabbit's ears, %
or other language-sensitive characters,
@ECHO Off
SETLOCAL
SET /p "age=Your age :"
FOR /L %%e IN (16,1,120) DO IF "%%e"=="%age%" GOTO candrive
FOR /L %%e IN (0,1,15) DO IF "%%e"=="%age%" SET /a wait4=16-%%e&GOTO wait
ECHO Invalid input
GOTO :eof
:wait
SET "plural="
IF %wait4% geq 2 SET "plural=s"
ECHO IN %wait4% year%plural%,
:candrive
ECHO you can drive
ECHO once you get a licence.
GOTO :EOF
%invalid%
might still be defined from previous experiments (check withset invalid
). Be sure to delete it before thefor /f
loop withset "invalid="
– Stephan Commented Mar 27 at 6:53;12
is additionally not detected as invalid because of;
is the default end of line character resulting in ignoring the value of environment variableage
. A user input with"
breaks the entire batch script execution and can even result in executing commands not written in the batch file at all. The definition ofyearsLeft
and its usage in same command block results in running into the delayed expansion trap with output of no year value or the year value from a previous execution of the batch file or something else. – Mofi Commented Mar 27 at 7:10