View unanswered posts | View active topics It is currently 20 Aug 2014 04:42



Post new topic Reply to topic  [ 4 posts ] 
How to count only quotes/characters in a string 
Author Message
Expert

Joined: 30 Aug 2007 08:05
Posts: 668
Location: Germany
Post How to count only quotes/characters in a string
Sometimes it's useful to count a single character in a string, and not all characters like stringLength function do.

There is the obvious solution to iterate over the complete string and examine each character, but I don't like this brute force way.
So I decide to create an other more elegant solution.

The core idea is to replace rearrange the string so that each quote (or the character you want) will be replaced with the string +1,
and all other characters will be completly removed.

For this I use a technic, I called it delayed reduction, to do the magic work.

The sample string
The dog said : "Hello you", the cat answered: "Hi" and smile
will be replaced to
-1!!#:X=The dog said : !!#:X=Hello you!!#:X=, the cat answered: !!#:X=Hi!!#:X= and smile!

The content of the variable # is +1, so after the exclamation marks are expanded the line is reduced to
-1+1+1+1+1+1

And this can be easily calculated with SET/a to 4.

The rest of the code is only to avoid problems with special characters like exclamation marks and carets in the string.

Code:
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set "line=!%~1!"
set "#=+1"

rem DelayedExpansion: double all quotes
set "line=!line:"=""!"

rem DelayedExpansion: remove all carets ^
set "line=!line:^=!"

rem PercentExpansion: Remove all !
set "line=%line:!=%"

rem PercentExpansion: Replace double quotes to !!#:#=
set "line=-1^!#:#=%line:""=^!^!#:#=%"

for /F "delims=" %%X in ("!line!") do (
   set /a count=%%X!
)

(
   endlocal
   set %~2=%count%
   exit /b
)


jeb


05 Jun 2012 08:17
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1201
Location: United States (east coast)
Post Re: How to count only quotes/characters in a string
:shock: That is insane jeb :lol:

You have a trivial bug, you need to change "temp" into "line" near the top.

I suppose you could add some additional code to specify the character to count. You would need to encode characters like ! and ^ instead of removing them. My guess is the only character you couldn't count would be =.

I'm wondering if something like the following might be faster and easier to code and understand. It replaces each quote with a linefeed and uses FOR /F to count the number of lines. Like your code, there is more work to be done to parametize the char to be counted. And it has the same inability to count =.
Code:
:CountQuotes
setlocal enableDelayedExpansion
set lf=^


set "line=x!%~1!"
for %%C in ("!lf!") do set line=!line:"=%%~Cx!
set count=-1
for /f "delims=" %%A in ("!line!") do set /a count+=1
(
  endlocal
  set %~2=%count%
  exit /b
)

Edit
What about simply using the strLen function to get the string length before and after replacing the char (quote) with nothing? This would have better length restrictions since the string doesn't have to expand to count the chars.

I just realized that there isn't a fast pure batch solution that is case sensitive. (At least I don't think there is)


Dave Benham


05 Jun 2012 10:51
Profile
Expert

Joined: 30 Aug 2007 08:05
Posts: 668
Location: Germany
Post Re: How to count only quotes/characters in a string
Thanks Dave,

but your solution is also a good idea :D.

You inspire me to create another solution with linefeeds, but without a for loop. :)

Code:
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set "line=!%~1!"
set "line=!line:%%=!"
for %%L in ("!LF!") DO set "line=!line:"=%%~Lset /a cnt+=1%%~Lrem # !"
set cnt=0
ECHO ON
(
rem # %line%
)
@ECHO OFF
(
   endlocal
   set %~2=%cnt%
   exit /b
)


jeb


05 Jun 2012 13:17
Profile
Expert

Joined: 12 Feb 2011 21:02
Posts: 1201
Location: United States (east coast)
Post Re: How to count only quotes/characters in a string
Very interesting. This last one may be the fastest, but it expands the string the most, so it limits the size of the string that can be processed.

You need to protect against the input being undefined.

I don't see the need to remove %% from the string.

And I assume the ECHO ON/OFF is just to help with understanding.

Here is a variation that minimizes the growth of the string.
Code:
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set lf=^


set "line=!%~1!"
if defined line for %%L in ("!LF!") DO set "line=!line:"=%%~Lset/ac+=1%%~L::!"
set c=0
(
  ::%line%
  rem
)
(
  endlocal
  set %~2=%c%
  exit /b
)

Edit
Heck - if we are going to get rid of FOR loops, let's do it for real :D
Code:
:::::::::::::::::::::::::::::::::::::::::::
:CountQuotes <stringVar> <result>
setlocal EnableDelayedExpansion
set "line=!%~1!"
if defined line set "line=!line:"=^

set/ac+=1^

::!"
set c=0
(
 ::%line%
 rem
)
(
  endlocal
  set %~2=%c%
  exit /b
)


Dave Benham


05 Jun 2012 14:53
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 


Who is online

Users browsing this forum: No registered users and 19 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Forum style by Vjacheslav Trushkin for Free Forums/DivisionCore.