Ben Brandt
Ben Brandt

Reputation: 2921

Batch File input validation - Make sure user entered an integer

I'm experimenting with a Windows batch file to perform a simple operation which requires the user to enter a non-negative integer. I'm using simple batch-file techniques to get user input:

@ECHO OFF
SET /P UserInput=Please Enter a Number: 

The user can enter any text they want here, so I would like to add some routine to make sure what the user entered was a valid number. That is... they entered at least one character, and every character is a number from 0 to 9. I'd like something I can feed the UserInput into. At the end of the routine would be like an if/then that would run different statements based on whether or not it was actually a valid number.

I've experimented with loops and substrings and such, but my knowledge and understanding is still slim... so any help would be appreciated.

I could build an executable, and I know there are nicer ways to do things than batch files, but at least for this task I'm trying to keep it simple by using a batch file.

Upvotes: 16

Views: 107703

Answers (17)

hideo
hideo

Reputation: 47

Just try this

 @echo off
    
    SET constNum=100

    :LOOP
    Set /p input=Please input a number less than %constNum% :  
    
    if "%input%" == "" echo Blank is not allowed & goto LOOP
    
    SET "notNumChar=" 
    for /f "delims=0123456789" %%i in ("%input%") do set notNumChar=%%i
    
    if defined notNumChar (
        echo %input% is a string
        goto LOOP
        
    ) else (
        REM Remove leading 0 if it has. eg: 08→8
        FOR /F "tokens=* delims=0" %%A IN ("%input%") DO SET inputNum=%%A   
    )
    
    REM Compare
    if defined inputNum (
        echo %inputNum%
        if %inputNum% equ %constNum% & goto LOOP
        if  %inputNum% gtr %constNum% & goto LOOP
        if  %inputNum% lss %constNum% & goto CONTINUE
    )
    :CONTINUE
    :: Your code here

Upvotes: 0

Wouter van Nifterick
Wouter van Nifterick

Reputation: 24116

This is the same idea as that of Johannes.. SET /A sets a numeric value. If the input is not a number, it changes it to 0. That's what you can exploit here to do your check.

@ECHO OFF
SET /P UserInput=Please Enter a Number:
IF %UserInput% EQU 0 GOTO E_INVALIDINPUT

SET /A UserInputVal="%UserInput%"*1
IF %UserInputVal% GTR 0 ECHO UserInput "%UserInputVal%" is a number
IF %UserInputVal% EQU 0 ECHO UserInput "%UserInputVal%" is not a number
GOTO EOF

:E_INVALIDINPUT
ECHO Invalid user input
 
:EOF

As an alternative, you could always create a little javascript file and call it from your batchfile. With parseInt() you could force the input to be an integer, or you could roll your own function to test the input.

Writing the javascript is just as fast as the batchfile, but it's much more powerful. No IDE or compiler required; notepad will do. Runs on every windows box, just like your batchfiles. So why not make use of it?

You can even mix batchfiles and javascript. Example:

contents of sleep.js:

var SleepSecs=WScript.Arguments.Item(0);
WScript.Sleep(SleepSecs*1000)

contents of sleep.cmd:

cscript /nologo sleep.js %1

You can now call this from a batchfile to make your script sleep for 10 seconds. Something like that is difficult to do with just a plain batchfile.

sleep 10

Upvotes: 4

Shekar Basha
Shekar Basha

Reputation: 39

for me this is working for all non-zero values ..should i be cautious of some rare cases?

set /a var = %1
if %var% neq 0 echo "it is number"
pause

Upvotes: -1

npocmaka
npocmaka

Reputation: 57322

Try this:

set /p numeric=enter a number

( 
  (if errorlevel %numeric% break ) 2>nul
)&&(
  echo %numeric% is numeric
)||(
  echo %numeric% is NOT numeric
)

Upvotes: 0

Ste
Ste

Reputation: 2313

If you want some sort of a loop and default set up for that particular question, then here's my method for doing this.

Notes on the code within.

@echo off
setlocal EnableDelayedExpansion
set "ans1_Def=2"

:Q1
set /p "ans1=Opt 1 of 1 [Value 1-5 / Default !ans1_Def!]: "

:: If not defined section. This will use the default once the ENTER key has been
:: pressed and then go to :Q2.
if not defined ans1 (
  echo/ & echo ENTER hit and the default used. Default is still: !ans1_Def! & echo/
  set "ans1=!ans1_Def!" && goto :Q2 )

:: This section will check the validity of the answer. The "^[1-5]$" will work
:: for only numbers between one and five in this example but this can be changed
:: to pretty much suit the majority of cases. This section will also undefine
:: the ans1 variable again so that hitting the ENTER key at the question
:: will work.
echo %ans1%|findstr /r /c:"^[1-5]$" >nul
if errorlevel 1 (
  echo/ & echo At errorlevel 1. Wrong format used. Default is still: !ans1_Def! & echo/
  set "ans1=" && goto Q1
  ) else ( echo Correct format has been used. %ans1% is the one. && goto :Q2 )

:Q2
echo/
echo -----------------------------
echo/
echo Now at the next question
echo !ans1!
echo/
pause
exit

Upvotes: 0

Mike D
Mike D

Reputation: 31

As pointed out by ghostdog74, the answers posted by Joey Mar 26 '09 (score 10) and Wouter van Nifterick Mar 26 '09 (score 5) don't work.

The answer posted by Joey Mar 25 '10 (score 2) does work, except that redirection symbols and '&' cause syntax errors.

I think the best and simplest solution is the one posted by Sager Oct 8 '14 (score 0). Unfortunately, it has a typo: ‘"%a"’ should be ‘"%a%"’.

Here's a batch file based on Sager's answer. Redirection symbols and '&' in the input don't cause problems. The only problems I could find were caused by strings containing double quotes.

@echo off & setlocal enableextensions & echo.
set /p input=Enter a string:
SET "x=" & for /f "delims=0123456789" %%i in ("%input%") do set x=%%i
if defined x (echo Non-numeral: "%x:~0,1%") else (echo No non-numerals)

Upvotes: 3

Flora
Flora

Reputation: 11

I know this is years old, but just to share my solution.

set /p inp=Int Only : 
:: Check for multiple zeros eg : 00000 ::
set ch2=%inp%-0
if %inp% EQU 0 goto :pass
if [%inp%]==[] echo Missing value && goto :eof
if %inp:~0,1%==- echo No negative integers! && goto :eof
set /a chk=%inp%-10>nul
if %chk%==-10 echo Integers only! && goto :eof
:pass
echo You shall pass
:eof

Tested and working on Windows 8.

Upvotes: 1

Krzysztof Gapski
Krzysztof Gapski

Reputation: 628

You can validate any variable if its number:

SET "var="&for /f "delims=0123456789" %i in ("%a") do set var=%i
if defined var (echo."NIC">nul) else (echo."number")

Upvotes: 0

Josh Heaps
Josh Heaps

Reputation: 1

This is more of a user friendly way.

if %userinput%==0 (
cls
goto (put place here)
)
if %userinput%==1 (
cls
goto (put place here)
)
if %userinput%==2 (
cls
goto (put place here)
)
if %userinput%==3 (
cls
goto (put place here)
)
if %userinput%==4 (
cls
goto (put place here)
)
if %userinput%==5 (
cls
goto (put place here)
)if %userinput%==6 (
cls
goto (put place here)
)if %userinput%==7 (
cls
goto (put place here)
)
if %userinput%==8 (
cls
goto (put place here)
)
if %userinput%==9 (
cls
goto (put place here)
)

This can be used for any type of user input.

Upvotes: -1

user3367829
user3367829

Reputation: 1

@echo off setlocal enableextensions enabledelayedexpansion set /p UserInput=Enter a number: set /a Test=UserInput if !Test! EQU 0 ( if !UserInput! EQU 0 ( echo Number ) else ( echo Not a number ) ) else ( echo Number )

yeaph everthing is great but you forget about one little thing 0 also is a digit ;(

Upvotes: -1

Whiskey Drainer
Whiskey Drainer

Reputation:

You might also like this one - it's short and easy. This one use the multiplication trick to set TestVal. Comparing TestVal against UserInput allows all numeric values to get through including zeroes, only non-numerics will trigger the else statement. You could aslo set ErrorLevel or other variables to indicate a failed entry

@ECHO OFF
SET TestVal=0

SET /P UserInput=Please Enter a Number:
SET /A TestVal="%UserInput%"*1

If %TestVal%==%UserInput% (
   ECHO You entered the number %TestVal%
   ) else ECHO UserInput "%UserInput%" is not a number

GOTO EOF

:EOF

Upvotes: 1

Joey
Joey

Reputation: 354854

You're probably not doing this in a DOS batch file. Or at least, support for set /p is unheard of for me in DOS :-)

You could use substrings. In fact I have written a parser for a specific regular language that way once, but it's cumbersome. The easiest way would probably be to assign the contents of %userinput% to another variable, using set /a. If the result comes out as 0 you need to check whether the input itself was 0, otherwise you can conclude it was a non-number:

@echo off
setlocal enableextensions enabledelayedexpansion
set /p UserInput=Enter a number: 
set /a Test=UserInput
if !Test! EQU 0 (
  if !UserInput! EQU 0 (
    echo Number
  ) else (
    echo Not a number
  )
) else (
  echo Number
)

However, this works only for numbers in the range of Int32. If you just care for any number (possibly floating-point as well) then you need to resort to the loop-based approach of dissecting it.

NOTE: Updated to solve the space issues. However, there is still a problem lurking: Entering 123/5 yields "number", since set /a can evaluate this ...

Upvotes: 17

Joey
Joey

Reputation: 354854

You can also use a quite simple trick:

echo %userinput%|findstr /r /c:"^[0-9][0-9]*$" >nul
if errorlevel 1 (echo not a number) else (echo number)

This uses findstr's regular expression matching capabilities. They aren't very impressive but useful at times.

Upvotes: 7

ghostdog74
ghostdog74

Reputation: 343137

you can reinvent the wheel and grow a few white hairs doing string validation in batch, or you can use vbscript

strInput = WScript.Arguments.Item(0)
If IsNumeric(strInput) Then
    WScript.Echo "1"
Else
    WScript.Echo "0"
End If

save it as checkdigit.vbs and in your batch

@echo off
for /F %%A in ('cscript //nologo checkdigit.vbs 100') do (
        echo %%A
        rem use if to check whether its 1 or 0 and carry on from here
)

Upvotes: 0

Nerun
Nerun

Reputation: 1

:ASK
SET /P number= Choose a number [1 or 2]: 
IF %number% EQU 1 GOTO ONE
IF %number% NEQ 1 (
  IF %number% EQU 2 GOTO TWO
  IF %number% NEQ 2 (
    CLS
    ECHO You need to choose a NUMBER: 1 OR 2.
    ECHO.
    GOTO ASK
  )
)

It works fine to me. If he chooses numbers less or greater, strings, floating number etc, he wil receive a message ("You need to choose a NUMBER: 1 OR 2.") and the INPUT will be asked again.

Upvotes: -1

Egbert
Egbert

Reputation:

In addition to the remark about the error that occures when spaces are part of the users input. You can use errorlevel errorlevel=9165. It can be used for the spaces in a string or for the error handling of 'no' input.

Kind Regards,

Egbert

Upvotes: 1

Ben Brandt
Ben Brandt

Reputation: 2921

Thanks all. I was trying to make it harder for myself looking at loops and string manipulation. I used your tips on math evaluation and comparison. Here's what I finally came up with as my concept script:

:Top
@ECHO OFF
ECHO.
ECHO ---------------------------------------
SET /P UserInput=Please Enter a Number: 
ECHO.
ECHO UserInput = %UserInput%
ECHO.
SET /A Evaluated=UserInput
ECHO Math-Evaluated UserInput = %Evaluated%
if %Evaluated% EQU %UserInput% (
    ECHO Integer
    IF %UserInput% GTR 0 ( ECHO Positive )
    IF %UserInput% LSS 0 ( ECHO Negative )
    IF %UserInput% EQU 0 ( ECHO Zero )
    REM - Other Comparison operators for numbers
    REM - LEQ - Less Than or Equal To
    REM - GEQ - Greater Than or Equal To
    REM - NEQ - Not Equal To
) ELSE (
    REM - Non-numbers and decimal numbers get kicked out here
    ECHO Non-Integer
)

GOTO Top

This method catches all numbers and can detect whether it's positive, negative, or zero. Any decimal or string will be detected as non-integers. The only edge case I've found is a string with spaces. For example, the text "Number 1" will cause the script to crash/close when the user input is evaluated as math. But in my situation, this is fine. I don't want my script to go on with invalid input.

Upvotes: 9

Related Questions