my own StrLen function

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
seb666
Posts: 3
Joined: 21 Sep 2012 04:10

my own StrLen function

#1 Post by seb666 » 21 Sep 2012 04:48

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 - :mrgreen:

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

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: my own StrLen function

#2 Post by dbenham » 21 Sep 2012 06:59

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

seb666
Posts: 3
Joined: 21 Sep 2012 04:10

Re: my own StrLen function

#3 Post by seb666 » 21 Sep 2012 11:15

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 ?

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: my own StrLen function

#4 Post by Ed Dyreen » 21 Sep 2012 11:35

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

billrich
Posts: 70
Joined: 24 Apr 2012 05:36
Location: USA

Re: my own StrLen function

#5 Post by billrich » 21 Sep 2012 12:57

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):
Last edited by billrich on 23 Sep 2012 19:45, edited 5 times in total.

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: my own StrLen function

#6 Post by Liviu » 21 Sep 2012 23:32

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.

billrich
Posts: 70
Joined: 24 Apr 2012 05:36
Location: USA

Re: my own StrLen function

#7 Post by billrich » 22 Sep 2012 01:17

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):

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: my own StrLen function

#8 Post by foxidrive » 22 Sep 2012 02:24

billrich wrote:Here is the Dostips strlen that did not work.
Please Help.


Code: Select all

   CALL :StrLen "%String%" Len



Change that to this:

Code: Select all

   CALL :StrLen String Len

seb666
Posts: 3
Joined: 21 Sep 2012 04:10

Re: my own StrLen function

#9 Post by seb666 » 22 Sep 2012 05:47

@ Ed Dyreen

Understood, thank you for your answers.

billrich
Posts: 70
Joined: 24 Apr 2012 05:36
Location: USA

Re: my own StrLen function

#10 Post by billrich » 22 Sep 2012 08:08

foxidrive wrote:
billrich wrote:Here is the Dostips strlen that did not work.
Please Help.


Code: Select all

   CALL :StrLen "%String%" Len



Change that to this:

Code: Select all

   CALL :StrLen String Len


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>

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: my own StrLen function

#11 Post by Liviu » 22 Sep 2012 11:26

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

billrich
Posts: 70
Joined: 24 Apr 2012 05:36
Location: USA

Re: my own StrLen function

#12 Post by billrich » 23 Sep 2012 09:59

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:

Image

String length: 11
Last edited by billrich on 02 Oct 2012 20:40, edited 1 time in total.

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: my own StrLen function

#13 Post by Liviu » 23 Sep 2012 10:45

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 ;-)

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: my own StrLen function

#14 Post by foxidrive » 23 Sep 2012 10:54

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.

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: my own StrLen function

#15 Post by Liviu » 23 Sep 2012 11:13

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.

Post Reply