中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [小把戏]交换两个变量的值而不使用临时变量
« [1] [2] »
作者:
标题: [小把戏]交换两个变量的值而不使用临时变量 上一主题 | 下一主题
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『楼 主』:  [小把戏]交换两个变量的值而不使用临时变量

  通用型的:
@echo off
set var1=abc
set var2=123
echo 交换前: var1=%var1% var2=%var2%
set var1=%var2%& set var2=%var1%
echo 交换后: var1=%var1% var2=%var2%
pause
  如果要交换的两个变量的值是数字的话,还可以使用如下两种方案:

  方案一:
@echo off
set /a num1=123,num2=456
echo 交换前: num1=%num1% num2=%num2%
set /a num1=%num2%,num2=%num1%
:: set num1=%num2%& set num2=%num1% 也是可以的
echo 交换后: num1=%num1% num2=%num2%
pause
  方案二:
@echo off
:: 会有数值范围的限制,即 num_a 与 num_b 的和必须在2^-31~2^31-1这个范围内
set /a num_a=123,num_b=456
echo 交换前: num_a=%num_a% num_b=%num_b%
set /a num_a=%num_a%+%num_b%-%num_a%,num_b=%num_a%+%num_b%-%num_b%
echo 交换后: num_a=%num_a% num_b=%num_b%
pause




尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2007-1-25 08:16
查看资料  发短消息 网志   编辑帖子
PPdos
高级用户




积分 783
发帖 268
注册 2006-12-26
状态 离线
『第 2 楼』:  被我先抢座了^^

纪录在案 以备后用!~



菩提本无树,明镜亦非台,本来无一物,何处惹尘埃.
2007-1-25 08:27
查看资料  发短消息 网志   编辑帖子
hangyug
初级用户




积分 99
发帖 43
注册 2007-1-12
状态 离线
『第 3 楼』:  

呵呵,试了一下,真是,,,还在琢磨呢。。。



我很菜,但我很努力~
2007-1-25 08:29
查看资料  发送邮件  发短消息 网志   编辑帖子
0401
中级用户

带走



积分 435
发帖 88
注册 2005-9-24
状态 离线
『第 4 楼』:  

不错,巧妙利用环境变量扩充的特性。其实这三个例子应该都算是一个意思吧。

2007-1-25 09:02
查看资料  发短消息 网志   编辑帖子
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 5 楼』:  



  Quote:
Originally posted by 0401 at 2007-1-24 20:02:
不错,巧妙利用环境变量扩充的特性。其实这三个例子应该都算是一个意思吧。

  如果你仔细看了代码的话,你就会觉得它们并不是同一种思路:通用型的代码利用了 & 来交换两个变量的值,方案一利用了 set /a 的一些特性,方案二在利用 set /a 的特性的基础上,还使用了A+B-A=B、A+B-B=A这个算式来交换变量的值。

  其实,这几段演示代码还引出了一个比较有趣的话题:set var1=%var2%已经把var2的值赋给var1了,按理说,此时var1的值已经发生了改变,但是,在使用 & 引出另一个赋值语句 set var2=%var1% 的时候,为什么var2还能得到var1发生改变前的值?难道var1这个变量能同时保存一个以上的值吗?set /a num1=num2%,num2=%num1%也存在类似的现象。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2007-1-25 10:11
查看资料  发短消息 网志   编辑帖子
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 6 楼』:  


交换二个变量值算法非常简单.

假如有两个杯子: A和B, 要将A,B杯子中的水互换, 就要用到第三个杯子C了.
1. 将A杯的水倒入C杯;
2. 将B杯的水倒入A杯;
3. 将C杯的水倒入A杯;

这样就完成了二个杯子中的水的互换.
namejm兄给出的三种方法中, 第一种利用管道符交换变量,后两种是差不多的意思, 用逗号运算符来交换变量.

其实这种方法是利用脚本的特殊性实现的, 如果大家熟悉C语言中宏的话就不难理解了. 脚本靠解释器执行, 批处理脚本解释器在解释时必须先执行宏展开, 并且在一般情况下为一行一行解释.
set x=2
set y=3
set x=%y%&set y=%x%

这里最后一句宏展开为set x=3&set y=2, 自动将x与y值展开至赋值语句中了, 因此不用中间变量而交换变量值. 这里解释器扮演了中间变量.
其实真正不用中间变量交换两个变量值, 在二进制程序中也可以实现的方法也有.

就是用位运算来实现的, 呵呵~  大家想想?



业精于勤而荒于嬉,形成于思而毁于随。
2007-1-25 10:25
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子
qzwqzw
银牌会员

天的白色影子


积分 2342
发帖 635
注册 2004-3-6
状态 离线
『第 7 楼』:  

C语言教材的教学案例
set /a "a=b^a"
set /a "b=b^a"
set /a "a=b^a"
另外,四则运算也可以实现

只是没有异或运算灵活无限制
set /a a=a+b
set /a b=a-b
set /a a=a-b


2007-1-25 10:41
查看资料  发短消息 网志   编辑帖子
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 8 楼』:  

是的, 四则运算无论从效率还是使用范围来说都没有位运算那么好.
@echo off
set a=2
set b=3
echo a=%a%  b=%b%
set /a "a=b^a"
set /a "b=b^a"
set /a "a=b^a"
echo a=%a%  b=%b%
set /a a=a+b
set /a b=a-b
set /a a=a-b
echo a=%a%  b=%b%
pause




业精于勤而荒于嬉,形成于思而毁于随。
2007-1-25 10:46
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子
0401
中级用户

带走



积分 435
发帖 88
注册 2005-9-24
状态 离线
『第 9 楼』:  

在单个语句之中,变量的赋值并不能马上被扩展(引用),只能在下一个语句中才能被扩展。单个语句是指 if for 语句以及使用括号 && & ||等连接的语句。除非启用了环境变量扩展延迟,并且使用“!”来代替“%”才能扩展变量值。所以我才说namejm兄你的三个例子意思差不多。。。

2007-1-25 10:59
查看资料  发短消息 网志   编辑帖子
simazhuo
新手上路





积分 1
发帖 2
注册 2006-12-31
状态 离线
『第 10 楼』:  

不错,收藏了

2007-1-25 11:07
查看资料  发送邮件  发短消息 网志   编辑帖子
namejm
荣誉版主

batch fan


积分 5226
发帖 1737
注册 2006-3-10
来自 成都
状态 离线
『第 11 楼』:  



  Quote:
Originally posted by pengfei at 2007-1-24 21:25:脚本靠解释器执行, 批处理脚本解释器在解释时必须先执行宏展开, 并且在一般情况下为一行一行解释.

  呵呵,想起了这就是批处理的预处理机制^_^,准确的说法似乎应是 逐句执行。



尺有所短,寸有所长,学好CMD没商量。
考虑问题复杂化,解决问题简洁化。
2007-1-25 11:17
查看资料  发短消息 网志   编辑帖子
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 12 楼』:  

是的, 一般情况下为一行一行解释, 应该改为逐句解释执行, 用括号括起来的复合语句, 解释器也是一次执行的.



业精于勤而荒于嬉,形成于思而毁于随。
2007-1-25 11:20
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子
lxmxn
版主




积分 11386
发帖 4938
注册 2006-7-23
状态 离线
『第 13 楼』:  


  感觉还是9楼的 0401 说得比较在理,如果启用变量延迟,以上的某些示例可能不成立。
@echo off
set var1=abc
set var2=123
echo 交换前: var1=%var1% var2=%var2%
set var1=%var2%&call set var2=%%var1%%
echo 交换后: var1=%var1% var2=%var2%
pause


2007-1-25 13:49
查看资料  发送邮件  发短消息 网志   编辑帖子
pengfei
银牌会员




积分 1218
发帖 485
注册 2006-7-21
来自 湖南.娄底
状态 离线
『第 14 楼』:  

lxmxn兄用call %%var1%%实际没有展开, 和!var!一样, 是变量延迟的另一种用法. 因此变量交换也无法实现.



业精于勤而荒于嬉,形成于思而毁于随。
2007-1-26 12:03
查看资料  发送邮件  发短消息 网志  OICQ (573381312)  编辑帖子
htysm
高级用户




积分 866
发帖 415
注册 2005-12-4
状态 离线
『第 15 楼』:  

精彩。精彩。

2007-1-27 05:33
查看资料  发送邮件  发短消息 网志   编辑帖子
« [1] [2] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: