《第6章 过程》由会员分享,可在线阅读,更多相关《第6章 过程(50页珍藏版)》请在金锄头文库上搜索。
1、第6章 过 程 VBVB应应用用程程序序是是由由一一系系列列过过程程组组成成的的,前前面面各各章章所所涉涉及及到到的的例例题题和和习习题题,除除了了定定义义一一些些公公共共的的常常量量、变变量量或或数数组组以以外外,编编写写的的代代码码都都是是在在事事件件过过程程中中。而而实实际际应应用用中中,往往往往要要根根据据问问题题的的复复杂杂程程度度,按按照照结结构构化化程程序序设设计计的的思思想想,将将应应用用程程序序按按功功能能划划分分为为若若干干个个模模块块,每每个个模模块块还还可可继继续续细细分分为为子子模模块块。模模块块和和子子模模块块均均是是可可重重复复调调用用的的程程序序段段,由由编编程
2、程人人员员按按照照一一定定的的格格式式建立,称为用户自定义过程,简称过程。建立,称为用户自定义过程,简称过程。 2第第6章章 过程过程6.1过程与函数过程与函数一、函数过程一、函数过程二、二、 子过程子过程三、三、 参数传递参数传递四、变量、过程的作用域四、变量、过程的作用域五、递归五、递归6.2 常用算法举例常用算法举例236.1过程与函数l前面几章中,我们已经常使用到了系统提供的内部函数过程和事件过程。在应用程序的编写中,有时问题比较复杂,按照结构化程序设计的原则,可把问题逐步细化,分成若干个功能模块,通过VB提供的自定义过程将功能模块定义成一个个过程,供事件过程多次调用。使用过程的好处是
3、使程序简练,便于调试和维护。l除了系统提供的内部函数过程和事件过程外,用户可自定义过程: 以Sub保留字开始的为子过程 以Function保留字开始的为函数过程 以Property保留字开始的为属性过程 以Event保留字开始的为事件过程主要介绍SUB子过程和Function函数过程4一、函数过程:引例6.1已知多边形的各条边的长度,要计算多边形的面积。计算多边形面积,可将多边形分解成若干个三角形。计算三角形面积的公式如下: xyz定义函数过程areaPublic Function area(x!, y!, z!) As Single Dim c! c = 1 / 2 * (x + y + z
4、) area = Sqr(c * (c - x) * (c - y) * (c - z)End Function调用函数过程:Sub command1_click() 输入若干个三角形边长 S1=area(a,b,c) S2=area(c,d,e) S3=area(e,f,g) Print S1+S2+S3End Sub计算三个三角形的面积,使用的公式相同,不同的计算三个三角形的面积,使用的公式相同,不同的仅仅是边长,因此首先定义一个求三角形面积的函仅仅是边长,因此首先定义一个求三角形面积的函数过程,然后像调用标准函数一样多次调用它。数过程,然后像调用标准函数一样多次调用它。51 1、函数过程
5、的定义:、函数过程的定义:自定义函数过程:自定义函数过程:有两种方法: (1)利用“工具”菜单下的“添加过程”命令定义,生成一个函数的框架 (2)利用代码窗口直接定义 函数过程形式: StaticPublicPrivateFunction 函数过程名函数过程名(参数列表) As 类型 局部变量或常数定义 语句块 函数名 = 返回值 函数过程体 Exit Function 语句块 函数名函数名 = 返回值返回值 End Function 函数过程名函数过程名:命名规则同变量名As类型:类型:函数返回值的类型,缺省为变体类型。 参数列表形式参数列表形式: ByVal变量名变量名()As 类型类型
6、称为形参或哑元,只能是变量或数组名(这时要加“()”),仅表示参数的个数、类型,无值。Byval表参数是值传递,否则是地址传递。无参时,函数名后的括号不能省略,这是函数过程的标志。 函数名函数名 = 返回值返回值 在函数体内至少对函数名赋值一次 Exit Function :表示退出函数过程StaticPublicPrivate说明:62 2、函数过程的调用、函数过程的调用 函数过程调用同标准函数调用形式:函数过程名函数过程名(参数列表参数列表) 参数列表:称为实参或实元,它必须与形参个数相同,位置与类型一一对应,可以是同类型的常量、变量、表达式。函数调用不能单独调用,必须作为表达式或表达式的
7、一部分,再配以其他的语法成分构成语句。Private Sub Command1_Click() s= “VB程序设计教程5.0版” Print MyReplace(s, 5.0, 6.0) Text1=MyReplace(Text1,”cd”,”3”)End SubFunction MyReplace(s$, OldS$, NewS$) Dim i%, lenOldS% lenOldS = Len(OldS) i = InStr(s, OldS) Do While i 0 s= Left(s, i - 1) + NewS + Mid(s, i + lenOldS) i = InStr(s, O
8、ldS) Loop MyReplace = s End FunctionS ”5.0” ”6.0”MyReplace(s$, OldS$, NewS$) 7二、二、 子过程子过程 函数过程给编程带来了优点但也有不足: (1)若编写过程,不是为了获得某个函数值,而是为了某种功能的处理,如控件的移动;(2)或者要获得多个结果,如对一组数的排序等。此时用函数过程,有些不便。VB中提供了功能更强、使用更灵活的子过程。 1.1.引引例例6.3 编写一个两个数交换的过程供多次调用。Swap (x,y)子过程的定义主调程序调用Swap子过程Public Sub Swap(x, y) Private Sub
9、Form_Click() Dim t Dim a, b t = x a = 10 x = y b = 20 y = t Call Swap (a, b)或者 Swap a,bEnd Sub Print a=;a,,b=; b End Sub82.2.子过程定义:子过程定义: StaticPublicPrivateSub 子过程名子过程名(参数列表) 局部变量或常数定义 语句块 Exit Sub 语句块 End Sub子过程体子过程名、参数列表规定同函数过程中对应项的规定,但当无形参时,括号也应无4.4.子过程与函数过程区别子过程与函数过程区别:(1)函数过程名有值,有类型,在函数体内至少赋值一
10、次; 子过程名无值,无类型,在子过程体内不能对子过程名赋值;(2)调用时,子过程调用是一句独立的语句。 函数过程不能作为单独的语句加以调用,必须参与表达式运算。(3)用函数过程和子过程没有严格的规定,但只要能用函数过程定义的,肯定能用子过程定义,反之不一定。即子过程适用面广。一般当过程有一个函数值,使用函数过程较直观; 反之若过程无返回值,或有多个返回值,使用子过程较直观3.3.子过程的调用子过程的调用 子过程名子过程名 参数列表 或 Call 子过程名子过程名(参数列表)6.1 Sub 过程 2 Sub2 Sub过程的调用过程的调用 Sub Sub过程调用有两种格式:过程调用有两种格式: 第
11、第1 1种格式:种格式:Call Call 过程名过程名 (参数列表)(参数列表) 第第2 2种格式:过程名种格式:过程名 参数列表参数列表说明:说明:(1) (1) 参数列表参数列表 代表要传送给代表要传送给SubSub过程的实际的值,可以为常过程的实际的值,可以为常 量、变量、数组元素、数组名或表达式等形式。参数之间量、变量、数组元素、数组名或表达式等形式。参数之间 用逗号分隔。与形参相对应,这里的参数称为实际参数用逗号分隔。与形参相对应,这里的参数称为实际参数 (简称实参)。(简称实参)。(2) (2) 在调用在调用SubSub过程时,实参和形参按它们的位置建立一一对过程时,实参和形参按
12、它们的位置建立一一对 应关系,实参的值或地址传给对应位置上的形参后,执行应关系,实参的值或地址传给对应位置上的形参后,执行 过程体,当遇到过程体,当遇到End SubEnd Sub或或Exit SubExit Sub语句时,结束语句时,结束SubSub过过 程,并返回主程序(调用过程语句所在的程序称为主程程,并返回主程序(调用过程语句所在的程序称为主程 序)。序)。 6.1 Sub 过程 1 Sub1 Sub过程的定义过程的定义说明:说明:(1) (1) 过程名过程名 过程标识符,命名规则与变量命名相同。过程标识符,命名规则与变量命名相同。(2) (2) (参数列表参数列表) ) 代表传递给代
13、表传递给SubSub过程的参数。该类参数本过程的参数。该类参数本 身没有值,只代表参数的个数、位置和类型,系统并不为身没有值,只代表参数的个数、位置和类型,系统并不为 其分配实际内存空间,因此也称为形式参数其分配实际内存空间,因此也称为形式参数( (简称形参简称形参) )。(3) (3) 在在VBVB中,形参只能为变量和数组,不得为常数或表达式;中,形参只能为变量和数组,不得为常数或表达式; 形参可以有多个,两两之间用逗号隔开。形参可以有多个,两两之间用逗号隔开。(4)(4)形参可以省略形参可以省略( (但过程名后的圆括号不得省略但过程名后的圆括号不得省略) ),这样的过,这样的过 程称为无参
14、过程。程称为无参过程。 (5) Private|Public (5) Private|Public 用于确定过程的作用域,用于确定过程的作用域,StaticStatic用用 于确定过程变量为静态变量。于确定过程变量为静态变量。(6) (6) 语句组:又称为过程体,用来实现过程功能的代码。语句组:又称为过程体,用来实现过程功能的代码。11例6.4分别编一计算某级数部分和的子过程和函数过程,并调用。级数为: 精度为:函数过程实现求部分级数和 Function Function jishu1jishu1(x!, eps#)(x!, eps#) As Double Dim n%, s#, t#n =
15、1: s = 0: t = 1Do While (Abs(t) = eps) s = s + t t = t * x / n n = n + 1Loop jishu1 = s jishu1 = sEnd FunctionEnd Function子过程实现求部分级数和 Sub jishu2Sub jishu2(s#s#, x!, eps#) Dim n%, t#n = 1: s = 0: t = 1Do While (Abs(t) = eps) s = s + t t = t * x / n n = n + 1LoopEnd SubEnd Subf1 = jishu1(2#, 0.000001)
16、 调用函数过程Call jishu2(f2, 2#, 0.000001) 调用子过程或 jishu2 f2,2#,0.00001 12 程序运行流程:程序运行流程: Private Sub Command1_Click() Dim f1#, f2# f1 = jishu1(2#, 0.000001) Call jishu2(f2, 2#, 0.000001) Print f1=; f1, f2 = ; f2 End SubSub jishu2(s#, x!, eps#) s=表达式表达式End Sub找子过程名调用找子过程名调用jishu2Function jishu1(x!, eps#) A
17、s Doubl jishu1=表达式表达式End Function找函数名调用找函数名调用jishu1jishu1函数名带了值返回函数名带了值返回 6.2 过程调用中的参数传递 形形参参与与实实参参之之间间的的数数据据传传递递是是调调用用过过程程和和返返回回过过程程运运算算结结果果的的桥桥梁梁。在在过过程程被被调调用用之之前前,所所有有形形参参既既没没有有具具体体的的存存储储地地址址也也无无具具体体的的值值,只只是是起起到到模模板板的的作作用用。当当程程序序流流程程转转向向执执行行过过程程时时,实实参参和和形形参参按按一一定定方方式式结结合合,形形参参获获取取了了相相应应的的值值后后执执行过程
18、体,过程的运算结果还可通过形参带回到主程序。行过程体,过程的运算结果还可通过形参带回到主程序。6.2 过程调用中的参数传递1 1 参数传递参数传递1 1)传地址方式)传地址方式 传地址是传地址是VBVB默认的参数传递方式。在这种方式下,将实参默认的参数传递方式。在这种方式下,将实参的存储地址传给形参,使形参与实参共用同一存储单元,因此的存储地址传给形参,使形参与实参共用同一存储单元,因此在过程中对形参的任何操作实质都是对相应实参的操作。在过程中对形参的任何操作实质都是对相应实参的操作。 要实现传地址方式可体现在过程定义和过程调用中。在过要实现传地址方式可体现在过程定义和过程调用中。在过程定义时
19、,形参前省略关键字程定义时,形参前省略关键字ByRefByRef(或加(或加ByRefByRef显式说明);显式说明);在过程调用时,对应位置的实参是相同类型的变量或数组名。在过程调用时,对应位置的实参是相同类型的变量或数组名。实参为常数或表达式是无法实现地址传递的。实参为常数或表达式是无法实现地址传递的。6.2 过程调用中的参数传递1 1 参数传递参数传递1 1)传地址方式)传地址方式采用传地址方式进行参数传递时需要注意以下问题:采用传地址方式进行参数传递时需要注意以下问题: 当实参为变量时,参数传递时是把变量的地址传递给形参,当实参为变量时,参数传递时是把变量的地址传递给形参,使实参与形参
20、共享同一存储单元。使实参与形参共享同一存储单元。 当实参为数组时,参数传递时是把数组的存储地址传递给当实参为数组时,参数传递时是把数组的存储地址传递给形参,使实参数组与形参数组共享同一存储区域。编写过程定形参,使实参数组与形参数组共享同一存储区域。编写过程定义时,形参中数组名只须带括号,不指定元素个数;编写过程义时,形参中数组名只须带括号,不指定元素个数;编写过程调用语句时,实参数组名既无括号,也不能指定元素个数。调用语句时,实参数组名既无括号,也不能指定元素个数。 6.2 过程调用中的参数传递1 1 参数传递参数传递2 2传值方式传值方式 当以传值方式调用一个过程时,形参拥有独立的存储单元,
21、当以传值方式调用一个过程时,形参拥有独立的存储单元,实参只是将值复制给形参。被调过程的操作是在形参自己的存实参只是将值复制给形参。被调过程的操作是在形参自己的存储单元中进行,如果形参的值被改变了,对应位置的实参值不储单元中进行,如果形参的值被改变了,对应位置的实参值不会受任何影响。当过程调用结束时,形参所占用的存储单元也会受任何影响。当过程调用结束时,形参所占用的存储单元也同时被释放。同时被释放。6.2 过程调用中的参数传递1 1 参数传递参数传递2 2)传值方式)传值方式 当以传值方式调用一个过程时,形参拥有独立的存储单元,当以传值方式调用一个过程时,形参拥有独立的存储单元,实参只是将值复制
22、给形参。被调过程的操作是在形参自己的存实参只是将值复制给形参。被调过程的操作是在形参自己的存储单元中进行,如果形参的值被改变了,对应位置的实参值不储单元中进行,如果形参的值被改变了,对应位置的实参值不会受任何影响。当过程调用结束时,形参所占用的存储单元也会受任何影响。当过程调用结束时,形参所占用的存储单元也同时被释放。同时被释放。6.2 过程调用中的参数传递1 1 参数传递参数传递2 2)传值方式)传值方式实现传值方式也可体现在过程调用和过程声明中。实现传值方式也可体现在过程调用和过程声明中。(1 1)在过程调用时,如果实参为常量、表达式或为带括号的)在过程调用时,如果实参为常量、表达式或为带
23、括号的 变量,参数传递是按传值方式进行的。变量,参数传递是按传值方式进行的。(2 2)定义过程时,如果形参前加)定义过程时,如果形参前加ByValByVal关键字。调用过程时,关键字。调用过程时, 不管实参以何种形式,参数传递均采用传值方式。不管实参以何种形式,参数传递均采用传值方式。 19三、三、 参数传递参数传递在调用过程时,一般主调过程与被调过程之间有数据传递,即主调过程的实参传递给被调过程的形参(虚参),完成实参与形参的结合,然后执行被调过程体。在VB中,实参与形参的结合有两种方法:传址(ByRef)与传值(ByVal),其中传址又称为引用,是默认的方法。区分两种结合的方法是在要使用传
24、值的形参前加有“ByVal”关键字。1. 1. 传址与传值传址与传值 传址:传址: 形参得到的是实参的地址地址,形参值的改变同时也改变实参的值也改变实参的值。 传值:传值: 形参得到的是实参的值值,形参值的改变不会影响实参的值不会影响实参的值。 选用传值还是传址的使用规则:选用传值还是传址的使用规则:(1)形参是数组、自定义类型时只能用传址方式,若要将过程中的结果返回给主调程序,则形参必须是传址方式。这时实参必须是同类型的变量名,不能是常量或表达式。(2)若形参不是(1)中的两种情况,一般应选用传值方式。这样可增加程序的可靠性和便于调试,减少各过程间的关联。20例例6.5 两个变量的交换Sub
25、 Swap1(ByVal x%, ByVal y%) t% = x: x = y: y = tEnd SubSub Swap2(x%, y%) t% = x: x = y: y = tEnd SubPrivate Sub Command1_Click() a% = 10: b% = 20 Swap1 a, b 传值传值 Print A1=; a, B1=; b a = 10: b = 20 Swap2 a, b 传址传址 Print A2=; a, B2=; bEnd Sub运行结果A1=10 B1=20A2=20 B2=10书上P92P93页例子212. 2. 数组参数的传递数组参数的传递
26、在VB中允许参数是数组,数组只能通过传址方式进行传递。 在传递数组时要注意: 在实参和形参中可只写数组名,或忽略维数的定义,但圆括号不能省。 被调过程可通过Lbound和Ubound函数确定实参数组的下、上界。 例 6.7 编一函数tim,求任意一维数组中各元素之积。 调用tim,求 和 Function tim(a() As Integer) Dim t#, i% t = 1 For i = Lbound(a) To Ubound(a) t = t * a(i) Next i tim = tEnd Function调用:调用:Sub Command1_Click() Dim a%(1 To
27、5),b%(3 To 8) t1# = tim(a() t2 #= tim(b() Print t1, t2 End Sub223 3、对象参数:、对象参数:VB允许用对象作为过程的参数,即窗体或控件可以作为过程的参数。 对象只能通过传址方式传送。(1)窗体参数:)窗体参数:定义过程时将窗体作为形参,要在形参表中用“As Form”来定义形参变量的类型是窗体。在调用时也要对应地用窗体名作为实参。(2)控件参数:)控件参数:定义过程时将控件作为形参,在形参表要用“As Control”来定义形参变量的类型是控件。在调用时也要对应地用控件名作为实参。6.4 变量、过程的作用域 VBVB的的应应用用
28、程程序序由由若若干干个个过过程程组组成成,这这些些过过程程一一般般保保存存在在窗窗体体文文件件(.frm.frm)或或标标准准模模块块文文件件(.bas)(.bas)中中。变变量量是是过过程程代代码码中中必必不不可可少少的的,一一个个变变量量、过过程程所所处处的的位位置置不不同同,可可被被访访问问的的范范围围也也不不同同。变变量量、过过程程可可被被访访问问的的范范围围称称为为变变量量、过过程程的的作作用用域。域。6.4 变量、过程的作用域1 1 过程的作用域过程的作用域1 1)VBVB应用程序的组成应用程序的组成6.4 变量、过程的作用域1 1 过程的作用域过程的作用域1)窗体(模块)级过程窗
29、体(模块)级过程 窗体级过程是指在窗体或标准模块通用声明段定义的、用窗体级过程是指在窗体或标准模块通用声明段定义的、用PrivatePrivate关键字限制的过程,这类过程只能在所属的窗体或标准关键字限制的过程,这类过程只能在所属的窗体或标准模块中被其它过程调用。模块中被其它过程调用。6.4 变量、过程的作用域1 1 过程的作用域过程的作用域2 2)全局级过程)全局级过程 在窗体或标准模块中定义的过程默认是全局的,也可用在窗体或标准模块中定义的过程默认是全局的,也可用Pub1icPub1ic关键字声明。全局级过程可供该应用程序的所有窗体和关键字声明。全局级过程可供该应用程序的所有窗体和所有标准
30、模块中的过程调用,但根据过程所处的位置不同,其所有标准模块中的过程调用,但根据过程所处的位置不同,其调用方式有所区别:调用方式有所区别:(1) (1) 在窗体中定义的全局级过程,该窗体之外的其它过程要调在窗体中定义的全局级过程,该窗体之外的其它过程要调 用,必须在过程名前加该过程所在的窗体名。用,必须在过程名前加该过程所在的窗体名。(2) (2) 在标准模块中定义的过程,外部过程均可调用,但过程名在标准模块中定义的过程,外部过程均可调用,但过程名 必须惟一,否则要加标准模块名。必须惟一,否则要加标准模块名。 6.4 变量、过程的作用域2 2 变量的作用域变量的作用域 变量的作用域是指变量能被访
31、问的范围。根据变量声明的变量的作用域是指变量能被访问的范围。根据变量声明的位置及限制范围关键字(位置及限制范围关键字(PrivatePrivate或或PublicPublic)的不同,变量的作)的不同,变量的作用域可分为过程级、窗体(模块)级和全局级。过程级和窗体用域可分为过程级、窗体(模块)级和全局级。过程级和窗体(模块)级常被称为私有级变量,而全局级也常被称为公有级(模块)级常被称为私有级变量,而全局级也常被称为公有级变量。变量。 6.4 变量、过程的作用域2 2 变量的作用域变量的作用域1 1)过程级变量)过程级变量 过程级变量的作用范围限制在该过程内部,也就是说在一过程级变量的作用范围
32、限制在该过程内部,也就是说在一个过程内部声明的变量,只有该过程内部的代码才能访问或改个过程内部声明的变量,只有该过程内部的代码才能访问或改变变量的值。该类变量通常用来存储过程中的临时数据。在过变变量的值。该类变量通常用来存储过程中的临时数据。在过程内部使用程内部使用DimDim或或StaticStatic关键字来声明变量。关键字来声明变量。 6.4 变量、过程的作用域2 2 变量的作用域变量的作用域1 1)过程级变量)过程级变量2 2)窗体(模块)级变量)窗体(模块)级变量 窗体(模块)级变量的作用域限制在声明它的窗体(模块)窗体(模块)级变量的作用域限制在声明它的窗体(模块)中,该窗体(模块
33、)中的所有过程均可访问该变量,其它窗体中,该窗体(模块)中的所有过程均可访问该变量,其它窗体(模块)则不能。在窗体(模块)的通用段中用(模块)则不能。在窗体(模块)的通用段中用PrivatePrivate或或DimDim关键字声明。关键字声明。 6.4 变量、过程的作用域2 2 变量的作用域变量的作用域1 1)过程级变量)过程级变量2 2)窗体(模块)级变量)窗体(模块)级变量3 3)全局级变量)全局级变量 全局级变量在所有模块的所有过程都能使用,它的作用范全局级变量在所有模块的所有过程都能使用,它的作用范围是整个应用程序,在模块的通用段中使用围是整个应用程序,在模块的通用段中使用Public
34、Public关键字声明。关键字声明。 6.4 变量、过程的作用域2 2 变量的作用域变量的作用域变量级别确定的原则:变量级别确定的原则:(1) (1) 如果变量只在某一个过程中使用,它的运算结果也不被其如果变量只在某一个过程中使用,它的运算结果也不被其 它过程再次使用,则可以声明为过程级变量。如本书中的它过程再次使用,则可以声明为过程级变量。如本书中的 大部分例题,采用的都是这种级别的变量。大部分例题,采用的都是这种级别的变量。(2) (2) 如果变量将在同一窗体的多个过程中被用到,且彼此之间如果变量将在同一窗体的多个过程中被用到,且彼此之间 还有相互关系,则可以声明为窗体(模块)级变量。还有
35、相互关系,则可以声明为窗体(模块)级变量。 (3) (3) 如果变量将在多个窗体中被用到,且彼此之间还有相互关如果变量将在多个窗体中被用到,且彼此之间还有相互关 系,则可以声明为全局变量。系,则可以声明为全局变量。32四、变量、过程的作用域四、变量、过程的作用域作用域:变量、过程可被访问的范围。变量、过程随所处的位置不同,可被访问的范围不同。 1.1.过程的作用域过程的作用域 窗体/模块级:加Private关键字的过程,只能被定义的窗体或模块中的过程调用。 全局级:加Public关键字(缺省)的过程,可供该应用程序的所有窗体和所有标准模块中的过程调用。332. 2. 变量的作用域变量的作用域
36、局部变量:在过程内用Dim声明的变量(或不加声明直接使用的变量),只能在本过程中使用。 窗体/模块级变量:在“通用声明”段中用Dim语句或用Private语句 声明的变量,可被本窗体/模块的任何过程访问。 全局变量:在 “通用声明”段中用Public语句声明的变量,可被本应用程序的任何过程或函数访问。34例如在下面一个标准模块文件中不同级的变量声明:Public Pa As integer 全局变量Private Mb As string *10 窗体/模块级变量Sub F1( ) Dim Fa As integer 局部变量End SubSub F2( ) Dim Fb As Single
37、局部变量End Sub35若在不同级声明相同的变量名若在不同级声明相同的变量名, ,系统按局部、窗体系统按局部、窗体/ /模块、全局次模块、全局次序访问(即优先访问作用域小的变量名)。序访问(即优先访问作用域小的变量名)。如: Public Temp As integer 全局变量 Sub Form_Load() Dim Temp As Integer 局部变量 Temp=10 访问局部变量 Form1.Temp=20 访问全局变量必须加窗体名 Print Form1.Temp, Temp 显示 20 10 End Sub363. 3. 静态变量静态变量局部变量声明: Dim 声明声明,随过程
38、的调用而分配存贮单元,每次调用都对变量初始化;过程体结束,变量的内容自动消失,存贮单元释放。 Static 声明声明,每次调用过程,变量保持原来的值。 声明形式:Static 变量名 AS 类型 Static Function 函数过程名(参数列表) As 类型 Static Sub 子过程名(参数列表)过程名前加Static,表示该过程内的局部变量都是静态变量。例例6.9 比较比较Dim和和Static的区别。一个的区别。一个Form_Click()和一个求和函数和一个求和函数sum()组成的应用程序,在组成的应用程序,在Form_Click()中中5次调用函数次调用函数sum(): Pri
39、vate Sub Form_Click() Dim i% ,isum% For i = 1 To 5isum = sum(i)Print isum; Next i End SubPrivate Function sum(n As Integer) Dim j As Integer j = j + n sum = jEnd Function结果为:1 2 3 4 5Static j As Integer,结果?结果为:1 3 6 10 1537Sub f1(x) x=f2(xx)*3End SubSub Command1_Click() Call f1(y)End SubFunction f2(
40、x) f2=f3(x)+3End SubFunction f3(x) f3=x*xEnd SubSub f1(x) Call f1(y)End Sub过程的直接调用过程的直接调用Sub Command1_Click() Call f1(y)End Sub过程的递归调用过程的递归调用五、递归五、递归: :381.1.递归的概念递归的概念 用自身的结构来描述自身就称为“递归”。例对阶乘的定义: 2. 递归过程递归过程 过程在自身定义的内部调用自己。 例例6.10 编fac(n)=n! 的递归函数 Function fac(n As Integer) As Integer If n = 1 Then
41、 fac = 1 Elsefac = n * fac(n - 1) End If End FunctionSub Command1_Click() Print “fac(4)=”;fac(4)End Sub结果:fac(4)=2439递推回归在递归处理中,用栈来实现。栈中存放形参、局部变量、返回地址。递推过程:每调用自身,当前参数压栈,直到达到递归结束条件。回归过程:不断从栈中弹出当前的参数,直到栈空。思考: 若上述fac函数中少了 : If n = 1 Then fac = 1 即仅有语句: fac = n * fac(n - 1) 或 n=0 程序运行将造成何结果?注意:1、递归算法设计简
42、单,但消耗的机时和占据的内存空间比非 递归大。2、构成递归的要素:具备递归条件;具备递归结束条件及结 束时的值;能用递归形式表示,并且递归向终止条件发展。fac(2)=2*fac(1)fac(1)=1fac(4)=4*6fac(3)=3*2fac(2)=2*1fac(3)=3*fac(2)fac(4)=4*fac(3)40本节重点和难点 1. 确定自定义的过程是子过程还是函数过程 函数过程名有值,子过程名无值。 过程有一个返回值,则使用函数过程; 若返回多个值或无返回值,一般使用子过程。2过程中形参的个数和传递方式的确定 过程中参数的作用是实现过程与调用者的数据通信。 (1)从主调程序获得初值
43、,值传递。 (2)将结果返回给主调程序,地址传递。3. 实参与形参结合时对应问题 个数、类型、位置、次序一一对应。 形参是值传递,对应实参可以是表达式、常量、数组元素。 形参是地址传递,对应实参只能是简单变量。 4、数组、记录类型、对象只能是地址传递。414. 变量的作用域问题 局部变量、静态变量、全局变量特点、作用 5. 递归调用出现“栈溢出”递归过程中有终止的条件和终止时的值或某种操作; 每递归调用一次,其中的参数要向终止方向收敛。42递归常见错误:递归常见错误:递归调用出现“栈溢出” 在递归调用时,其中的参数要向终止方向收敛。如下求阶乘的递归函数过程: Public Function f
44、ac(n As Integer) As IntegerIf n = 1 Then fac = 1Else fac = n * fac(n - 1)End IfEnd FunctionPrivate Sub Command1_Click() Print “fac(5)=”;fac(5) Print “fac(5)=”;fac(-5) 栈溢出栈溢出End Sub43一、基本算法一、基本算法1 1、数制转换数制转换 例6.13 将一个十进制整数m转换成 r (216)进制字符串。 方法:将m不断除 r 取余数,直到商为零,以反序得到结果。6.2 6.2 常用算法举例常用算法举例2 2442 2、例例
45、6.146.14加密和解密加密和解密简单加密的思想是: 将每个字母C加一序数K,式子 c=chr(Asc(c)+k), 例如序数k为5,这时 “A”“F”, “a”“f”,“B”“G” 当加序数后的字母超过“Z”或“z”则 c=hr(Asc(c)+k -26)。 解密为加密的逆过程。45二、排序二、排序选择、冒泡、插入法排序、合并排序等。前两种排序欲排序的数据全部输入后,再进行排序;插入法排序每输入一项,马上插入到数组应在的位置,数组始终有序。例例6.17 6.17 插入排序,插入排序,实现的步骤: (1)输入欲排序的数据项x;在数组a中找x应所处的位置j; (2)从数组的最后一个元素开始到下
46、标j依次往后移,使j位置空出; (3)将x放入位置j处,一个数据插入完成; (4)有若干个数重复(1)(3)。46例例P114P114:合并排序合并排序,将两个有序的数组合并成另一个有序的数组。假设有序的数组为A、B,合并后的数组为C。合并排序的思想为:(1)先在A、B数组中各取第一个元素进行比较,将小(递增次序)的元素放入C数组;(2)取小的元素所在数组的下一个元素与上次比较后较大的元素比较,重复上述过程,直到某个数组被先排完;(3)将另一个数组剩余元素抄入C数组,合并排序完成。47三、查找三、查找 1、顺序查找、顺序查找 例例6.15。 顺序查找根据查找的关键值与数组中的元素逐一比较(数组
47、可无序)Public Sub Search(a() As Variant, ByVal key As Variant, index%) Dim i% For i = LBound(a) To UBound(a) If key = a(i) Then 找到,元素的下标在index中,结束查找 index = i Exit Sub End If Next i index = -1 找不到, index形参的值为-1End Sub平均查找次数平均查找次数 n/248Keya(mid) low=mid+1 查找区域缩小一半,继续直到找到或查找区域中无元素.本例用递归实现6.16 Sub birsear
48、ch(a(), low%, high%, key , index%)2、二分法查找(折半法查找)、二分法查找(折半法查找)要查找的数组必须有序必须有序。 思想:要查找的关键值Key同数组的中间mid项元素比较:12345678111222333444555666777888Lowhighmid444Key49四、四、 二分法求根二分法求根思想: 已知求根区间a,b有一根,每次把求根区间缩小一半,直到找到解或求根区间足够小。方法:求a,b的中点c,判断 f(c)=0, c为求得的根,结束; f(a)与f(c)同号,则a,c无根,c代替a; 否则c,b无根,c代替b; 使求根区间缩小一半,重复上述
49、步骤,直到区间小于精度。Public Function halfRoot(ByVal a!, ByVal b!) Dim c! Do While Abs(b - a) 0.00001 c = (a + b) / 2 If f(c) = 0 Then Exit Do ElseIf f(a) * f(c) 0 Then a = c Else b = c End If Loop halfRoot = cEnd Function50五、字符串处理五、字符串处理例6.20 编写一个英文打字训练的程序,要求如下:(1)在标签框内随机产生30个字母的范文;(2)当焦点进入文本框时开始计时,并显示当时时间;(3)在键入文本框按产生的范文输入相应的字母;(4)当键入满了30个字母后结束计时,禁止向文本框输入内容 ,与范文逐一比较,显示打字的速度和正确率。