|
3742668
荣誉版主
      
积分 2013
发帖 718
注册 2006-2-18
状态 离线
|
『楼 主』:
[讨论][NT]计算字符串长度批处理代码查错
使用 LLM 解释/回答一下
@echo off
:began
set /p mystr=输入要计算长度的字符串:
echo %mystr:~0,1% | findstr /i "q" 1>nul 2>nul && exit rem 输入q退出
call :bflen "%mystr%" rem 这两句调用bflen,返回长度到变量ret中。
echo 字符串: "%mystr%"
echo 长 度: %ret%
goto began
:bflen rem 真麻烦,初始化要单独拿出来。
set num=
set str=
set ret=
set str=%1
:len rem 计算字符串长度
set str=%str:~0,-1%
set /a num = %num% + 1
if defined str goto len
set /a ret = %num% - 2
set num=
goto :eof
请帮忙测试一下bflen以后有什么漏洞,或者优化改进一下。
本来准备自己测试的,不过想想人多力量大,而且刚好willsort也在,所以就贴出来请大家帮忙看看。主要用途是获取字符串长度,从标号bflen开始,如果测试成功以后在批处理中就可以直接引用而不用再花时间去写了。
Last edited by willsort on 2006-5-22 at 12:37 ]
### Problem analysis
1. **Vulnerability analysis**:
- **Edge case handling**:
- When the input string is an empty string, the current code will have problems. For example, if `mystr` is an empty string, the `bflen` function will calculate incorrectly. Because when `str` is an empty string, the loop in the `len` label will still execute, and finally `ret` will be calculated incorrectly.
- **Variable scope issues**:
- The variables `num`, `str`, and `ret` are set in the `bflen` function. If there are other parts of the code that also use these variable names, there may be variable name conflict problems.
### Optimization suggestions
1. **Handle empty string situation**:
in the `bflen` function, add a judgment at the beginning of the `bflen` function to handle the case of an empty string. For example:
```batch
:bflen
set num=
set str=
set ret=
if "%~1"=="" (
set ret=0
goto :eof
)
set str=%1
:len
set str=%str:~0,-1%
set /a num = %num% + 1
if defined str goto len
set /a ret = %num% - 2
set num=
goto :eof
```
2. **Improve variable scope**:
- To avoid variable name conflicts, you can use more specific variable names. For example, prefix the variable names in the `bflen` function with `bflen_`. Modify the relevant parts as follows:
```batch
:bflen
set bflen_num=
set bflen_str=
set bflen_ret=
if "%~1"=="" (
set bflen_ret=0
goto :eof
)
set bflen_str=%1
:len
set bflen_str=%bflen_str:~0,-1%
set /a bflen_num = %bflen_num% + 1
if defined bflen_str goto len
set /a bflen_ret = %bflen_num% - 2
set bflen_num=
set ret=%bflen_ret%
goto :eof
```
The above code first handles the situation of an empty string and then improves the variable scope to make the code more robust.
```code
@echo off
:began
set /p mystr=输入要计算长度的字符串:
echo %mystr:~0,1% | findstr /i "q" 1>nul 2>nul && exit rem 输入q退出
call :bflen "%mystr%" rem 这两句调用bflen,返回长度到变量ret中。
echo 字符串: "%mystr%"
echo 长 度: %ret%
goto began
:bflen
set bflen_num=
set bflen_str=
set bflen_ret=
if "%~1"=="" (
set bflen_ret=0
goto :eof
)
set bflen_str=%1
:len
set bflen_str=%bflen_str:~0,-1%
set /a bflen_num = %bflen_num% + 1
if defined bflen_str goto len
set /a bflen_ret = %bflen_num% - 2
set bflen_num=
set ret=%bflen_ret%
goto :eof
```
|
|
2006-3-30 12:07 |
|
|
willsort
元老会员
         Batchinger
积分 4432
发帖 1512
注册 2002-10-18
状态 离线
|
『第 2 楼』:
使用 LLM 解释/回答一下
Re 3742668:
程序的退出语句有些缺陷,会导致以q起始的所有字符串均无法测得长度。另外,感觉取串长的算法效率有些低,最初改用echo串至文件再取文件长度的算法。但是它也存在无法测出某些含有特殊字符串长的兼容性问题,所以改成现在的算法。
测试案例:
command
command>nul
"command>nul"
command"com
@echo off & setlocal EnableExtensions
:began
set mystr=
set /p mystr=输入要计算长度的字符串(直接回车退出):
if not defined mystr goto :eof
call :strlen
echo 字符串: "%mystr%"
echo 长 度: %strlen%
goto began
:strlen rem 计算字符串长度
set strlen=
echo "%mystr%">_strlen.tmp
for %%f in (_strlen.tmp) do set strlen=%%~zf
set /a strlen=strlen-4
goto :eof
@echo off & setlocal EnableDelayedExpansion
:began
set mystr=
set /p mystr=输入要计算长度的字符串(直接回车退出):
if not defined mystr goto :eof
for /l %%i in (0,1,1000) do if "!mystr:~%%i,1!"=="" set strlen=%%i && goto :_endfor
:_endfor
::echo 字符串: "%mystr%"
echo 长 度: %strlen%
set strlen=
goto began
Re 3742668:
There are some flaws in the program's exit statement, which will cause all strings starting with q to not be able to measure the length. In addition, it feels that the algorithm for getting the string length is somewhat inefficient. Originally, the algorithm of echoing the string to a file and then getting the file length was used . But it also has compatibility problems of not being able to measure the length of some special strings, so it was changed to the current algorithm .
Test cases:
command
command>nul
"command>nul"
command"com
@echo off & setlocal EnableExtensions
:began
set mystr=
set /p mystr=输入要计算长度的字符串(直接回车退出):
if not defined mystr goto :eof
call :strlen
echo 字符串: "%mystr%"
echo 长 度: %strlen%
goto began
:strlen rem 计算字符串长度
set strlen=
echo "%mystr%">_strlen.tmp
for %%f in (_strlen.tmp) do set strlen=%%~zf
set /a strlen=strlen-4
goto :eof
@echo off & setlocal EnableDelayedExpansion
:began
set mystr=
set /p mystr=输入要计算长度的字符串(直接回车退出):
if not defined mystr goto :eof
for /l %%i in (0,1,1000) do if "!mystr:~%%i,1!"=="" set strlen=%%i && goto :_endfor
:_endfor
::echo 字符串: "%mystr%"
echo 长 度: %strlen%
set strlen=
goto began
|

※ Batchinger 致 Bat Fans:请访问 批处理编程的异类 ,欢迎交流与共享批处理编程心得! |
|
2006-3-30 15:24 |
|
|
3742668
荣誉版主
      
积分 2013
发帖 718
注册 2006-2-18
状态 离线
|
『第 3 楼』:
使用 LLM 解释/回答一下
先谢了
不过可能是我没说清楚,我的本意是把取字符串长度的那部分做成一个类似函数的东东,然后在别的批处理中可以直接拷贝后调用。呵呵,积累多了以后也好偷懒。
如果我现在另外写个批处理的话我就可以直接把我的bflen标号以后的语句直接拷贝过去然后用call调用。
Thanks in advance.
But maybe I didn't make it clear. My original intention was to make the part of getting the string length into something like a function, so that it can be directly copied and called in other batch scripts. Hehe, it's easier to be lazy when there are more accumulations.
If I write another batch script now, I can directly copy the statements after the bflen label and call them using call.
|
|
2006-3-30 16:44 |
|
|
yardian
中级用户
  
积分 305
发帖 85
注册 2005-5-23
状态 离线
|
『第 4 楼』:
使用 LLM 解释/回答一下
二楼的代码2每次都要算1000次,效率太慢了啊?
The code 2 on the second floor has to calculate 1000 times each time, which is too slow.
|
|
2006-12-17 05:53 |
|
|
namejm
荣誉版主
       batch fan
积分 5226
发帖 1737
注册 2006-3-10 来自 成都
状态 离线
|
『第 5 楼』:
使用 LLM 解释/回答一下
不会的,只会执行字符串长度数的次数就跳出来了,请注意 && goto :_endfor 这一句。
It won't. It will just jump out after executing the number of times equal to the length of the string. Please pay attention to the line && goto :_endfor.
|

尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。 |
|
2006-12-17 07:29 |
|
|
zzs162
初级用户
 
积分 27
发帖 11
注册 2006-3-16
状态 离线
|
|
2007-2-18 20:30 |
|
|
skyearth
初级用户
 
积分 34
发帖 13
注册 2006-7-20
状态 离线
|
『第 7 楼』:
使用 LLM 解释/回答一下
代码2也有问题,如果包括中文也只视为1个字节
There is also a problem with code 2. If Chinese is included, it is only regarded as 1 byte
|
|
2007-3-2 00:35 |
|
|
slore
铂金会员
      
积分 5212
发帖 2478
注册 2007-2-8
状态 离线
|
『第 8 楼』:
使用 LLM 解释/回答一下
Originally posted by skyearth at 2007-3-1 11:35:
代码2也有问题,如果包括中文也只视为1个字节
这个单纯只的是位数。
vbs直接len(str)……方便
Originally posted by skyearth at 2007-3-1 11:35:
There is also a problem with code 2. If Chinese is included, it is only regarded as 1 byte.
This is simply about the number of bits.
It's convenient for VBS to directly use len(str)...
|
|
2007-3-2 00:40 |
|
|
slore
铂金会员
      
积分 5212
发帖 2478
注册 2007-2-8
状态 离线
|
『第 9 楼』:
使用 LLM 解释/回答一下
最大的bug是只能单行。
The biggest bug is that it can only be single-line.
|
|
2007-3-2 00:43 |
|
|
skyearth
初级用户
 
积分 34
发帖 13
注册 2006-7-20
状态 离线
|
『第 10 楼』:
使用 LLM 解释/回答一下
可能没描述清楚,我是想判断“中英文字符混排”时,用BAT如何得到实际的字节位数,比如:“这是一个test”,如果用代码一,其结果12就是正确的结果,而代码二,其结果就是8,与实际的字节数不一致,这只是字数。
我是在做一个可在原地显示进度信息的脚本,由于汉字的长度不能正确计算,因此,其退格的长度就不好控制,请理解。
Maybe not described clearly. I want to judge how to get the actual number of bytes when mixing Chinese and English characters with BAT. For example, "这是一个test", if using code one, the result 12 is the correct result, while code two has a result of 8, which is inconsistent with the actual number of bytes, this is just the number of characters.
I am making a script that can display progress information in place. Because the length of Chinese characters cannot be calculated correctly, the length of backspace is not easy to control, please understand.
|
|
2007-3-3 03:20 |
|