1、第4章 过程,4.1 子过程的定义和调用 4.2 函数过程的定义和调用 4.3 参数传送 4.4 过程的作用域 4.5 递归,将多次被重复使用的程序段设计成一个具有一定功能的独立程序段,即为通用过程。,【例】1!+2!+3!+n!,4.1 子过程,4.1.1 子过程的定义 4.1.2 子过程的调用,在VB中,的Sub子过程分为:事件过程和通用过程 1. 事件过程 (1)窗体事件的语法 Private Sub Form_事件名(参数列表)语句组 End Sub(2)控件事件的语法 Private Sub 控件名_事件名(参数列表)语句组 End Sub,4.1.1 通用过程的定义,1. 通用过程
2、的语法格式 通用过程的语法格式如下: Public | Private Static Sub 过程名(形参表)局部变量或常数声明语句块Exit Sub语句块 End Sub,Public可选的。表示所有模块的所有其它过程都可访问这个 Sub 过程。 Private可选的。表示只有在包含其声明的模块中的其它过程可以访问该 Sub 过程。 Friend可选的。只能在类模块中使用。表示该 Sub 过程在整个工程中都是可见的,但对对象实例的控制者是不可见的。 Static可选的。表示在调用之间保留 Sub 过程的局部变量的值。,说明: (1)Public | Private:可选。指定过程的作用范围。
3、若省略,则默认为Public(全局)。 (2)Static:可选。指定本过程内的所有局部变量均为静态变量。 (3)过程名:命名规则与变量命名规则相同。无参数时,过程名后的括号不能省略。 (4)形参表:形参表类似于变量声明,指明本过程被调用时传送给本过程的变量个数和类型。若有多个变量,各变量之间用逗号间隔。形参表中出现的参数称为形式参数,简称形参。每个形参的格式为: ByVal | ByRef 形参名() As 类型ByVal表示该参数按值传递,ByRef表示该参数按地址传递(默认)。(5)Exit Sub语句表示立即退出子过程,通常将其置于选择结构中。 (6)在过程内不能再定义过程,但可以调用
4、其他过程。,2. 通用过程的创建 创建通用过程有两种方法:使用“添加过程”对话框;直接在代码编辑器窗口中输入过程代码。 (1)使用“添加过程”对话框创建。 (2)直接在代码编辑器窗口中输入。,图 【添加过程】对话框 图 过程模板,【例1】 编一个交换两个整型变量值的子过程。 Private Sub Swap( X As Integer, Y As Integer)Dim temp As IntegerTemp=X : X=Y : Y=Temp End Sub,Private Sub command1_click()Dim a%,b%a=val(inputbox(“a=“)b=val(input
5、box(“b=“)print “a=“;a,”b=“,bcall swap(a,b)print “a=“;a,”b=“,b End Sub,4.1.2 子过程的调用,子过程的Sub与End Sub之间的语句序列称为过程体,每次调用子过程都会执行过程体中的语句。在程序中,既可以调用通用过程,也可以调用事件过程。 1. 调用通用过程 调用子过程有两种方法:使用Call语句;直接使用过程名。语法格式如下:Call 过程名(实参表) 或者:过程名 实参表,说明: (1)实参表是实际参数(简称实参)列表,若有多个参数,参数之间要用逗号间隔。各实参与形参在参数列表中的位置相互对应,实参与对应位置的形参必须
6、是同一类型,可以是常数、变量、数组元素或表达式。 (2)当用Call语句调用子过程时,若有参数,则参数必须放在圆括号内;若无参数,则省略过程名后的圆括号。 (3)若不使用Call关键字,则过程名后不能加括号。若有参数,则参数直接跟在过程名之后,参数与过程名之间用空格间隔,参数与参数之间用逗号间隔。,【例2】编写一个计算矩形面积的Sub过程,然后调用该过程计算矩形面积。Sub area (x As Single, y As Single)Dim s As Singles = x * yMsgBox “总面积是 “ & s End Sub Private Sub Form_Click()Dim a
7、 As Single, b As Singlea = Val(InputBox(“请输入矩形长度?“)b = Val(InputBox(“请输入矩形宽度?“)Call area(a, b) 或area a,bEnd Sub,2. 调用事件过程在程序中不仅可以调用通用过程,也可以调用事件过程,二者的语法格式相同。例如: 执行窗体加载事件过程中的语句 Form_Load 或:Call Form_Load 调用命令按钮cmdAdd的单击事件过程 command1_Click 或:Call command1_Click调用事件过程实际上就是执行事件过程中的语句序列,如同通用过程一样,亦可起到复用和简化
8、代码的作用。,4.2 函数过程,4.2.1 函数过程的定义 4.2.2 函数过程的调用 Function(函数)过程也是独立的过程,可读取参数、执行一系列语句并改变其参数的值,这一点与前面介绍的Sub过程相同。Function过程与子过程不同的是:子过程没有返回值,只能作为独立的基本语句被调用,不能出现在表达式中;而Function过程有返回值,既可以出现在表达式中,也可以作为独立的语句被调用。,4.2.1 函数过程的定义,函数过程的定义与子过程的定义相似。不同的是,由于函数过程可以返回一个值,因此要在定义中加入返回值类型说明。语法格式为: Private|Public Static Func
9、tion 函数名(形参表) As 类型语句块函数名=表达式Exit Function语句块函数名=表达式 End Function,说明: (1)“函数名”即函数过程的名称,命名规则与变量相同。 (2)As 类型 指定函数过程返回值的类型,可以是Integer、Long、Single、Double、Currency、String或Boolean。若省略,则默认的数据类型为Variant。 (3)“表达式”的值是函数返回的结果,通过赋值语句将其赋给函数名。若在函数过程中省略“函数名=表达式”,则该过程返回一个默认值。数值函数过程返回0,字符串函数返回空字符串。因此,为了能使一个函数过程完成所指定
10、的操作并获取返回值,通常要在过程中为函数名赋值。 (4)在过程体中,可以使用一个或多个Exit Function语句退出函数。 (5)函数过程语法中其他部分的含义与子过程相同。,与子过程一样,可以在“代码编辑器”窗口中直接输入代码来创建函数过程,也可以使用“添加过程”对话框来创建函数过程,只是在选择类型时要选择“函数”。 例如,以下函数RectArea可计算并返回矩形的面积: Private Function RectArea(a As Single, _b As Single) As Single RectArea = a * b End Function,注意:函数不能作为独立语句使用调用
11、,必须与其他成分结合使用实参列表中的参数个数、位置和类型与形参一一对应,如: Public Function area(x!,y!,z!) As Singlec=0.5*(x+y+z) area=sqr(c*(c-x)*(c-y)*(c-z)End Function,【例3】计算多边形的面积,4.2.2 函数过程的调用,函数过程通常在表达式中调用,也可以作为独立的语句被调用。在表达式中调用格式:函数名(实参表)这种调用方式与大部分VB内部函数的调用相同,即将函数名及其实参写在表达式中。例如,以下语句均可调用前面8.2.1小节中计算矩形面积的函数过程: Print “矩形面积为:“; RectA
12、rea(6, 8) MsgBox “矩形面积为:“ & RectArea(3, 4),【例4】编写一个计算矩形面积的Sub过程,然后调用该过程计算矩形面积。Private Function rectArea(a As Single, b As Single) As Single RectArea = a * bEnd FunctionPrivate Sub Form_Click()Dim a As Single, b As Single, s as singlea = Val(InputBox(“请输入矩形长度?“)b = Val(InputBox(“请输入矩形宽度?“) s= rectare
13、a(3, 5)Call Recarea(A, B) recarea a,bEnd Sub,Private Sub Form _ Click() a=5 : b=4 : c=3 : d=3 e=4 : f=5 : g=4s1=area(a,b,c) s2=area(c,d,e)End Sub,Public Function area(x!,y!,z!) As Singlec=0.5*(x+y+z) area=sqr(c*(c-x)*(c-y)*(c-z)End Function,【例5】计算多边形的面积,多边形的的面积,【例6】计算110阶乘之和。运行结果如图所示。 思路:首先编制一个求阶乘(N
14、!)的函数过程,在窗体的单击事件中调用此过程,依次求出1!、2!10!的值,并将其累加。 代码如下: 求阶乘(N!)的函数过程 Private Function jc(N As Integer) As LongDim i As Integer, p As Longp = 1For i = 1 To Np = p * i 累乘Nextjc = p 对函数名赋值,返回函数值 End Function,Private Sub Form_Click() 单击窗体Dim Sum As Long, i As Integer在循环中调用函数过程求110的阶乘并累加For i = 1 To 10Sum = S
15、um + jc(i)NextPrint “ 1!+2!+.+10! =“; Sum 显示结果 End Sub,例7:求1!n!之和,Public Function fac(n%) As Integerfac = 1For i = 1 To nfac = fac * iNext i End Function,Dim sum as integer,k As integer,For k = 1 To 5Sum = Sum + fac(k)Nextprint Sum,Private Sub Command1_Click(),分析: (1)函数过程:完成求任一数n! (2)Command1_Click中
16、:各阶乘值的累加,和 函数调用及输出,4.3 参数传送,4.3.1 传值 4.3.2 传址,4.3.1 传值,按值传送时传送的不是实参的值,仅传送实参变量的副本,执行完调用语句后,调用程序中的实参值不会改变。,按值传递形参的语法特点:在相应的形式变量前加“ByVal”关键词如:Public Sub test(ByVal j As Integer)End Sub,4.3.2 传址,按地址传送时传送的是实参的地址,在调用时,被调用过程直接将接受到的地址里的值进行修改,从而实参值被改变。所以执行完调用语句后,实参的值将会有所改变。,按址传递形参的语法特点:形式变量前没有修饰词;或在形式变量前加“By
17、Ref”关键词如:Public Sub test(i!,ByRef j As Integer)End Sub,Private Sub Command1_Click()dim a as integer,b as integer a= 10: b= 20: Swap1 a, b 传值 call swap1(a,b)Print “a1=“; a, “b1=“; ba = 100: b = 200: Swap2 a, b 传址Print “a2=“; a, “b2=“; bEnd Sub,【例8】 用传值和传址两种方式进行两个数的交换。 Swap1为传值,swap2为传址。,Sub Swap1(ByV
18、al x%, ByVal y%)t% = x: x = y: y = tEnd SubSub Swap2(x%, y%)t% = x: x = y: y = tEnd Sub,传值和传址在形式上表现的主要区别为:,按值传送:形参变量前应加有ByVal; 说明:如果形参是变量,实参是常数或表达式时,即使在形参前没有关键词ByVal,也是实现按值传递 按址传送:形参前没有加上任何修饰词,或加“ByRef”,8.4 过程的作用域应用,1. VB程序的模块结构,(1)窗体/模块级:在某个窗体或模块内定义并加Private关键字的过程,只能被在本窗体或模块中定义的过程调用。 (2)全局级:在某窗体或模块内定义并加Public关键字(可缺省)的过程,可被整个应用程序的所有窗体或模块中定义的过程调用或引用。,2. 过程的作用域,Private Function rectarea(a As Single, b As Single) As Singlerectarea = a * bEnd Function,把这段函数分别放在: 一个窗体中 第一个窗体中,第二个窗体调用 放在模块中,