Discussion forum for all Windows batch related topics.
Moderator: DosItHelp
-
Jer
- Posts: 177
- Joined: 23 Nov 2014 17:13
- Location: California USA
#1
Post
by Jer » 29 Jan 2015 00:28
I am trying to use a function to validate numeric input. This method, not in a function,
was recently posted as a solution in this forum.
Can you tell me why the function below does not communicate the result, which would be FALSE
in this example, after the function exits? After the call line, the variable isNumb when echoed is blank.
Code: Select all
@Echo Off
setlocal enabledelayedexpansion
Set variable=12b
Call:checkNumber %variable% isNumb
Echo %variable% -- is it zero or a whole number? !isNumb!
GoTo:eof
:checkNumber
setlocal enabledelayedexpansion
Set isNumb=TRUE
For /f "delims=0123456789" %%a In ("%1") Do Set isNumb=FALSE
Echo Line 17, testing...isNumb: !isNumb!
endlocal & Set %~2=!isNumb!
Exit /b
endlocal
-
julesverne
- Posts: 81
- Joined: 19 Nov 2013 00:41
#2
Post
by julesverne » 29 Jan 2015 02:08
I did this, and I got FALSE as the variable: I switched your goto:eof and your exit /b around. I added the pause so you could see the result.
Code: Select all
@Echo Off
setlocal enabledelayedexpansion
Set variable=12b
Call:checkNumber %variable% isNumb
Echo %variable% -- is it zero or a whole number? !isNumb!
pause
Exit /b
:checkNumber
setlocal enabledelayedexpansion
Set isNumb=TRUE
For /f "delims=0123456789" %%a In ("%1") Do Set isNumb=FALSE
Echo Line 17, testing...isNumb: !isNumb!
endlocal & Set %~2=!isNumb!
GoTo:eof
endlocal
-
penpen
- Expert
- Posts: 2009
- Joined: 23 Jun 2013 06:15
- Location: Germany
#3
Post
by penpen » 29 Jan 2015 06:25
This is the issue:
The endlocal (in the function :checkNumber) restores the old environment, so the variable value of isNumb is restored (empty in this case).
I think you wanted to use %isNumb%, in this case, as the value is set before this line is executed:
Code: Select all
@Echo Off
setlocal enabledelayedexpansion
Set variable=12b
Call:checkNumber %variable% isNumb
Echo %variable% -- is it zero or a whole number? !isNumb!
endlocal
GoTo:eof
:checkNumber
setlocal enabledelayedexpansion
Set isNumb=TRUE
For /f "delims=0123456789" %%a In ("%1") Do Set isNumb=FALSE
Echo Line 17, testing...isNumb: !isNumb!
endlocal & Set %~2=%isNumb%
Exit /b
penpen
-
Aacini
- Expert
- Posts: 1913
- Joined: 06 Dec 2011 22:15
- Location: México City, México
-
Contact:
#4
Post
by Aacini » 29 Jan 2015 07:42
May I suggest a different method to validate the input? You may use the subroutine described at
this post that was developed precisely for this task. This way, the user is allowed to
enter just digits, so the test is not required at all! That subroutine may be modified in order to just read a number of N digits, so the code becomes shorter...
Antonio
-
rojo
- Posts: 26
- Joined: 14 Jan 2015 13:51
#5
Post
by rojo » 29 Jan 2015 10:05
Jer wrote:I am trying to use a function to validate numeric input. This method, not in a function,
was recently posted as a solution in this forum.
Can you tell me why the function below does not communicate the result, which would be FALSE
in this example, after the function exits? After the call line, the variable isNumb when echoed is blank.
I agree with penpen. Whenever you
endlocal & set "var=!var!" delayed expansion causes heartache and misery. Use
endlocal & set "var=%var%" or
endlocal & set "var=%%I" instead.
Since you're basically asking your subroutine to return a boolean value, you could have it set %ERRORLEVEL% and evaluate it with conditional execution like this:
Code: Select all
@echo off
setlocal
for %%I in (12345 123.3 0 abcde "12") do (
call :isInt %%I && (
echo %%I is an integer.
) || (
echo %%I is not an integer.
)
)
exit /b 0
:isInt <str>
for /f "delims=0123456789" %%a in ("%1") do exit /b 1
exit /b 0
Result:
Code: Select all
C:\Users\me\Desktop>test
12345 is an integer.
123.3 is not an integer.
0 is an integer.
abcde is not an integer.
"12" is not an integer.
-
Compo
- Posts: 600
- Joined: 21 Mar 2014 08:50
#6
Post
by Compo » 29 Jan 2015 10:24
What's wrong with this?
Code: Select all
Echo(%variable%|FindStr "[^0-9]">Nul&&(Echo(Non integer)||(Echo(Integer)
-
rojo
- Posts: 26
- Joined: 14 Jan 2015 13:51
#7
Post
by rojo » 29 Jan 2015 10:34
Compo wrote:What's wrong with this?
Code: Select all
Echo(%variable%|FindStr "[^0-9]">Nul&&(Echo(Non integer)||(Echo(Integer)
Internal functions are generally faster than executables. Your solution is simpler, but less efficient.
-
Squashman
- Expert
- Posts: 4486
- Joined: 23 Dec 2011 13:59
#8
Post
by Squashman » 29 Jan 2015 10:49
Compo wrote:What's wrong with this?
Code: Select all
Echo(%variable%|FindStr "[^0-9]">Nul&&(Echo(Non integer)||(Echo(Integer)
Yep. Just another way to skin the cat. I know we used that one just a few weeks ago. Had to explain inverse class to the user.
-
Jer
- Posts: 177
- Joined: 23 Nov 2014 17:13
- Location: California USA
#9
Post
by Jer » 29 Jan 2015 21:28
Thank you all for your input to this post. I am going with penpen's fix to my batch code, using %var% instead of !var!
notation to capture the result of the function.
This is for a hobby-type batch file application, so in my early stages of learning I will stick with the simpler solution.
Jerry