Page 1 of 2
my own StrLen function
Posted: 21 Sep 2012 04:48
by seb666
Hello everybody !
I want to thank all DosTips members for their efforts and all these nice tools !
Here, i discovered how to make recursive functions in Dos ! - Priceless -
I know you already made a StrLen function, but i created my own with a different method.
Before knowing about these recursive functions i used to make an infinite loop with a DEFINED test inside it (to quit the loop) and reduce the string from 1 character by each loop...
Here is my new StrLen recursive function (more elegant than my old infinite loop):
Code: Select all
:StrLen "Str", NbCar
:: StrLen function compute the input string's length from 0 (empty) to DOS limit
:: -- Str [in] - Any string
:: -- NbCar [in,out] - Variable reference (input) and length (input, output)
SETLOCAL
SET "Str=%~1"
SET /A "NbCar=%~2"
IF DEFINED Str (SET /A "NbCar+=1"& CALL %0 "%Str:~1%", NbCar)
(
ENDLOCAL &:: RETURN VALUE
IF "%~2" NEQ "" SET "%~2=%NbCar%"
)
GOTO :EOF
:: End Function StrLen
Re: my own StrLen function
Posted: 21 Sep 2012 06:59
by dbenham
The code works and is a good learning experience for you. But I hope you never try to use it in a production environment.
- You have to initialize your return value to 0 or undefined before each call.
- It is a very slow way to get the length.
- The routine cannot handle a string like "This & that" & the other thing
- Recursion is limited in batch due to a limited stack size. The limit varies per machine, but on my machine your script failed at length 448 (it took several seconds to get there!). Batch environment variables can be as long as 8191 bytes.
The DosTips strlen function handles all possible strings up to the max length supported by batch (actually maxLength-1), and completes in the blink of an eye.
Dave Benham
Re: my own StrLen function
Posted: 21 Sep 2012 11:15
by seb666
Thanks for your replies.
You can use this code to test it :
Code: Select all
@ECHO OFF
SET /P String=Enter a string (ex: Hello World):
CALL :StrLen "%String%", Len
ECHO.&ECHO Length = %Len%
ECHO.&PAUSE>NUL
EXIT /B
:StrLen "Str", NbCar
:: StrLen function compute the input string's length from 0 (empty) to DOS limit
:: -- Str [in] - Any string
:: -- NbCar [in,out] - Variable reference (input) and length (input, output)
SETLOCAL
SET "Str=%~1"
SET /A "NbCar=%~2"
IF DEFINED Str (SET /A "NbCar+=1"& CALL %0 "%Str:~1%", NbCar)
(
ENDLOCAL &:: RETURN VALUE
IF "%~2" NEQ "" SET "%~2=%NbCar%"
)
GOTO :EOF
:: End Function StrLen
@ dbenham
You are right, my code is not as efficient as the DosTips function.
In fact even my previous code with infinite loop was quicker than this recursive method.
I never intend to use this in production environment, it was just for my own purpose and, like you say, for my "learning experience".
My goal was to play with this new concept, and thanks to your review i learned new things and saw the loooong way to go before having a good understanding of DOS.
Thank you !
By the way i have two questions for you:
Could you explain me why i have to initialize my return value to 0 or undefined before each call ?
If i understood correctly what i have read so far, the main problem of recursive program in DOS is time consumption.
This is due to the CALL function that creates a new DOS environement in each loop then destroy them from last to the first when all loops are done ?
Re: my own StrLen function
Posted: 21 Sep 2012 11:35
by Ed Dyreen
seb666 wrote:Could you explain me why i have to initialize my return value to 0 or undefined before each call ?
If you don't, your code will not return the correct length 0 on an empty string or even return a false result if len was previously set.
seb666 wrote:If i understood correctly what i have read so far, the main problem of recursive program in DOS is time consumption.
This is due to the CALL function that creates a new DOS environement in each loop then destroy them from last to the first when all loops are done ?
Call does not creates a new DOS environment, but leaves a pointer.
It is slow because it evaluates what follows then checks if the file exists and if it doesn't search the label and if it doesn't execute the command ( if any ).
Code: Select all
call %%myVar%%
call myBatch.CMD
call :myLabel
Re: my own StrLen function
Posted: 21 Sep 2012 12:57
by billrich
seb666 wrote:Thanks for your replies.
I got your strlen code to work
Thanks for your help.
Code: Select all
@echo off
:start
set Len=0
set "string="
SET /P String=Enter a string (ex: Hello World):
CALL :StrLen "%string%", Len
ECHO Length = %Len%
goto :start
EXIT /B
:StrLen "Str", NbCar
:: StrLen function compute the input string's length from 0 (empty) to DOS limit
:: -- Str [in] - Any string
:: -- NbCar [in,out] - Variable reference (input) and length (input, output)
SETLOCAL
SET "Str=%~1"
SET /A "NbCar=%~2"
IF DEFINED Str (SET /A "NbCar+=1"& CALL %0 "%Str:~1%", NbCar)
(
ENDLOCAL &:: RETURN VALUE
IF "%~2" NEQ "" SET "%~2=%NbCar%"
)
GOTO :EOF
:: End Function StrLen
Output:
C:\test>joelen.bat
Enter a string (ex: Hello World): hello world
Length = 11
Enter a string (ex: Hello World): this and that and the other thing
Length = 33
Enter a string (ex: Hello World):
Length = 0
Enter a string (ex: Hello World): DosTips
Length = 7
Enter a string (ex: Hello World):
Length = 0
Enter a string (ex: Hello World):
Enter a string (ex: Hello World): HelloWorld
Length = 10
Enter a string (ex: Hello World): DosTips
Length = 7
Enter a string (ex: Hello World): Works
Length = 5
Enter a string (ex: Hello World): Enter <αßc??>,
Length = 15
Enter a string (ex: Hello World): <αßc??>
Length = 7
Enter a string (ex: Hello World):
Re: my own StrLen function
Posted: 21 Sep 2012 23:32
by Liviu
billrich wrote:I got your strlen code to work
Seb666's code works within certain limits, as stated already. Try entering "!?" or %cd% at the set/p prompt to see some failure cases.
billrich wrote:but the not DosTips strlen
Try to explain in some detail what "doesn't work" for you. Note that the dostips :strlen takes the input string by reference, not by value (i.e. variable name, not its value).
Liviu
P.S. There is something missing from billrich's code posted earlier. That one had a recursive call to itself, which wasn't a good idea by any stretch, but at least matched the output he quoted.
Re: my own StrLen function
Posted: 22 Sep 2012 01:17
by billrich
Here is the Dostips strlen that did not work.
Please Help.
Liviu wrote:billrich wrote:but the not DosTips strlen
Try to explain in some detail what "doesn't work" for you. Note that the dostips :strlen takes the input string by reference, not by value (i.e. variable name, not its value).
Liviu
P.S. There is something missing from billrich's code posted earlier. That one had a recursive call to itself, which wasn't a good idea by any stretch, but at least matched the output he quoted.
Code: Select all
C:\test>type dosstr.bat
@ECHO OFF
set len=0
echo len=%len%
SET /P String=Enter a string (ex: Hello World):
CALL :StrLen "%String%" Len
ECHO Length = %len%
call dosstr.bat
EXIT /b
:strLen string len -- returns the length of a string
:: -- string [in] - variable name containing the string being measured for length
:: -- len [out] - variable to be used to return the string length
:: Many thanks to 'sowgtsoi', but also 'jeb' and 'amel27' dostips forum users helped making this short and efficient
:$created 20081122 :$changed 20101116 :$categories StringOperation
:$source http://www.dostips.com
( SETLOCAL ENABLEDELAYEDEXPANSION
set "str=A!%~1!"&rem keep the A up front to ensure we get the length and not the upper bound
rem it also avoids trouble in case of empty string
set "len=0"
for /L %%A in (12,-1,0) do (
set /a "len|=1<<%%A"
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"
)
)
( ENDLOCAL & REM RETURN VALUES
IF "%~2" NEQ "" SET /a %~2=%len%
)
EXIT /b
Output:
C:\test>dosstr.bat
len=0
Enter a string (ex: Hello World): Hello World
Length = 0
len=0
Enter a string (ex: Hello World): DosTips
Length = 0
len=0
Enter a string (ex: Hello World): 777777
Length = 0
len=0
Enter a string (ex: Hello World):
Re: my own StrLen function
Posted: 22 Sep 2012 02:24
by foxidrive
billrich wrote:Here is the Dostips strlen that did not work.
Please Help.
Change that to this:
Re: my own StrLen function
Posted: 22 Sep 2012 05:47
by seb666
@ Ed Dyreen
Understood, thank you for your answers.
Re: my own StrLen function
Posted: 22 Sep 2012 08:08
by billrich
foxidrive wrote:billrich wrote:Here is the Dostips strlen that did not work.
Please Help.
Change that to this:
When the CALL :strlen String Len is used the Dostips strlen works except previous length repeats when no string is entered?
Where can I find a clean copy of the Dostips strlen code with an output example?
Code: Select all
@ECHO OFF
:start
SET /P String=Enter a string (ex: Hello World):
CALL :StrLen String Len
ECHO Length = %len%
goto :start
EXIT /b
:strLen string len -- returns the length of a string
:: -- string [in] - variable name containing the string being measured for length
:: -- len [out] - variable to be used to return the string length
:: Many thanks to 'sowgtsoi', but also 'jeb' and 'amel27' dostips forum users helped making this short and efficient
:$created 20081122 :$changed 20101116 :$categories StringOperation
:$source http://www.dostips.com
( SETLOCAL ENABLEDELAYEDEXPANSION
set "str=A!%~1!"&rem keep the A up front to ensure we get the length and not the upper bound
rem it also avoids trouble in case of empty string
set "len=0"
for /L %%A in (12,-1,0) do (
set /a "len|=1<<%%A"
for %%B in (!len!) do if "!str:~%%B,1!"=="" set /a "len&=~1<<%%A"
)
)
( ENDLOCAL & REM RETURN VALUES
IF "%~2" NEQ "" SET /a %~2=%len%
)
EXIT /b
Output:
C:\test> dosstr.bat
Enter a string (ex: Hello World): Hello World
Length = 11
Enter a string (ex: Hello World): DosTips
Length = 7
Enter a string (ex: Hello World):
Length = 7
Enter a string (ex: Hello World): When no string, the previous string length?
Length = 43
Enter a string (ex: Hello World): When string="", the previous string
Length = 35
Enter a string (ex: Hello World):
Length = 35
C:\test>
Re: my own StrLen function
Posted: 22 Sep 2012 11:26
by Liviu
billrich wrote:Enter a string (ex: Hello World): DosTips
Length = 7
Enter a string (ex: Hello World):
Length = 7
Enter a string (ex: Hello World): When no string, the previous string length?
You are mistaken. There is a string, and that string is "DosTips" from the previous set/p.
Set/p never clears or undefines a variable. If you enter no text at the set/p prompt and simply press ENTER, the variable keeps its previous value, in your case "DosTips". If that's not what you want to happen, then your code must clear the variable explicitly i.e. a line "set String=" right before the "set/p" line.
Liviu
Re: my own StrLen function
Posted: 23 Sep 2012 09:59
by billrich
http://www.tools4noobs.com/online_php_functions/strlen/Online strlen() function
int strlen ( string $str )
This tool will display the length of the given text.
Hello World
p.s:
String length: 11
Re: my own StrLen function
Posted: 23 Sep 2012 10:45
by Liviu
billrich wrote:http://www.tools4noobs.com/online_php_functions/strlen/
Enter ‹αß©∂€›, click 'display length', get string length: 18.
Dostips' :strlen function gives the (correct) string length of 7 for the same string.
Dostips wins
Re: my own StrLen function
Posted: 23 Sep 2012 10:54
by foxidrive
Liviu wrote:Enter ‹αß©∂€›, click 'display length', get string length: 18.
Dostips' :strlen function gives the (correct) string length of 7 for the same string.
Maybe they are following the thread and fixed it.
It gave me 7 characters when I went to confirm it.
Re: my own StrLen function
Posted: 23 Sep 2012 11:13
by Liviu
foxidrive wrote:Liviu wrote:Enter ‹αß©∂€›, click 'display length', get string length: 18.
Maybe they are following the thread and fixed it.
It gave me 7 characters when I went to confirm it.
Interesting
They seem to have browser-specific pages, and one of those is wrong. Using Internet Explorer or Opera, the 'string length' on the main page does not update while you type or copy/paste, and clicking the 'display length' button navigates to a separate page showing String length: 18. Using Firefox, Safari or Chrome the string length updates live on the main page and gives the correct count of 7.
Incidentally, 18 is the character length of the UTF-8 representation of the ‹αß©∂€› string, so it looks like they may have simply mis-declared one of their internal encodings.