批处理之家's Archiver

defanive 发表于 2009-1-17 15:30

批处理中set /a 极大的误区

关于 set /a 中极大的误区,几乎所有的批处理教材中都有这个错误,误导了至少80%的人!

这句:set /a a+=1
一切教学资料上的解释都是:与
set /a a=%a%+1
相等同!

那么我们做一个有趣的实验:[code]@echo off
set a=0
for /l %%b in (1,1,5) do set /a a+=1
echo a=%a%
pause[/code]得到的输出是:
a=5
请按任意键继续. . .

那么根据教材所说的,等同于 set /a a=%a%+1 ,我们测试一下效果:[code]@echo off
set a=0
for /l %%b in (1,1,5) do set /a a=%a%+1
echo a=%a%
pause[/code]得到的输出是:
a=1
请按任意键继续. . .

教材和资料都错了!
正确的解释应是:set /a a+=1 与 set /a a=a+1 对等!
多了两个%括住就造成的极大的错误!

正确对等的代码是:
[quote]@echo off
set a=0
for /l %%b in (1,1,5) do set /a a=a+1
echo a=%a%
pause[/quote]

输出:
a=5
请按任意键继续. . .

当然,无聊的话下面这样写也是对等的,当然及不简便:[code]@echo off
setlocal enabledelayedexpansion
set a=0
for /l %%b in (1,1,5) do set /a a=!a!+1
echo a=%a%
pause[/code]开启变量延迟,用!括住也是正确的



那么,请大家看完这篇东西之后,记住不要再犯同样的错误,同样不要再去误导他人:
set /a a+=1
不等于
set /a a=%a%+1
应等于
set /a a=a+1

tireless 发表于 2009-1-17 16:46

是[color=red]预处理[/color]的关系吧,与 set 无关。

[quote]set a=0
for /l %%b in (1,1,5) do set /a a=%a%+1[/quote]
当读取以上整个 for 语句后,执行语句前进行了[color=red]预处理[/color],最后实际执行的是:

for /l %%b in (1,1,5) do set /a a=[color=red]0[/color]+1

[[i] 本帖最后由 tireless 于 2009-1-17 18:35 编辑 [/i]]

defanive 发表于 2009-1-17 18:02

通常的讲,set /a a+=1正确的应该是set /a a=a+1而不是set /a a=%a%+1

实际上for这五次set /a a=%a%+1的变量设置都被延迟了

但是set /a a=a+1是set /a的一个特性,设置的变量会立即生效

所以set /a a+=1就结果来看,是立即生效的,对应的应该是set /a a=a+1

的确不关set的事,关教材资料的事

pusofalse 发表于 2009-1-17 18:15

特性如此~[code]If you use any of the logical or modulus operators, you will need to
enclose the expression string in quotes.  Any non-numeric strings in the
expression are treated as environment variable names whose values are
converted to numbers before using them.  If an environment variable name
is specified but is not defined in the current environment, then a value
of zero is used.  This allows you to do arithmetic with environment
variable values without having to type all those % signs to get their
values.[/code]This allows you to do arithmetic with environment
variable values without having to type all those % signs to get their
values.
set /a a=%a%+1实际执行的是set /a a=+1而不是set /a a=0+1
set /a a=a+1 才是set /a a=0+1,但在for中它是会实时改变的。

BBCC 发表于 2009-1-17 21:12

所以说,微软在这方面做得很乱,两个标准……

sjzong 发表于 2009-4-14 15:42

哦!谢谢楼主,以后要注意了!

鳌头七队 发表于 2011-6-1 19:32

是批处理的变量延迟搞的鬼

Demon 发表于 2011-6-1 19:49

那些垃圾教程只会误人子弟罢了

qzwqzw 发表于 2011-6-1 21:25

说实话,
没有看到哪里的教材是这样写的
楼主提及“几乎所有的批处理教材”
不知是否能够例举一二?

Batcher 发表于 2011-6-1 23:31

这个帖子也许是楼主刚接触批处理的时候写的,大家淡定了。

applba 发表于 2011-6-2 04:52

set命令能够自行识别变量名,并完成变量值的替换。
还有一个用法类似,if defined varname,也不需要%。

szylmzs 发表于 2011-6-2 09:47

应该是变量延迟的问题

cjiabing 发表于 2011-6-3 21:46

哈哈,我比较怕数学,没有上过当,不过现在经常用到set /a a+=1,其它两个用得少。
写教材一定要自己亲自测试过代码才可以引用,否则害人不浅!~

andy七少 发表于 2011-6-9 12:40

for中的%a%只会应用上一个语句set设置的环境变量
还是变量延迟高的鬼嘛!

guaiwu 发表于 2011-10-4 16:12

有心提醒了。   心意领会了

Fantasys 发表于 2011-10-12 17:59

我觉得官方解释不能说错,只是在批处理有些特别的地方罢了。开启变量延迟就可以了,说明它解释还是对的。

网上邻居 发表于 2016-3-17 14:41

预处理机制而已。

小程936 发表于 2016-6-17 09:38

set /a x=a,a=b,b=x
可以交换a和b的位置,你怎么看?

ai20110304 发表于 2016-10-20 23:33

谢谢 分享     :)

tiger999 发表于 2017-1-27 15:07

QAQ LZ不要误导别人啊,吓得差点误解了我习惯了3年的知识
这是因为变量延迟的问题,这和所谓的%%没有关系
你只需要加一个setlocal enabledelayedexpansion,把%换成!就好了,QAQ

ShenMian 发表于 2018-2-18 00:31

这是延迟变量的问题,而不是什么教程乱讲。若考虑延迟变量应该写为set /a a+=1等价于set /a a=!a!+1,如果没有开启本地自动化操作则是错误的语句。所以set /a a=%a%+=1并没有错误。

ai20110304 发表于 2018-8-29 23:29

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=81221&ptid=3104]11#[/url] [i]applba[/i] [/b]


    大侠说到点子上了。细心点发现

ai20110304 发表于 2018-8-29 23:31

[b]回复 [url=http://www.bathome.net/redirect.php?goto=findpost&pid=19129&ptid=3104]1#[/url] [i]defanive[/i] [/b]


    这个复合运算符隐含延迟变量的功能。就像java中复合运算符隐式一个强制类型转换

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.