找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
楼主: plp626

[文本处理] 求字符串长度,简短高效的批处理代码(多种算法)

[复制链接]
发表于 2014-8-5 23:02:44 | 显示全部楼层
0是用来防空的。。。。
发表于 2014-8-5 23:15:14 | 显示全部楼层
回复 16# xxpinqz


    他应该是回复14楼的...
发表于 2014-8-6 01:06:28 | 显示全部楼层
对的,不好意思,手机太老了
发表于 2014-11-3 16:42:42 | 显示全部楼层
太棒了,非常受用,收藏了。
发表于 2018-8-1 09:15:47 | 显示全部楼层
回复 1# plp626

楼主的算法确实精简高效,把数学计算用到了极致。但这两天在学习时发现,该代码存在以下问题:
1、使用for /l (128 64 32...)时,判断某数为空后折半,需要把括号中的数减一后再判断,就如
if "!a:~127,1!" neq ""  set /a "len+=%%a",而不是if "!a:~%%a,1!" neq ""  set /a "len+=%%a"。用这种算法,固然可以在全部计算后最终加1得到正确长度,但是毕竟原代码结果不正确。

2、第9句的set/a "len+=0x!s:~16,1!",应该是set/a "len+=0x!s:~15,1!"

说的不对的地方,请斧正。

我的代码如下:
  1. @echo off
  2. set "var=1234567890abcdefghijklmnopqrstuv12345678901234567890abcdefghijklmnopqrstuv12345678901234567890abcdefghijklmnopqrstuv12345678901"
  3. call :Len var,n
  4. echo 长度为%n%
  5. pause&exit

  6. :Len
  7. Setlocal enabledelayedexpansion
  8. set "s=!%1!"
  9. for %%a in (512 256 128 64 32 16) do (
  10.         set/a "m1=%%a-1" &call set "b1=%%s:~!m1!,1%%"       
  11.         if "!b1!" neq "" (
  12.                 set/a "len+=%%a" &set "s=!s:~%%a!"
  13.                 if "!s!"=="" goto ok )
  14. )

  15. set "s=!s!fedcba9876543210" &set/a "len+=0x!s:~15,1!"
  16. :ok
  17. endlocal&set/a "%2=%len%"&goto:eof
  18. pause
复制代码
发表于 2018-8-1 09:32:47 | 显示全部楼层
回复 20# 踏沙行

set "$=!%1!#"
这不是没有意义的
发表于 2018-8-1 10:27:49 | 显示全部楼层
回复 20# 踏沙行


    能否举例说明一下原代码哪个结果不正确?
发表于 2018-8-1 14:59:32 | 显示全部楼层
回复 22# Batcher
  1. @echo off
  2. set a="1234567890abcdef"
  3. call :Len a n
  4. echo 长度为%n%
  5. pause&exit

  6. :Len
  7. setlocal enabledelayedexpansion
  8. set "$=!%1!#"
  9. 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!
  10. endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码
执行结果:长度为18
实际上应该是16
发表于 2018-8-1 15:09:03 | 显示全部楼层
回复 23# 踏沙行


楼主代码没问题,是你的理解不太准确。

set a="1234567890abcdef"
这种写法,set命令会认为变量a的值是包含双引号的,18位是正确的

set "a=1234567890abcdef"
这种写法,set命令会认为变量a的值是不包含双引号的,16位是正确的
发表于 2018-8-1 15:18:48 | 显示全部楼层
本帖最后由 踏沙行 于 2018-8-1 15:40 编辑

回复 24# Batcher
谢谢,是我写的有问题。
修正后再测试,代码如下:
  1. @echo off
  2. set "a=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  3. rem a的长度为64
  4. call :Ten a n
  5. echo 长度为%n%
  6. pause&exit

  7. :Ten
  8. setlocal enabledelayedexpansion
  9. set "$=!%1!#"
  10. set "len="
  11. for %%a in (64 32 16 8 4 2 1) do (
  12. if !$:~%%a^,1!. NEQ . set/a len+=%%a&set $=!$:~%%a!
  13. set/a "T=T+1"&echo.第!T!次判断
  14. )
  15. endlocal&If %2. neq . (set/a%2=%len%)else echo %len%
复制代码
运行结果为:
第1次判断
第2次判断
第3次判断
第4次判断
第5次判断
第6次判断
第7次判断
长度为64
请按任意键继续. . .

【问题】本来字符长度为64,可以一次判断出结果。但是因为使用了set "$=!%1!#",让计算次数增加了6次
而且,对于if !$:~%%a^,1!. NEQ .这样的判断,如果字符串中存在有.(点号),也会影响正常判断吧
发表于 2018-8-1 15:44:27 | 显示全部楼层
回复 25# 踏沙行


让计算次数增加了6次

你有更加优化的代码吗?发出来大家一起讨论一下吧
如果字符串中存在有.(点号),也会影响正常判断吧

把你的测试用例和测试结果发出来看看
发表于 2018-8-1 15:59:57 | 显示全部楼层
回复 26# Batcher
  1. @echo off
  2. set "a=1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
  3. call :Ten a n
  4. echo 长度为%n%
  5. pause&exit

  6. :Ten
  7. setlocal enabledelayedexpansion
  8. set "$=!%1!#"
  9. set "len="&for %%a in (4096 2048 1024 256 128 64 32 16 8 4 2 1) do (if "!$:~%%a,1!" NEQ "" set/a len+=%%a&set "$=!$:~%%a!" &if "!$:~1!"=="" goto ok)
  10. set "s=!s!fedcba9876543210" &set/a "len+=0x!s:~16,1!"
  11. :ok
  12. endlocal&set/a "%2=%len%"&goto:eof
  13. pause
复制代码
增加 if "!$:~1!"=="" goto ok,可以在刚好够2分时,及时跳出循环。
发表于 2018-8-5 11:17:38 | 显示全部楼层
查表法

  1. ::0 ~ 255字
  2. setlocal enableDelayedExpansion

  3. set "s=your string"

  4. set a=□0□1□2□3□4□5□6□7□8□9□A□B□C□D□E□F
  5. set "$=!%a:□=!!a:□=%!!s!!s!"


  6. set /a len=0x!$:~-512,2!
  7. echo %len%

复制代码

  1. :: 0 ~ 1279字   (8191 /6 = 1365)
  2. setlocal enableDelayedExpansion

  3. set "s=your string"

  4. set a=□0□1□2□3□4□5□6□7□8□9□A□B□C□D□E□F
  5. set d=!%a:□=!!a:□=□%!


  6. set b=□0□1□2□3□4
  7. set "$=!%b:□=!!d:□=%!!s!!s!!s!"


  8. :: (0x4FF + 1 ) *3 = 1280 * 3 = 3840
  9. set /a len=0x!$:~-3840,3!
  10. echo %len%

复制代码

评分

参与人数 2技术 +2 收起 理由
77七 + 1 感谢分享
CrLf + 1 有趣

查看全部评分

发表于 2018-8-5 20:45:34 | 显示全部楼层
本帖最后由 CrLf 于 2018-8-5 21:02 编辑

回复 28# nwm310


    挺好的思路
    把变量拆分成7份分别查询,就可以查8191字符长度内的所有变量了
发表于 2018-8-7 09:05:45 | 显示全部楼层
精典老贴! 再学习学习。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 04:04 , Processed in 0.022310 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表