这是迄今为至,我多年来看过的批处理代码中,见到的最优美的一段代码,不和大家分享一下实在不好意思。
原以为,求字符串长度的方法在二分法和查表法后不会有突破了,但我发现时我的思想是太懒了。
二分回溯法(现在更正下,准确的叫法应该是优化的二分法)求字符串长度:
原帖:http://www.dostips.com/forum/viewtopic.php?f=3&t=1429- setlocal enabledelayedexpansion
- set "$=!%1!#"
- set len=&for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do if !$:~%%a^,1!. NEQ . set/a len+=%%a&set $=!$:~%%a!
- endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码 关于求字符串长度,以前论坛里讨论过不少,但就代码长度,支持最长字符串,和执行耗时来综合考虑,
我“个人认为”都没有超越上面这段代码。
把原代码小修小补增加了30多K的字节(原帖是联合256位的表),可以减少相当于大概2~7次set 赋值命令所耗费的时间(效率提高8%~30%):- :strlen <stringVarName> [retvar]
- :: 思路: 二分回溯联合查表法
- :: 说明: 所求字符串大小范围 0K ~ 8K;
- :: stringVarName ---- 存放字符串的变量名
- :: retvar ---- 接收字符长度的变量名
- setlocal enabledelayedexpansion
- set "$=!%1!#"
- set N=&for %%a in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%a!. NEQ . set/aN+=%%a&set $=!$:~%%a!
- set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
- endlocal&If %2. neq . (set/a%2=%N%)else echo %N%
复制代码 对于上面代码
如果所求字符串长度不超过4096:
可以将4096 2048 1024 512 256 128 64 32 16改为2048 1024 512 256 128 64 32 16
如果所求字符串长度不超过2048:
可以将4096 2048 1024 512 256 128 64 32 16改为 1024 512 256 128 64 32 16
以此类推。。。
=============================================================
测试一下效率- @echo off&setlocal enabledelayedexpansion
- :: 将strlen函数内敛到变量_strlen中,测试字符串长度小于4096;入口参数#1,返回变量##
- set "_strlen=set $=^!#1^!#&set ##=&(for %%a in (2048 1024 512 256 128 64 32 16)do if ^!$:~%%a^!. NEQ . set/a##+=%%a&set $=^!$:~%%a^!)&set $=^!$^!fedcba9876543210&set/a##+=0x^!$:~16,1^!"
-
- :: 生产一个长度为4096字符个数的字符串
- set str=.&for /l %%a in (1 1 12)do set str=!str!!str!
-
- :: 测试一下速度,4000次
- set bt=%time%
- for /l %%a in (1 1 4000)do (
- set #1=!str:~-%%a!
- (%_strlen%)
- echo 长度:!##!
- )
- set et=%time%
- :: 计算花费时间
- set /a ct=1!et:~-5,2!!et:~-2!-1!bt:~-5,2!!bt:~-2!,ct+=-6000*("ct>>31")
- echo ---------------------&echo 开始时间:%bt%&echo 结束时间:%et%
- echo 4000次测试用时:%ct% 跑秒&echo -----------------------
- pause
复制代码
|