260 likes | 435 Views
第六章 过程. Function 过程的定义与调用 Sub 过程的定义与调用 参数传递 可选参数和可变参数 递归. 在 VB 中,系统提供了常用的内部函数过程,如 Sin 函数、 Abs 函数,系统也预定义了一些事件过程,如 Click( )、Load( ) 等。. 除此之外,用户可以自定义过程: 以 Sub 保留字开始的子过程 以 Function 保留字开始的函数过程. 函数过程的定义和调用. 自定义函数过程有两种方法 第一:利用 “ 工具 ” 菜单下的 “ 添加过程 ” 命令定义,生成一个函数的框架 第二:利用代码窗口直接定义.
E N D
第六章 过程 Function过程的定义与调用 Sub过程的定义与调用 参数传递 可选参数和可变参数 递归
在VB中,系统提供了常用的内部函数过程,如Sin函数、Abs函数,系统也预定义了一些事件过程,如Click( )、Load( )等。 除此之外,用户可以自定义过程: 以Sub保留字开始的子过程 以Function保留字开始的函数过程
函数过程的定义和调用 自定义函数过程有两种方法 第一:利用“工具”菜单下的“添加过程”命令定义,生成一个函数的框架 第二:利用代码窗口直接定义
Function过程的定义 Function过程的定义格式: [Static][Public|Private]Function 函数名([<参数列表>])[As<类型>] <语句组1> [函数名=返回值] [Exit Function] <语句组2> [函数名=返回值] End Function
说明: 1.函数过程名:命名规则同变量名。 2.参数列表形式: [ByVal|ByRef]变量名[( )][As 数据类型] 称为形参或哑元,仅表示参数的个数、类型,无值。 3.ByVal表示当该过程被调用时,参数是按值传递的;缺省或ByRef表示当该过程被调用时,参数是按地址传递的。
4.函数名 = 返回值:在函数体内至少对函数名赋值一次,如缺省则返回一个默认值。 5.[Exit Function]:表示退出函数过程。常常是与选择结构(If或Select Case语句)联用,即当满足一定条件时,退出函数过程。 6.[Public|Private]:缺省为Public。 7.As<类型>:是指函数返回值的类型,若省略,则函数返回变体类型值(Variant)。
Function Fact(n As Integer) As Long Dim i As Integer, f As Long f = 1 For i = 1 To n f = f * i Next i Fact = f End Function 例6.1 编写一个计算N!的Function过程。
函数过程的调用 形式:函数过程名([参数列表]) 说明: 1.参数列表称为实参或实元,它必须与形参个数相同,位置与类型一一对应。可以是同类型的常量、变量、表达式。 2.函数调用只能出现在表达式中,其功能是求得函数的返回值。
例6.2 从键盘上输入一个整数,计算其阶乘数。 Private Sub Command1_Click() Dim x As Integer x = Val(Text1) Label2.Caption = Trim(Str(x)) & "的阶乘为:" Text2 = Trim(Str(Fact(x))) End Sub
Sub过程的定义与调用 在实际使用时,有时不需要返回值或者需要多个返回值,这时用函数过程就难以实现了,可以使用Sub过程。 在VB中,Sub子过程分为:事件过程和通用过程。
子过程定义: [Public|Private][Static] Sub 子过程名([形参表]) <语句组> [Exit Sub] <语句组> End Sub 子过程的调用: 子过程名 [实参表] 或 Call 子过程名[(实参表)]
例6.3 编写一个计算N!的Sub过程。 Private Sub Fact(n As Integer,f As Long) Dim i As Integer f = 1 For i = 1 To n f = f * i Next i End Sub 调用形式为: Call fact(x,y) 或 Fact x,y
1.函数过程名有值有类型,在函数体内至少赋值一次;子过程名无值无类型,在子过程体内不能对子过程名赋值;1.函数过程名有值有类型,在函数体内至少赋值一次;子过程名无值无类型,在子过程体内不能对子过程名赋值; 子过程与函数过程区别: 2.调用时,子过程调用是一句独立的语句; 函数过程不能作为单独的语句加以调用,必须参与表达式运算。 3.一般当过程有一个函数值,使用函数过程较直观;反之若过程无返回值,或有多个返回值,使用子过程较直观。
参数传递 指主调过程的实参传递给被调过程的形参。 1. 传址与传值 传址: 形参得到的是实参的地址,当形参值的改变同时也改变实参的值。 传值: 形参得到的是实参的值,形参值的改变不会影响实参的值。 说明: 在定义通用过程时,若形参前面有关键字ByVal,则表示该参数传值方式传送,否则用传址方式传送。
例6.4 两个变量的交换。 Sub Swap1(ByVal x%, ByVal y%) t% = x: x = y: y = t End Sub Sub Swap2(x%, y%) t% = x: x = y: y = t End Sub Private 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="; b End Sub
注意: • 实参和形参中写数组名,忽略维数的定义,但圆括号不能省。 • 被调过程可通过Lbound()和Ubound()函数确定实参数组的下、上界。 • 当用数组作形参时,对应的实参必须也是数组,且类型一致。 • 实参和形参结合是按地址传递,即形参数组和实参数组共用一段内存单元。 2. 数组参数的传递 当参数是数组时是通过传址方式进行传递。
例6.5 编一函数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 = t End Function 调用: Sub Command1_Click() Dim a%(1 To 5),b%(3 To 8) … t1# = tim(a()) t2# = tim(b()) Print t1, t2 End Sub
使用过程注意事项: • 1.确定自定义的过程是子过程还是函数过程 • 函数过程名有值,子过程名无值。 • 2.过程中形参的个数和传递方式的确定 • 过程中参数的作用是实现过程与调用者 • 的数据通信。 • 从主调程序获得初值,值传递。 • 将结果返回给主调程序,地址传递。
3. 实参与形参结合时对应问题 • 个数、类型、位置、次序一一对应。 • 形参是值传递,对应实参可以是表达式、常量、数组元素。 • 形参是地址传递,对应实参只能是简单变量。 • 数组、记录类型、对象只能是地址传递。
可选参数和可变参数 可选参数:在vb6.0中,可以指定一个或者多个参数作为可选参数。 在定义过程时形参表中使用optional为关键字,并在过程中通过Ismissing()函数测试调用时是否传送了可选参数。
例6.6 编写一个既能计算两个相乘,也能计算三个数相乘的sub过程。 Private Sub mul(first As Integer, sec As Integer, Optional third) result = first * sec If Not IsMissing(third) Then result = result * third End If Print result End Sub Private Sub Command1_Click() Call mul(3, 5):Call mul(2, 3, 5) End Sub
Sub 过程名(ParamArray 数组名() ) 例如: Private Sub sum(ParamArray num()) s = 0 For Each x In num s = s + x Next x Print s End Sub 可变参数:在vb6.0中,可以定义成任意个数参数的传递。可变参数过程的定义形式: 调用: Call sum(1,2,3,4,5) Call sum(1,2,3,4,5,6,7,8,9)
过程的递归调用 用自身的结构来描述自身,称递归。 Visual Basic允许在一个Sub子过程和Function过程的定义内部调用自己,即递归Sub子过程和递归Function函数。
例6.7 编求阶乘fac(n)=n! 的递归函数 Private Function fac(n As Integer) As Integer If n = 1 Then fac = 1 Else fac = n * fac(n - 1) End If End Function Private Sub Form_Click() Print “fac(4)=”;fac(4) End Sub
说明: • 递归处理一般用栈来实现,分递推和回归两个过程。 • 递推过程:每调用一次自身,把当前参数(形参、局部变量、返回地址等)压入栈,直到递归结束条件成立。 • 回归过程:然后从栈中弹出当前参数,直到栈空。
递归算法设计简单,解决同一问题,使用递归算法消耗的机时和占据的内存空间要比使用非递归算法大。递归算法设计简单,解决同一问题,使用递归算法消耗的机时和占据的内存空间要比使用非递归算法大。 • 使用递归算法必须要满足以下的递归条件: 一是存在递归结束条件及结束时的值; 二是能用递归形式表示,且递归向终止条件发展。