1、第8章,过 程与函数,过程的定义:在设计一个规模较大、复杂程度较高的程序时,往往根据需要按功能将程序分解成若干个相对独立的部分,然后对每个部分分别编写一段程序,这些程序段称为过程。过程是构成程序逻辑部件的基本单位,将程序分割成较小的逻辑部件可以简化程序设计任务,结构化设计就是建立在这个思路之上。 每个过程完成一个具有特定目的的任务。,过程的分类:,事件过程VB中有两类过程: Sub 过程通用过程Function 过程 事件过程是对发生的事件进行处理的代码 通用过程是由用户根据自己的需要定义和编写的、可供事件过程多次调用的程序段。 二者的区别是: 通用过程是由程序中的语句调用。 事件过程往往是由
2、用户事件触发。,8.1 Sub 过程(子程序过程),Sub 过程是指以规定语法结构组织的、可以被重复调用的、具有特定功能的、相对独立的语句块。1、 声明 Sub 过程声明 Sub 过程就是在窗体或标准模块的代码窗口编写一个能实现预期功能的语句块。 声明Sub过程的语法格式为:Private | Public Static Sub 过程名() Exit Sub 过程体End Sub 注意: Sub 过程名无值,无类型。,上一页,下一页,返回首页,说明:,1、每个通用过程都有一个过程名(由用户自己指定,规定同变量名),同一模块中过程名不得重复。 2、过程前加上Public关键字或缺省,则该过程为全
3、局级过程,可以被应用程序的所有窗体模块或标准模块中的过程调用(在窗体中定义,调用时应加窗体名)。 3、过程前加上Private关键字,则该过程为模块级过程,只有在声明它的模块中才可以调用此过程。 4、在过程名前加上Static关键字,表明该过程的变量都是静态变量。 5、形参列表是传递到过程中的变量名(多个时用“,”分隔),它指明了调用时传递给过程的参数的类型和个数, 格式为:变量名() AS 数据类型(过程级变量),上一页,下一页,返回首页,如:Sub Tryout(x as integer, y as integer),x=x+100y=y*6Print x,yEnd Sub 6、注意:过程
4、可以有参数,也可以不带任何参数。通用过程可以在标准模块中建立,也可以在窗体模块中建立。 7、建立通用过程可以使用以下两种方法: “工程”添加模块”,添加一标准模块;“工具”添加过程” 在标准模块或窗体模块中,直接输入通用过程的代码。,上一页,下一页,返回首页,2、调用 Sub 过程,在其他过程中执行已声明的Sub过程被称为对Sub 过程的调用。 1使用Call语句调用Sub过程格式:Call 过程名(实参列表) 2. 将过程名作为语句使用格式: 过程名 特点: Sub 过程的调用是一句独立的语句。,上一页,下一页,返回首页,说明:,1、可以直接调用本模块中声明的过程或标准模块中声明的全局过程;
5、 2、当定义的过程重名时,调用过程时,过程名前应加模块名修饰; 3、如果要调用窗体模块中声明的全局过程,调用时过程名前应加窗体名。 4、调用Sub 过程时,若省略 Call ,则 外面的括号也必须省略。 5、调用Sub 过程时,每个实参可以加单独的括号。 6、实参数表,是往被定义过程的形参列表传递的数据;因此,其数据类型需要和形参列表保持一致。实参可以是常量、变量、数组,或复杂表达式,但无论是什么都必须有确定的值。,上一页,下一页,返回首页,例1:将求三角形的面积的代码存放在过程triarea(a,b,c)中,边长从三个文本框中输入,如果符合构成三角形的条件,则调用该过程,否则调用suberr
6、过程。 Lt1.vbp 程序如下: Private Sub triarea(area As Double, x As Double, y As Double, z As Double)Dim s As Doubles = (x +y + z) / 2area = Sqr(s - x) * (s - y) * (s - z) * s) End SubPrivate Sub suberr(intyrn As Integer)intyrn = MsgBox(“请检查您的数据“, vbYesNo + vbInformation, “数据错误“) End Sub,3、 使用 Sub 过程,上一页,下一页
7、,返回首页,Private Sub Command1_Click()Dim a#, b#, c#, s#Dim intYesorNo As Integera = Val(Text1.Text)b = Val(Text2.Text)c = Val(Text3.Text)If a + b c And b + c a And c + a b ThenCall triarea(s, a, b, c) 使用Call关键字,实际参数用括号括起来Print “ 面积 =“; sElsesuberr intYesorNo 不使用Call关键字,实际参数不用括号End If End SubSub 过程的调用是一
8、句独立的语句。,上一页,下一页,返回首页,Function 过程 与Sub 过程 的主要区别是:Function 过程可返回一个值到调用的过程 1、 声明 Function 过程 格式:Public|Private Static Function 函数过程名() As = 返回值语句 Exit Function End Function 注意:Function 过程名有值,有类型。在函数体内,函数名可以当变量名使用,函数的返回值就是通过对函数名的赋值语句来实现的。即函数值通过函数名返回。函数过程需要返回的值的类型由 As 设置。,8.2 Function 过程(函数),上一页,下一页,返回首页
9、,2、 调用 Function 过程,Function 过程的调用,与标准函数(内部函数)相同。通常用在表达式中格式:函数名()特点:不能独立存在,必须参加表达式的运算。如:下面是已知直角三角形两直角边的值,计算斜边的函数。function myfun(A as integer,B as integer) as stringmyfun=sqr(A*A+B*B)End functionlabel1.caption=myfun(Cint(text1.text),cint(text2.text)strX=myfun(width,height),上一页,下一页,返回首页,例2:将例1中两个Sub过程改
10、为Function过程。Private Function triarea(x As Double, y As Double, z As Double)Dim s As Doubles = (x + y + z) / 2triarea = Sqr(s - x) * (s - y) * (s - z) * s) End FunctionPrivate Sub Command1_Click()Dim a#, b#, c#, s#, intYesorNo%a = Val(Text1.Text) : b = Val(Text2.Text)c = Val(Text3.Text)If a + b c And
11、 b + c a And c + a b ThenPrint “ 面积 =“; triarea(a, b, c)ElseintYesorNo = suberr( ) 无参数时,括号不能省略End If End Sub,上一页,下一页,返回首页,Sub过程和Function函数过程中的中的参数称为形式参数(形参),在程序中调用Sub过程和Function函数过程时中称为实际参数(实参) 。 在调用过程时,就是把“实参”依次按位置传递给被调用过程的“形参” ,然后执行被调用过程中的语句。参数传递时相当于给变量赋初值。 如: Print greatcd(x, y)Public Function gr
12、eatcd(m As Integer, n As Integer) 参数传递有两种模式:按值传递与 按址传递,8.3 过程中参数的传送,按值传递就是将实参的值传送给被调用过程中的形参。即:系统把实参复制一份传送给形参。这样,被调用的过程如果改变了形参的值,也不会改变实参的值。在VB中,传值方式的标志为:在形参前加上ByVal。这种传递方式是一种单向的数据传递,即调用时只能由实参的值传递给形参,调用结束不能由形参将操作结果返回给实参。实参可以是常数、变量或表达式。,1、 按值传递,上一页,下一页,返回首页,例:写出下列程序的运行结果,Sub tryout(ByVal x as integer,
13、ByVal y as integer)x=x+100y=y*6print “x=“;x.”y=“;y End SubSub Form_click()Dim a%,b%a=10:b=20tryout a,bPrint “a=“;a,”b=“;b End Sub,传值: X=110 y=120 a=10 b=20,传址: X=110 y=120 a=110 b=120,上一页,下一页,返回首页,2、 按址传递变量的引用,传址方式是将实参在内存的地址传递给形参,也就是实参、形参公用内存的“地址”。在VB中,按址传递数据是在形参前加上ByDef(默认方式)。这种传递方式是一种双向的数据传递,即调用时实
14、参将值传递给形参;调用结束由形参将操作结果返回给实参。当用传址方式时,实参只能是变量、数组名,不能是常数、表达式。 修改前例题 ByVal ByDef 再写其运行结果,例5:下面的程序求解 S1=nS2=n+nSn=n+n+n(n个n累加)并输出S1到Sn。n为自然数,从文本框值输入。函数过程(注意传值与传址的区别): ByDef Public Function sum(m As Integer, ByVal n As Integer)sum = mDo While n 1 sum = sum + mn = n - 1Loop End Function,上一页,下一页,返回首页,事件过程:,P
15、rivate Sub Command1_Click()Dim i%, s( ), a%, k%Clsa = Val(Text1.Text)ReDim s(1 To a)For i = 1 To a 按值传送 s(i) = sum(a, i)k = k + 1Print “i=“; i, “k=“; k, “s“ s(i)If k a Then Exit ForNext i End Sub,按址传送,上一页,下一页,返回首页,3、 数组作过程的参数,Visual Basic允许把数组作为实参传送到过程中。数组作参数是通过传地址方式传送。在传送数组时,除遵守参数传送的一般规则外,还应注意以下几点:
16、1为了把一个数组的全部元素传送给一个过程,应将数组名分别写入形参表中,并略去数组的上下界,但括号不能省略。 Private Sub Sort(a() As single) End Sub 其中形参“a( )”即为数组。,2被调过程可通过Lbound和Ubound函数确定实参数组的上、下界。3当用数组作形参时,对应的实参必须也是数组,且类型一致。4实参和形参结合是按地址传递,即形参数组和实参数组共用一段内存单元。例如:定义了实参数组b(1 to 8),给它们赋了值,调用Sort()函数过程的形式如下:Sort b( ) 或 Call Sort( b() ) 实参数组后面的括号可以省略,但为便于阅
17、读,建议一般不要省略为好。,3、 数组作过程的参数,调用时形参数组a和实参数组b虚实结合,共用一段内存单元,如图6-7所示。因此在Sort()过程中改变数组a的各元素值,也就相当于改变了实参数组b中对应的元素的值,当调用结束时,形参数组a成为无定义。b(1) b(2) b(3) b(4) b(5) b(6) b(7) b(8)a(1) a(2) a(3) a(4) a(5) a(6) a(7) a(8) 参数为数组时虚实结合示意图,3、 数组作过程的参数,8.4 可选参数和可变参数,1、 可选参数在过程的形参列表中加入Optional关键字,就可以指定过程的参数为可选的。如果指定了可选参数,则
18、参数表中此参数后面的其它参数也必是可选的,并且要用Optional关键字来声明。,例6:求两个数的和的函数过程。 lt6.vbp 函数过程: Public Function mysum (first As Integer, second As Long, Optional third )mysum = first + secondIf Not IsMissing(third) Then mysum = mysum + third End Function,事件过程:,Private Sub Command1_Click()Dim a As Integer, b As Long, c As Do
19、ubleDim sum As Integera = 10: b = 20Sum=mysum(a, b)Print “sum=“; Suma = 10: b = 20: c = 30Sum=mysum(a, b, c)Print “sum=“; Sum End Sub IsMissing( )检测可选参数是否被省略,上一页,下一页,返回首页,2、 不定数量的参数(可变参数),一般说来,过程调用中的参数个数应等于过程说明的参数个数。在传递参数时,如果要求参数的数目可以变化,则在函数过程或Sub过程的形参前可加 ParamArray关键字(不能与ByVal ByDef连用)指明。 格式如下:,Sub
20、 过程名( 其他参数, ParamArray ( ) ),上一页,下一页,返回首页,Private Sub Command1_Click()Dim s( ), a%, b As Long, c As Variant, d As Doubles = Array(1, 2, 3, 4, 5)Print “sum=“; multisum( s(0), s(2), s(4) )a = 1000: b = 10000: c = 100: d = 10Print “sum=“; multisum( a, b, c, d ) End SubPublic Function multisum( ParamArr
21、ay p() )Dim int1%, sum as variantFor int1= LBound(p) To UBound(p)sum = sum + p(int1)Nextmultisum=sumEnd Sub,上一页,下一页,返回首页,8.6 过程的嵌套和递归,1、 过程的嵌套,在程序中调用一子过程,而在子过程中又调用另外的子过程,这种程序结构称为过程的嵌套。过程的嵌套调用执行过程如下图:,2、 过程的递归调用,用自身的结构来描述自身,称递归。例如,对阶乘的定义:,Visual Basic允许在一个Sub子过程和Function过程的定义内部调用自己,即递归Sub子过程和递归Functi
22、on函数。,6.6 过程的嵌套和递归调用,Private Function fac(n As Integer) As IntegerIf n = 1 Then fac = 1Elsefac = n * fac(n - 1)End If End Function Private Sub Form_Click() Print “fac(4)=”;fac(4) End Sub,程序的递归过程:,说明: 递归处理分递推和回归两个过程,如上图所示。 使用递归算法必须要满足以下的递归条件:(1)存在递归结束条件及结束时的值;(2)能用递归形式表示,且递归向终止条件发展。,8.7变量与过程的作用范围,根据过
23、程的作用域,过程分为窗体/ 模块级和全局级。,不同作用范围的二种过程定义及调用规则,能 但过程名必须唯一,否则要加标准模块名,能 但必须在过程名前加窗体名,不能,不能,能否被本应用程序其他模块调用,能,能,能,能,能否被本模块其他过程调用,Public 缺省,Private,定义方式,标准模块,窗体,标准模块,窗体,全局级,模块级,作用范围,变量的作用域,根据变量的作用域,变量分为局部(过程级)变量、窗体/ 模块变量和全局变量 局部变量 在过程中用Dim语句定义,只存在于过程中 窗体/ 模块变量 Dim语句或Private语句定义,模块中的所有过程都可使用 全局变量 Public语句定义,可以在所有模块中使用,能,能 变量名前加窗体名,不能,不能,被其他模块存取,能,能,不能,被本模块的其他过程存取,通用声明,通用声明,过程中,声明位置,Public,Dim Private,Dim Static,声明方式,标准模块,窗体,全局变量,窗体/ 模块级变量,局部变量,作用范围,不同作用范围的三种变量声明及使用规则,