您的当前位置:首页正文

cad7

来源:图艺博知识网
机械设计

7.1 Visual LISP的循环控制函数

所谓“循环结构”就是通过反复的“测试条件 ─ 执行代码 ─ 测试条件”方法,来

重复地执行一些表达式,直至满足某个测试条件为止。

在Visual LISP中主要的循环控制函数有:while、repeat、foreach 与mapcar。

7.1.1 while循环

while 函数将对测试表达式进行求值,如果不为 nil(吻合条件),则重复执行循环子句中的表达式,直到测试表达式的求值结果为 nil(不吻合条件)为止,然后跳出循环。其标准语法如下:

(while (testexpression) [statement...] )

while 函数将返回最后 statement 表达式最新的值,如果不需返回值,可以使用princ

语法来静默退出。我们将以图7-1所示来说明循环的原理观念:

为了要让循环内可以达到计数、累加等功用,一般在循环开始前都会像这样先设定一些循环内需要初始值

对称括号

以此范例为例,变量 i 的值一开始为零,当循环每执行一圈就做这些事并将 i 累加 1,那么绕 25

次以后,当i = 26 时.就会结束此循环了

图7-1 循环的原理观念

100

第7章 循 环

接下来,我们还要以图7-2所示来说明循环的正确设计观念。

对称括号

对称括号对称括号

对对称称括括号号

对称括号

让对称括号呈巢状结构是正确的循环设计让对称括号呈互相干扰的结构是错误的循环设计(这也就是所谓的“逻辑错误”!)

图7-2 循环的正确设计观念

以下范例将提示操作者输入整数的上下限、定出整数的范围,然后计算整个范围内的整数和与平均值:

(1);;;while loop demo------whiledemo.lsp

(2);;;function: calculate sum and average of integers (3)

(4)(defun c:whiledemo(/ fInt sInt temp sum sumx i avr) (5) (setq fInt(getint \"\\n请输入第一个整数:\")) (6) (setq sInt(getint \"\\n请输入第二个整数:\")) (7) (if (> fInt sInt) (8) (progn

(9) (setq temp fInt) (10) (setq fInt sInt) (11) (setq sInt temp) (12) ) (13) )

(14) (setq i fInt) (15) (setq sum 0)

101

机械设计

(16) (setq sumx 0) (17) (while(<= i sInt) (18) (setq sum (1+ sum )) (19) (setq sumx (+ sumx i)) (20) (setq i(1+ i )) (21) )

(22) (setq avr(/ sumx sum)) (23) (princ \"\\n从 \")(princ fInt)

(24) (princ \" 到 \")(princ sInt)(princ \" 的整数和 = \")(princ sumx) (25) (princ \"\\n平均值 = \")(princ avr) (26) (princ) (27))

执行结果:请输入第一个整数:1

请输入第二个整数:100 从1到100的整数和 = 5050 平均值 = 50

分析:这个程序的第(7)行~第(12)行是一个判断子句,如果fInt大于sInt,则交换两数,并保证 fInt 为较小的整数。第(17)行~第(21)行则为while循环,它将计算从fInt到sInt的所有整数和。在这个循环中,我们首先判断i(i的初始值为fInt)是否小于sInt,如果是,那么计数器变量 sum 就等于sum+1,整数和变量sumx就等于sumx+i。然后再让i再加1(往前进),直到i等于sInt,结束并跳出循环为止。

在while内的表达式里,一般都要对表达式里的变量进行修改,否则很容易造成无限循环,导致所谓的“逻辑错误”。例如,在上例的循环语法中,(setq i(1+i))的语法作用就是希望每执行一次循环,就将i加1,如此下去,i一定会等于sInt,这样就会因为不吻合while(<= i sInt)而跳出循环了。

7.1.2 repeat循环

102

第7章 循 环

repeat 函数的重点是对循环体中的每一个表达式进行指定次数的求值计算,并返回最后一个表达式的值。其标准语法如下:

(repeat int [expression...] )

其中,参数int为正整数,代表循环的次数。repeat 返回值将变为最后一个计算的原子或表达式的值。如果不需要返回值,您可以使用(princ)语法来静默退出。例如,以下范例将绘出一个三角函数 sin 的曲线图:

(1);;;repeat loop demo------repeatdemo.lsp (2);;;function: draw a sin curve (3)

(4)(defun C:repeatdemo(/ pt pt1 pt2 a1 a i bm cc) (5) (setq pt1 (getpoint \"\\n请输入起始点:\")) (6) (setq pt pt1) (7) (setq oo pt1) (8) (setq i 0) (9) (repeat 36 (10) (ang1 i)

(11) (setq pt2 (list (+ (car pt) (/ i 90.0)) (+ (cadr pt) (sin ang)))) (12) (command \"line\" pt1 pt2 \"\") (13) (setq pt1 pt2) (14) (setq i (+ i 10)) (15) )

(16) (command \"zoom\" \"w\" (getvar \"extmin\") (getvar \"extmax\")) (17) (command \"pedit\" \"l\" \"y\" \"j\" \"c\"

(18) (getvar \"extmin\") (getvar \"extmax\") \"\" \"s\" \"\") (19) (command \"scale\" \"l\" \"\" oo 50) (20) (command \"zoom\" \"E\") (21) (princ) (22) )

(23)(defun ang1 (a1)

(24) (setq ang (* pi (/ a1 180.0))) (25))

103

机械设计

执行结果:此程序将在 AutoCAD 屏幕上画出一个填满屏幕的 Sin 曲线。

分析:程序中的第(9)行~第(15)行将画出36条短线以拟合一条0°~360°的sin曲线。第(10)行将调用ang1函数来将度量转为弧度量。第(16)行程序将用来取得这36条线所在的范围。第(17)行会将这36条线段连成一条聚合线,并将之拟合为一条 spline。第(19)、(20)行将调整Sin曲线的显示比例,并令其充满屏幕。

104

第7章 循 环

7.1.3 foreach函数

foreach 函数可将表中的所有成员以指定变量的身份带入表达式中求值。其标准语法如下:

(foreach name list [expression...])

foreach 函数遍历表list,将其中每一个元素依次赋给变量name,并对每一个表达式求值。foreach函数可以指定任意多个表达式。foreach返回最后一个表达式计算的值,如果未指定表达式,则返回nil。如果不需返回值,可以用(princ)静默退出。例如:

(foreach n ' (1 2 3) (princ n))

其中,n 为变量,表达式 (princ n) 将顺序打印表 (1 2 3) 中的各值。其输出结果为:

1233

最后的那个3是foreach的返回值。

7.1.4 mapcar函数

mapcar 会将一个或多个表参数里的各个元素提供给指定函数,以进行求值,并将求值结果变成表返回。其标准语法如下:

(mapcar function list1... listn)

其中,function 是要应用到表 list1...listn 的函数。实例如下:

(setq a 1 b 2 c 3) (mapcar '1+ (list a b c))

这样的语法将输出:(2 3 4)。这样的二条程序语法就等于以下三条程序:

(1+ a) (1+ b) (1+ c)

如果写成这样:

(mapcar '* (list a b c )(list 10 10 10))

则将输出:(10 20 30)。

这样的一条程序语法就等于以下三条程序:

(* a 10) (* b 10) (* c 10)

105

机械设计

7.2 VBA的循环控制函数

VBA可支持的常用循环控制函数有:

do...loop for...next while...wend for each...next do...loop

以下就为您分节叙述这些循环控制函数。

7.2.1 do...loop 循环

使用do循环来重复执行一组表达式,且重复次数不定。do...loop 语句有几种变化形式,不过每种都是计算数值条件以决定是否继续执行。例如,If...Then condition必须是一个数值或者值为 True(非零)或 False(零)的表达式。其标准语法如下:

do while condition statements... loop

在do...loop循环中,只要condition为True,就执行statements。当VBA执行这个do循环时,首先会测试 condition。如果condition为False(零),就跳过循环中所有的表达式。如果condition为True(非零),则VBA就会执行循环中的表达式,然后退回到Do While的开头,再测试条件,周而复始。因此,只要 condition 为 True 或非零,循环就可以随意执行任意次数。如果condition 一开始就得到 False 的结果,则不会执行该循环。例如,以下程序范例将计算某一目标字符串 MyText 在另一字符串中出现的次数,程序中只要发现目标字符串就执行循环:

Dim position, count position = 1 Do While position>0

position = InStr(position+1,MyText, \"\") count = count + 1

106

第7章 循 环

Loop

上示这个程序的另一个意义就是说:如果目标字符串未出现在另一个字符串中,则InStr 将返回 0,而且不再执行循环而跳出循环。

do...loop 语句的另一种变体形式是:先执行语法,然后在每次执行后才去测试condition。这种形式将保证 statements 至少被执行过一次。其标准语法如下:

do statements... loop while condition

还有两个类似前两个语法的do...loop变体,所不同的是:只要 condition为False而不是true,它们就执行循环。其标准语法如表7-1所示。

表7-1 do loop标准语言

do until condition do statements... statements... loop do loop until condition (循环零次或多次) (至少循环一次) 7.2.2 for...next 循环 在您不确定循环内需要重复执行多少次时,宜使用 do...loop 循环。但是,如果已知道要执行的次数时,则最好使用 for...next 循环。与 do...loop 循环不同的是:for...next 循环使用一个叫做计数器的变量,每重复一次循环之后,计数器变量的值就会增加或者减少。其标准语法如下: for counter = start To end [Step increment] statements... next [counter] 其中,参数counter、start、end 与 increment都是数值型的。例如,一样是7.1.1节中whiledemo.lsp 范例的功能(计算两个整数之间的所有整数和与平均值),我们以for...next循环的方式来改写,程序本文如下: (1)'for next loop demo------fornext.dvb

(2)'function: calculate the sum and average of integers (3)

(4)Option Explicit

107

机械设计

(5)Public Sub fornext()

(6)Dim fInt As Integer, sInt As Integer (7)Dim temp As Integer, i As Integer (8)Dim sum As Integer, sumx As Integer (9)Dim str As String, str2 As String (10)fInt = InputBox(\"Input an integer:\") (11)sInt = InputBox(\"Input another integer:\") (12)If fInt > sInt Then

(13) temp = fInt: fInt = sInt: sInt = temp (14)End If

(15)sum = 0: sumx = 0 (16)For i = fInt To sInt (17) sum = sum + 1 (18) sumx = sumx + i (19)Next

(20)str = \"ths sum from \" & fInt & \" to \" & sInt & \" = \" & sumx (21)str2 = \"the average = \" & CStr(sumx / sum) (22)MsgBox str & vbCr & str2 (23)End Sub

分析:在程序的第(13)行与第(15)行采用了符号“:”,使原来分别要写成3行和2

行的程序,一行就解决了。第(16)行~第(19)行就是使用 for...next 循环来计算从fInt到sInt中所有整数和及个数。

7.2.3 while...wend 循环

while...wend 循环的作用是:while 函数将对条件表达式进行求值,如果不为nil,则执行循环中的表达式。然后重复这个过程,直到测试条件表达式的求值结果为nil并跳出循环为止。其标准语法如下:

While condition [statements] Wend

举例如下:

108

第7章 循 环

Dim icount As integer Dim ssetObj as acadselection While (icount <> 0)

Set ssetObj = thisdrawing.selections.item (icount -1) ssetObj.delete icount = icount -1 wend

这个范例将检查选集里是否有元素存在,如果有,就将其删除。

7.2.4 for each...next循环

for each...next是VBA 中一个非常有用的循环。这个循环语法提供了一种可以遍历集

合对象中所有元素的功能。例如,在 AutoCAD 中,要将一个选集(Selection Set)中所有对象的颜色变成红色,就可用下列程序:

dim acadObj as Object '声明 acadObj 为对象变量 For Each acadObj in ssetObj 'ssetObj 为选集 AcadObj.color = acRed Next acadObj

7.2.5 exit函数

exit函数将允许循环在遇到某些特殊值时跳出循环。exit 语法有五种形式,它们分别是:

Exit Do

跳出 Do...Loop 循环

Exit For 跳出 For...Next 或 For Each...Next Exit Function 结束含有本语法的函数 Exit Sub 结束含有本语法的程序 Exit Property 结束含有本语法的属性

下面的范例将接收所输入的数字,并显示它的倒数,如果输入为 0,则跳出:

(1)'break loop program------exitwhile.dvb (2)'function: break loop (3)

(4)Option Explicit

109

机械设计

(5)Public Sub exitwhile() (6)Dim x As Double, y As Double (7)Do

(8) x = InputBox(\"Input a real number:\") (9) If (x = 0) Then (10) Exit Do (11) End If (12) y = 1 / x

(13) MsgBox (\"The reciprocal = \" & y) (14)Loop While (1) (15)End Sub

执行结果:在InputBox中输入数值,计算它的倒数后在信息框中显示出。如果输入数

为 0,则结束程序。

分析:在本程序第(14)行中的 while 要判断的表达式值为1,按道理这个循环是不中断的,会永远执行下去。所以,我们在第(10)行中使用了exit do函数,它位于一个if判断式中。当输入值为0时,就会执行exit do语法来强制跳出循环。

课 后 习 题

一、多选题

1. while 循环与 repeat 循环差别在于:( )

(A)While 将根据判断式与条件来循环执行,而 repeat 函数的主要重点则是对循环体中的每一个表达式进行指定次数的求值计算,并返回最后一个表达式的值

(B)repeat 将根据判断式与条件来循环执行,而 while 函数的主要重点则是对循环体中的每一个表达式进行指定次数的求值计算,并返回最后一个表达式的值

(C)没有差别 (D)以上都不对

2. 以下有关 foreach 函数的叙述,哪个是正确的:( )

(A)foreach 函数可将表中的所有成员以指定变量的身份带入表达式中求值 110

第7章 循 环

(B)(foreach n ' (1 2 3 4) (princ n)) 的返回值是 12344 (C)与 repeat 函数的功能类似 (D)以上都不对 3. 以下三条程序:

(- a 10) (- b 10) (- c 10)

就相当于:( )

(A)(foreach '- (list a b c )(list 10 10 10)) (B)(mapcar '- (list a b c )(list 10 10 10)) (C)(while '- (list a b c )(list 10 10 10)) (D)以上都不对

4. 当您不确定循环内需要重复执行多少次时,宜使用:( ) (A)for...next 循环 (B)while...wend 循环 (C)do...loop 循环 (D)以上都不对

5. 以下哪一个循环可以遍历集合对象中所有元素:( ) (A)for...next 循环 (B)for each...next 循环 (C)while...wend 循环 (D)以上都不对 6. 以下哪个为 exit 函数的特性:( )

(A)允许循环在遇到某些特殊值时跳出循环 (B)命令立刻跳出循环

(C)指定再循环三次就跳出循环 (D)以上都不对

二、实作问答题

1. 请设计多重剪取功能,让每次在设定边界之后就能一次选择一组图形来做Trim的动作(用AutoLISP编写)。

111

机械设计

设计询问句:(1)请点取边界线 !

(2)请输入选取框的第一点: (3)输入选取框的第二点:

解答文件名:MTRIM.LSP

2. 如上题,设计多重延伸功能(用 AutoLISP/VLISP/VBA 编写)。

设计询问句:(1)请点取边界线 !

(2)请输入选取框的第一点 : 112

第7章 循 环

(3)输入选取框的第二点 :

解答文件名:MEXTEND.LSP , V-MEXTEND.LSP , MEXTEND.DVB

3. Flange 图形,在机械设计的绘制中,是很常见的设计组件。我们希望您能设计一个可依操作者输入的设计条件来自动绘出 Flange 图形的程序(用AutoLISP/VLISP/VBA编写)。

设计提问: (1)请输入 Flange 的中心点:

(2)请输入 Flange 的外圆半径: (3)请输入 Flange 的内圆半径: (4)通过圆孔中心的中心线: (5)圆孔直径: (6)圆孔数:

(7)第一个圆孔的起始角度:

解答文件名:FLANGE.LSP , V-FLANGE.LSP , FLANGE.DVB 4. 在AutoCAD中,“图形锁定”的其中功能之一——Quadran(锁定圆或弧的四分之一点)虽然不错,但是,却没有锁定圆或弧的八分之一点的功能,您能设计一个吗?(用 AutoLISP/VLISP 编写)

设计询问句:

例如:您想拉一条线到一圆的八分点上,加载本程序后,请按下述指令流程执行。 指令:Line

起点:(请在屏幕上选取任一点)

113

机械设计

下一点:(P8)

下一点:(V-P8) 或的(请点取屏幕上已经事先绘好的一圆上) 下一点:

解答文件名:P8.LSP , V-P8.LSP

114

因篇幅问题不能全部显示,请点此查看更多更全内容

Top