[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
太棒了,非常受用,收藏了。

TOP

对的,不好意思,手机太老了

TOP

回复 16# xxpinqz


    他应该是回复14楼的...

TOP

0是用来防空的。。。。
初学BAT,非专业。代码不适当之处还望前辈们多多指点。在此表示感谢!

TOP

标题

本帖最后由 wankoilz 于 2014-8-5 21:01 编辑

这样的话,fedcba9876543210中的0都可以省了。
不过我还是觉得用4096  2048……更好,因为每个数字正好对应于二进制上的一位,理解和计算都更好一点。
1

评分人数

    • CrLf: 感谢指点~技术 + 1

TOP

本帖最后由 CrLf 于 2014-8-5 23:15 编辑

回复 13# wankoilz


    看来个人有个人的习惯写法,我比较倾向用其他手段代替补位,这样可以兼容最长的变量(除了 , 这个变态的变量名),不过代码就稍显冗长了:
  1. @echo off&setlocal enabledelayedexpansion
  2. for /l %%a in (1 1 8189) do set s=!s!;
  3. call :strlen s len
  4. echo len=%len%
  5. pause&exit/b
  6. :strlen <stringVarName> [retvar]
  7. :: 思路: 二分回溯联合查表法
  8. :: 说明: 所求字符串大小范围 0K ~ 8K;
  9. ::    stringVarName ---- 存放字符串的变量名
  10. ::    retvar      ---- 接收字符长度的变量名
  11. setlocal enabledelayedexpansion&set $=!%1!&set N=0
  12. if defined $ (
  13. for %%a in (4095 2047 1023 511 255 127 63 31 15)do if !$:~%%a!. NEQ . set/aN-=~%%a&set $=!$:~%%a,-1!
  14. set $=!$!fedcba987654321&set/aN+=0x!$:~15,1!
  15. )
  16. endlocal&If %2. neq . (set %2=%N%)else echo %N%
复制代码

TOP

本帖最后由 wankoilz 于 2014-8-5 12:38 编辑

哦哦对的,是我自己没仔细看,在原字符串后加上一位就对了。
楼主的代码确实是简练!
不过对于我来说,不改动原字符串更容易理解 :
  1. :strlen <stringVarName> [retvar]
  2. :: 思路: 二分回溯联合查表法
  3. :: 说明: 所求字符串大小范围 0K ~ 8K;
  4. ::    stringVarName ---- 存放字符串的变量名
  5. ::    retvar      ---- 接收字符长度的变量名
  6. setlocal enabledelayedexpansion
  7. set "$=!%1!"
  8. set N=&for %%a in (4096 2048 1024 512 256 128 64 32 16)do if !$:~%%a!. NEQ . set/aN+=%%a&set $=!$:~%%a!
  9. set $=!$!!$!100f0e0d0c0b0a090807060504030201
  10. set/aN+=0x!$:~32,2!&set/aN+=0x!$:~16,1!
  11. endlocal&If %2. neq . (set/a%2=%N%)else echo %N%
复制代码

TOP

回复 11# wankoilz

因为源代码在字符串后补了一个字符,所以才用位移16,例字符串"abcd",实际扩展开来:$=abcd#fedcba9876543210    所以len=4

fedcba9876543210,这个本来就是取15位以内长度,没人说能取16位。
初学BAT,非专业。代码不适当之处还望前辈们多多指点。在此表示感谢!

TOP

本帖最后由 wankoilz 于 2014-8-5 02:00 编辑

无聊翻看经典帖子,发现前两段代码好像都少算了一个字符,比如第二段代码,在执行到
  1. set $=!$!fedcba9876543210&set/aN+=0x!$:~16,1!
复制代码
的时候,变量$的长度范围应该是1-16(不考虑$长度为0),而fedcba9876543210只能表达0-15
所以似乎应该把这一句改成这样:
  1. set $=!$!!$!100f0e0d0c0b0a090807060504030201&set/aN+=0x!$:~32,2!
复制代码
小小疏忽,请明察

TOP

同findstr类似,又一个外部命令求字符串长度的方法(适合于纯英文字符),连续的宽字符被视为1个字符;
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set str=www.bathome.net
  4. set n=0
  5. for /f "delims=" %%a in ('cmd/u/cecho !str!^|more')do set/a n+=1
  6. set n
  7. pause
复制代码
如果要给英文字符串中每个字符后加换行符,这是个简洁的方案;

TOP

本帖最后由 netbenton 于 2011-12-21 09:45 编辑

发现,楼主的这个代码和16字符限制的查表法合并才是最佳的,即8 4 2 1项用查表法代替。效率应该可以提高20%,增加的字符也不多

TOP

当多数人的思维在二分法和查表法后 正如plp626兄说道 "我们的思想是太懒了"
看这段精妙代码后 和plp626兄一样 我“个人认为” 似乎都没有超越上面这段代码
现在想法 结合查表法至 2048 位 然后 for %%a in (4096 2048)do...
表太长了  不贴这里了

TOP

本帖最后由 zm900612 于 2011-4-9 09:26 编辑

我的想法:
  1. @echo off
  2. set "$=%1"
  3. setlocal enabledelayedexpansion
  4. set len=8192
  5. (for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do (
  6. set /a len-="%%a!$:~%%a,1!"||set $=!$:~%%a!
  7. ))2>nul
  8. echo %len%
  9. ::未考虑字符串包含数字、特殊字符的情况
复制代码
稍加改进后仍然难以克服特殊字符的难关:
  1. @echo off
  2. set "$=%1"
  3. setlocal enabledelayedexpansion
  4. set len=8192
  5. (for %%a in (4096 2048 1024 512 256 128 64 32 16 8 4 2 1)do (
  6. set /a len-="%%a*^!(1-1!$:~%%a,1!)"||set $=!$:~%%a!
  7. ))2>nul
  8. echo %len%
  9. pause
  10. ::不惧怕数字了,但是仍然没有办法在set /a中很好地转义特殊字符,看来要想通用,那个if是不能省的了
复制代码

TOP

有一种直觉,几乎接近真实了
就求字符串长度来说,还有比一楼更快代码更简洁的代码。

TOP

也想过类似的思路,但是当时思维惯性,只想到了二分回溯补位,并没有用变量偏移,一墙之隔啊,可惜当时没想这么深入,呵呵。

TOP

返回列表