1 / 24

第 6 章 过程与函数

第 6 章 过程与函数. 6.1 子过程的定义与调用 6.2 函数的定义与调用 6.3 子过程与函数的参数传递 6.4 变量、过程的作用域 6.5 递归 6.6 常用算法举例. VB 中的过程有两种 : (1) 系统提供的内部函数过程和事件过程。 (2) 用户根据应用的需要而设计的过程。 在 VB 中根据应用的要求可分为几种类型的自定义过程 : (1) 以 “ Sub ” 保留字开始的子过程。 (2) 以 “ Function ” 保留字开始的函数过程。 (3) 以 “ Property ” 保留字开始的属性过程。

topaz
Download Presentation

第 6 章 过程与函数

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 第6章 过程与函数 6.1 子过程的定义与调用 6.2 函数的定义与调用 6.3 子过程与函数的参数传递 6.4 变量、过程的作用域 6.5 递归 6.6 常用算法举例

  2. VB中的过程有两种: • (1) 系统提供的内部函数过程和事件过程。 • (2) 用户根据应用的需要而设计的过程。 • 在VB中根据应用的要求可分为几种类型的自定义过程: • (1) 以“Sub”保留字开始的子过程。 • (2) 以“Function”保留字开始的函数过程。 • (3) 以“Property”保留字开始的属性过程。 • (4) 以“Event”保留字开始的事件过程。 • 本书仅讨论以“Sub”开头的子过程和以“Function”开头的函数过程。

  3. 6.1.1 子过程的定义 在VB中用Sub 语句定义的过程叫做子过程。可按下列格式定义子过程: Sub 子过程名 ( [ 形式参数列表 ]) 语句序列 End Sub 子过程中可以使用Exit Sub语句跳出子过程。形式参数列表由若干个形式参数构成,参数之间用逗号分隔。每个形式参数按下列格式定义:: 形式参数名 [As 类型名] 省略类型说明则表示是Variant类型。例如下列代码定义了一个子过程sub1,有两个长整型形式参数a和b,功能是将a+b的值赋给变量c 。 Sub sub1 (a as long, b as long) c = a+b End Sub

  4. 6.1.2 子过程的调用 子过程只能作为语句被调用,不能作为表达式被调用。可以用下列两种方法调用子过程: Call子过程名( [ 实际参数列表 ] ) 或 子过程名 [ 实际参数列表 ] 以上两种调用方法功能完全一致。注意,当使用 Call 语法时,参数必须在括号内。若省略 Call 关键字,则也必须省略参数两边的括号。 例如下列两条语句都可以调用了前面定义的子过程sub1,调用的结果是变量c的值变成了5。 Call sub1(2,3) 或 sub1 2,3 事件过程的调用:当有事件发生时,系统会自动调用与事件相对应的事件过程。事件过程是与对象相关联的,是对象对事件做出的响应。事件过程的名称由对象名、下划线、事件名连接而成。

  5. 6.2.1 函数的定义 在VB中,用Function语句定义的过程叫做函数。可按下列格式定义函数: Function 函数名( [ 形式参数列表 ] )[ As 类型 ] 语句序列 End Function 函数的定义与子过程类似,不同之处在于函数有返回值。函数的返回值用函数名表示,在函数返回前至少需要对函数名赋值一次。使用语句Exit Function 可以立即跳出函数。 例如下列代码定义了一个函数Fun1,有两个长整型形式参数a和b,函数的返回值为长整型,值等于a+b的结果。 Function fun1(a As Long, b As Long) As Long fun1 = a + b End Function

  6. 6.2.2 函数的调用 函数可以作为表达式来调用。格式为: 函数名[(实际参数列表)] 如果函数要直接作为语句来使用,则必须按照子过程的方式来调用,当然此时也就不能利用函数的返回值了。 例如下列三条语句都可以调用前面定义的函数Fun1: Print fun1(2, 3) Call fun1(2, 3) fun1 2, 3

  7. 6.3 子过程与函数的参数传递 1.参数传递方式 参数有两种传递方式:按值传递和按地址传递。 按值传递参数:在形式参数前加上关键字ByVal表示指定按值传递参数。调用时实际参数仅将值传递给形式参数,形式参数的任何改变不会影响实际参数。 按地址传递参数:在形式参数前加上关键字ByRef表示指定按地址传递参数。调用时如果实际参数是表达式,则传递方式与按值传递效果相同;如果实际参数是变量,则将实际参数的内存地址传递给形式参数,形式参数与实际参数指向同一个内存地址,形式参数的改变也就是实际参数的改变。

  8. 6.3 子过程与函数的参数传递 【例6-4】下列程序运行后,每次单击窗体就会显示“a=3”,“b=8”。 Option Explicit Dim a As Long Dim b As Integer Sub s(c As Long) c = c + 1 End Sub Sub Form_Click() a = 2 b = 8 s a Print "a="; a s (b) Print "b="; b End Sub 说明:本例中,圆括号用于将实际参数由变量b转换为表达式,即按值传递(s(b)),否则就是按址传递(s a)。

  9. 6.3 子过程与函数的参数传递 2.可选参数 在形式参数前加上关键字Optional可以指定该形式参数为可选参数。可选参数在过程调用时可以不提供与可选参数对应的实际参数。可选参数可以指定默认的缺省值。 3.命名参数 实际参数使用“形式参数名:= 实际参数”的格式即为命名参数。命名参数出现的位置可以与定义时的顺序无关。但需注意非命名参数仍需按定义时的位置出现,所以非命名参数在定义时应排在第一个命名参数之前。 4.数组作为参数和返回值 数组可以作为实际参数传递到过程中。此时形式参数应为Variant类型或与实际参数类型完全相同的数组类型。作为形式参数的数组应为可变数组,用数组名跟空的圆括号表示。函数的返回值也可以是数组,此时类型说明为Variant类型或“As 类型()”。

  10. 6.3 子过程与函数的参数传递 【例6-7】下列程序运行后,单击窗体时显示“9”、 “8”、“7”。 Option Explicit Function f(a() As Long) As Long() f = a End Function Sub Form_Click() Dim b() As Long Dim c(2) As Long c(0) = 9 c(1) = 8 c(2) = 7 b = f(c) print b(0) b()=f(c()) print b(1) Print f(c)(2) ’函数表达式直接带数组下标代表数组元素 End Sub

  11. 6.3 子过程与函数的参数传递 5.可变个数参数 将最后一个形式参数声明为Variant类型的数组,同时在前面加上ParamArray关键字,就变成可变个数的参数;调用过程时可输入任意个数的参数,输入的参数转变为数组的元素;也可以省略该参数。ParamArray 关键字不能与 ByVal或ByRef一起使用,也不能在参数列表中出现Optional。 【例6-8】下列程序运行后,每次单击窗体就会显示“6”。 Option Explicit Function f(a, ParamArray b()) f = a + b(0) + b(1) End Function Sub Form_Click() Print f(1, 2, 3) End Sub 注意:在用可变个数参数时,实参个数不能少于使用的形参个数。

  12. 6.4 变量、过程的作用域 • 1.过程的作用域 • 定义过程时在过程名前加关键字Private,则该过程为私有过程,仅在定义该过程的模块内有效,其他模块的过程不能调用该过程。如果没有加关键字Private或加了关键字Public,则该过程为公共过程,在整个工程内有效,其他模块内的过程可以调用该过程。 • 调用当前过程所在模块定义的过程可以直接使用过程名。调用其他窗体模块或其他标准模块定义的过程,使用“模块名.过程名”的格式。

  13. 6.4 变量、过程的作用域 • 2.变量的作用域 • 局部变量:过程的形式参数、过程中定义的变量、未经定义直接使用的变量,仅在过程中有效。 • 全局变量:在所有过程之外定义的变量,在定义变量的模块中有效。 • 公共变量:用Public定义的变量,在整个工程内有效。 • 私有变量:用Private或Dim定义的变量,仅在定义它的模块内有效。。 • 调用当前过程所在模块定义的过程可以直接使用过程名。调用其他窗体模块或其他标准模块定义的过程,使用“模块名.过程名”的格式。

  14. 6.4 变量、过程的作用域 • 3.静态变量 • 过程中可以用Static语句定义静态变量。Static语句的格式为: • Static 变量名[([数组维数])] [As [New] 类型] [, …] • Static语句与Dim语句用法相同,但Static语句不能用于定义全局变量。用Dim定义的变量在每次过程被调用时都会被分配新的存储空间,在过程调用结束时释放存储空间;静态变量只分配一次存储空间,在整个应用程序运行时,其值一直存在。 • 定义过程时在过程名前加关键字Static,则该过程为静态过程。静态过程中定义的所有变量都是静态变量,但形式参数不会成为静态变量。

  15. 6.4 变量、过程的作用域 • 【例6-11】请仔细分析下列程序: • Option Explicit • Dim a • Sub b() • Dim c • Static d • a = a + 1 • Print "模块级变量a="; a • c = c + 1 • Print "局部变量c="; c • d = d + 1 • Print "静态变量d="; d • End Sub Static Sub e(f) Dim g a = a + 1 Print "模块级变量a="; a f = f + 1 Print "形式参数f="; f g = g + 1 Print "局部变量g="; g End Sub

  16. 6.4 变量、过程的作用域 运行结果如图所示。 • Private Sub Form_Click() • Print "第1次调用过程b" • b • Print • Print "第2次调用过程b" • b • Print • Print "第1次调用静态过程e" • e 0 • Print • Print "第2次调用静态过程e" • e 0 • End Sub

  17. 6.5 递归 • 过程如果直接或间接地调用了自身,这就是递归过程。使用递归算法在某些情况下可以大大简化程序设计的复杂度,但递归容易消耗系统资源,递归层次过多会引起堆栈上溢。递归过程应有适当的机会跳出递归,否则会因递归死循环引起堆栈上溢。 • 例【6-12】求n!的递归函数。 • Public Function FN(n As Integer) As Integer • if n=1 Then • FN=1 • Else • FN=n*FN(n-1) • End if • End Function • 从以上函数可见递归是一个不断自己调用自己的过程,直到n=1为止,然后是一个不断返回到不同调用级别的过程。这过程也是一个先一级级压堆栈,后又一级级弹堆栈的过程。

  18. 6.5 递归 • 【例6-13】一只猴子一天从山上摘来一袋桃子,从这天开始,它每天都要把袋中的桃子平分为二堆,吃掉其中的一堆,然后再从剩下的桃中拿出一个解谗,等到第10天,它发现袋中只有一只桃可吃,问猴子总共摘了多少桃。 • 程序如下(运行结果如下图): • Private Sub Command1_Click() • Dim Num As Integer • Num = Val(InputBox("请输入天数:")) • Label1.Caption = "桃子数量为:" & Eat(Num) • End Sub • Private Function Eat(N As Integer) '递归函数 • If N = 1 Then • Eat = 1 • Else • Eat = 2 * Eat(N - 1) + 2 • End If • End Function

  19. 6.6 常用算法举例 • 程序设计不仅仅需要具备程序设计语言的语法知识,更重要的是要掌握基本的算法并能灵活的加以应用。下面给出一些常用算法的应用实例 。 • 1.欧几里德算法求最大公约数和最小公倍数 • 欧几里德算法也叫做辗转相除法,是计算两个数最大公约数的传统算法。步骤如下: • (1)如果a < b,则交换a和b。 • (2)令c是a / b的余数。 • (3)如果c=0,则令gcd=b并终止;否则令a=b,b=c并转向步骤(2)。 • 具体算法应用见下例:

  20. 6.6 常用算法举例 • 【例6-15】求最大公约数的函数为: • Function gcd(ByVal a As Long, ByVal b As Long) As Long • Dim c As Long • If a < b Then • c = a: a = b: b = c • End If • Do • c = a Mod b • If c = 0 Then Exit Do • a = b: b = c • Loop • gcd = b • End Function • gcd函数的调用和系统函数的调用一样,如:Print gcd(12,28)为输出12与28的最小分倍数。

  21. 6.6 常用算法举例 • 2.异或操作实现加密和解密 • 【例6-17】异或操作可以实现简单的数据加密和解密,加密解密使用相同的密码和程序。 Function code(src() As Byte, key() As Byte) As Byte() Dim a() As Byte Dim i As Long Dim j As Long Dim K As Long Dim L As Long K = UBound(src) L = UBound(key) ReDim a(k) j = 0 For i = 0 To K a(i) = src(i) Xor key(j) j = j + 1 If j > L Then j = 0 Next i code = a End Function Private Sub Form_click() Dim a() As Byte Dim b() As Byte Dim c() As Byte a = "用于加密的密码" b = "密码" Print "加密前的明文:"; a a = code(a, b) '将原文与密码进行异或运算,实现对原文的加密 Print "加密后的密文:", a a = code(a, b) '将密文与密码进行异或运算,实现对密文的解密 Print "解密后的明文:", a End Sub

  22. 6.6 常用算法举例 • 3.数制转换 • 【例6-18】将任意进制正整数形式的字符串转换为数值(十进制),实现函数如下: • Function str2n(ByVal a As String, Optional ByVal b As Long) As Long • Dim i As Long • Dim num As Long • Dim c As String * 1 • For i = 1 To Len(a) • c = mid(a, i, 1) • c = UCase(c) • If c >= "0" And c <= "9" Then • num = num * b + Val(c) 'b为b进制的基 • ElseIf c >= "A" And c <= "Z" Then • num = num * b + Asc(c) - Asc("A") + 10 • End If • Next i • str2n = num • End Function

  23. 6.6 常用算法举例 • 4.多项式求值和求导数 • 【例6-19】多项式 a0 xn + a1 xn-1+ … + an-1x+ an的值可以用下面的函数计算: • Function polynomial(a() As Double, ByVal x As Double) As Double • Dim i As Long • Dim fx As Double • fx = a(0) • For i = 1 To UBound(a) • fx = x * fx + a(i) • Next i • polynomial = fx • End Function

  24. 本章小结 • 本章介绍了与过程的定义与调用有关的内容。过程有两种基本的形式:子过程与函数,这两种形式没有本质的区别。子过程是事件响应过程采用的形式,函数则使用起来更为灵活。过程调用时的参数有两种传递方式:值传递和引用传递。值传递仅仅是复制实际参数的副本传递给形式参数,所以形式参数的变化不会影响实际参数的值,引用传递时形式参数与实际参数是同一个变量,形式参数的改变也就是实际参数的改变。过程和变量都有作用域限制,同名过程或变量在调用时有优先级的差异,变量还有生存期的问题。本章最后给出了一些实用的自定义过程,读者可从中学习算法,加深对语法知识的理解。

More Related