第 8 章 过程

90
江江江江江江江江江江 Visual Basic 程程程程 江 8 江 江江

description

第 8 章 过程. 教学要求. 掌握 VB 的两种过程:事件过程和通用过程 掌握 Sub 过程的定义 掌握 Function 过程的定义 掌握过程的调用 掌握参数的传递 —— 按值传递和按地址传递 掌握递归算法 掌握变量的作用域. 教学内容. 8.1 Sub 过程 8.2 Function 过程 8.3 过程调用 8.4 参数传递 8.5 递归过程 8.6 变量的作用域 8.7 程序示例. 模块化程序设计. 基本思想:将一个大的程序按功能分割成一些小模块 特点: 各模块相对独立、功能单一、结构清晰、接口简单 - PowerPoint PPT Presentation

Transcript of 第 8 章 过程

Page 1: 第  8  章  过程

江苏省计算机等级考试

Visual Basic 程序设计

第 8 章 过程第 8 章 过程

Page 2: 第  8  章  过程

2 江苏计算机等级考试

Visual Basic 程序设计教学要求教学要求

掌握 VB 的两种过程:事件过程和通用过程 掌握 Sub 过程的定义 掌握 Function 过程的定义 掌握过程的调用 掌握参数的传递——按值传递和按地址传递 掌握递归算法 掌握变量的作用域

Page 3: 第  8  章  过程

江苏计算机等级考试

Visual Basic 程序设计

3

8.1 Sub过程

8.2 Function过程

8.3 过程调用8.4 参数传递

8.5 递归过程8.6 变量的作用域

8.7 程序示例

教学内容

Page 4: 第  8  章  过程

4 江苏计算机等级考试

Visual Basic 程序设计

基本思想:将一个大的程序按功能分割成一些小模块 特点:

各模块相对独立、功能单一、结构清晰、接口简单控制了程序设计的复杂性提高元件的可靠性缩短开发周期避免程序开发的重复劳动易于维护和功能扩充

开发方法 : 自上向下 , 逐步分解,分而治之

模块化程序设计

Page 5: 第  8  章  过程

5 江苏计算机等级考试

Visual Basic 程序设计

VB 中过程的分类

过程

事件过程 通用过程

子程序过程Sub

函数过程Function

Page 6: 第  8  章  过程

6 江苏计算机等级考试

Visual Basic 程序设计8.1 Sub 过程

8.1.1 事件过程8.1 Sub 过程 8.1.1 事件过程

当对象识别某事件后,进行的操作处理——以代码的形式存储在事件过程中。

分类:窗体事件过程 控件事件过程

Page 7: 第  8  章  过程

7 江苏计算机等级考试

Visual Basic 程序设计1 定义事件过程1 定义事件过程

[ 形式 ]:

Private Sub Form_ 事件名( [参数列表 ])

[ 局部变量和常数声明 ]

语句块

End Sub

完全由系统决定,用户无权修改

窗体的事件过程名中不使用其具体名称,而固定用 Form

窗体事件固定有“ Private”关键字,说明它是模块级

Page 8: 第  8  章  过程

8 江苏计算机等级考试

Visual Basic 程序设计2 窗体的 Initialize 、 Load 、 Activate 、 Gotfocus 事件2 窗体的 Initialize 、 Load 、 Activate 、 Gotfocus 事件

Initialize (初始化)事件——配置窗体时触发

Load (加载)事件——窗体装入内存时触发

Activate (激活)事件——窗体被激活时触发

Gotfocus 事件(得到焦点)事件——窗体成为当前焦点时触发

窗体上无可视控件时,触发窗体的 Gotfocus 事件;

窗体上有可视控件时,触发控件的 Gotfocus 事件;

执行次序:

Initialize Load Activate Gotfocus

Page 9: 第  8  章  过程

9 江苏计算机等级考试

Visual Basic 程序设计注 意注 意

窗体的 Initialize 、 Load 事件发生在窗体被显示之前,其中可放置系统初始化命令,但其中语句有所限制;

窗体加载后,只要不被卸载,就不会再执行 Initialize 、 Load事件,但 Activate 事件会多次发生;

当访问另一窗体上的“非可视”数据或调用其中定义的全局过程时,只会触发该窗体的 Initialize 事件,而 Load 事件不触发;

当访问另一窗体上的“可视”数据时,会同时触发该窗体的 Initialize 和 Load 事件;

Page 10: 第  8  章  过程

10 江苏计算机等级考试

Visual Basic 程序设计3 定义控件的事件过程3 定义控件的事件过程

[ 一般形式 ]:

Private Sub 控件名 _事件名( [参数列表 ])

[ 局部变量和常数声明 ]

语句块

End Sub

由系统决定,用户无权修改

控件的事件过程名中必须使用其具体名称

控件事件固定有“ Private”关键字,说明它是模块级

Page 11: 第  8  章  过程

11 江苏计算机等级考试

Visual Basic 程序设计4 建立事件过程4 建立事件过程

打开“代码编辑器”窗口;先选定某对象,再选定事件过程;编辑代码;

对象 过程

Page 12: 第  8  章  过程

cnm=m!(n-m)!

n!

Private Sub Command1_Click() n = Val(Text1.Text) m = Val(Text2.Text) k = n t = 1 For i = 1 To k t = t * i Next i s = t k = m t = 1 For i = 1 To k t = t * i Next i s = s / t k = n - m t = 1 For i = 1 To k t = t * i Next i s = s / t Text3.Text = Str(s)End Sub

共同代码计算 k !

能不能简化?

计算:

Page 13: 第  8  章  过程

13 江苏计算机等级考试

Visual Basic 程序设计

函数定义计算 k !

Private Sub Command1_Click() Dim m As Integer, n As Integer Dim i As Integer, k As Integer Dim t As Long, s As Long n = Val(Text1.Text) m = Val(Text2.Text) s = fact(n) / (fact(m) * fact(n - m)) Text3.Text = Str(s)End SubPrivate Function fact(k As Integer) As Long Dim i As Integer fact = 1 For i = 1 To k fact = fact * i Next iEnd Function

函数调用(三次)

使用函数

Page 14: 第  8  章  过程

14 江苏计算机等级考试

Visual Basic 程序设计

在以下两种情况下,经常使用自定义过程:

( 1 )应用程序中出现较频繁的处理,仅仅是每次处理的数据不同而已;

( 2 )程序中比较复杂的算法,独立出来,增强程序的可读性;

“过程”的引入使得整个程序的结构更加清晰,模块化更强。

过程的引入:

Page 15: 第  8  章  过程

15 江苏计算机等级考试

Visual Basic 程序设计8.1.2 通用过程8.1.2 通用过程

完成某一特定功能的程序段

——通用过程(自定义) 必须显式调用方可执行 ; 分为:

公有过程( Public )私有过程( Private )

Page 16: 第  8  章  过程

16 江苏计算机等级考试

Visual Basic 程序设计1 通用 Sub 过程的定义1 通用 Sub 过程的定义

[ 一般形式 ]:

[Private|Public] [static] Sub < 过程名 >([< 参数列表 >])

< 过程体 >

End Sub [ 说明 ]:(1) 以 Sub 开头, End Sub 结束 ,,中间是过程体——包括变

量声明和语句块;(2) 以 Private 为前缀的过程是模块级的,以 Public 为前缀的

过程是应用程序级的,缺省默认是 Public ;(3) Static 选项说明过程中的局部变量是静态变量;(4) 过程名的命名规则和变量名相同,在同一个模块中,过程

名必须是唯一的;

Page 17: 第  8  章  过程

17 江苏计算机等级考试

Visual Basic 程序设计

( 5 ) 参数列表中的参数称为形式参数,可以没有,但无参数时圆括号不能省略;有多个参数时,参数之间用逗号间隔;( 6 )参数说明格式: [Optional][ByVal|ByRef] < 变量名 >[ () ][As < 数据类型 >]

其中: a) 若参数是数组,则在变量名后面加一对圆括号,但无维界定义

b) ByVal :指明参数传递方式是传值;c) ByRef :指明参数传递方式是传地址,为缺省值;d) 若参数是字符型的,必须是不定长字符串 ;

e)Optional :参数是可选的,必须定义在必选参数后面。( 7 ) 当过程调用结束,即执行到 End Sub 语句,系统自动返回调用程序的调用语句处,执行调用语句的下一条语句; ( 8 ) 过程不能嵌套定义,但可嵌套调用; ( 9 ) Exit Sub 语句的功能是提前退出过程调用,返回调用语句。

说 明

Page 18: 第  8  章  过程

18 江苏计算机等级考试

Visual Basic 程序设计

例 : Private Sub Exchange(x As Integer,y As Integer)

Dim Temp As Integer

Temp=x : x=y : y=Temp

End Sub

该通用过程实现交换功能,包含两个参数,均是 ByRef 形式的参数。

Page 19: 第  8  章  过程

19 江苏计算机等级考试

Visual Basic 程序设计2 建立通用 Sub 过程

方法一:在“代码编辑窗口”的“通用”中自行输入;

方法二:进入代码编辑器窗口,执行“工具”菜单的“添加过程”,在“添加过程”对话框中输入定义过程的名称、类型和范围后单击“确定”按钮,系统会自动在代码窗口添加自定义过程的框架。

Page 20: 第  8  章  过程

20 江苏计算机等级考试

Visual Basic 程序设计3 Sub 过程调用

必须在事件过程或其它通用过程中显示调用。

Private Sub sub1()

…… Call Sub2( 实参表) ……End Sub

Private Sub sub2( 形参表)

……过程语句……

End Sub

① ② ③

④⑤

主调程序 被调过程

注意 :一个过程或函数可以被调用多次;

Page 21: 第  8  章  过程

21 江苏计算机等级考试

Visual Basic 程序设计Sub 过程调用

[ 格式一 ]: Call < 过程名 >[( <实在参数表 >) ]

[ 格式二 ] : < 过程名 > [<实在参数表 >]

[ 功能 ]:对已定义的过程进行调用。

如:

P164

1. Call

Fact(x)

2. Fact x

Page 22: 第  8  章  过程

22 江苏计算机等级考试

Visual Basic 程序设计

( 1)调用的过程必须是已经定义的,否则系统会出现“子程序或函数未定义”的信息提示;

( 2)实在参数可以是常量、变量或表达式;

( 3)实在参数的数目及类型要和定义时必选参数保持一致,否则系统会出现“参数不可选”的信息提示,参数之间用逗号间隔;

( 4)若子程序没有参数,则格式一中的括号可以省略;

( 5)格式一和格式二的区别在于:格式二的参数表无须括号,而是和过程名之间用空格隔开;

说 明

Page 23: 第  8  章  过程

23 江苏计算机等级考试

Visual Basic 程序设计

例 8-2 试编写一个找出任意一个正整数的因子的程序

P165

Page 24: 第  8  章  过程

24 江苏计算机等级考试

Visual Basic 程序设计

定义子程序 factor 求因子,该子程序定义了两个参数,来传递求因子实现前的原始数据和返回功能实现后的结果数据;

Option ExplicitPrivate Sub Command1_Click()

Dim inta As Integer, st As String inta = Text1 Call factor(inta, st) Text2 = st

End Sub调用过程 factor

Private Sub factor(ByVal n As Integer, s As String) Dim i As Integer For i = 1 To n - 1 If n Mod i = 0 Then s = s & Str(i) Next i

End Sub

定义过程

程序说明:

优点:程序即 Sub 过程的使用不仅可以缩短程序的长度,还能够使程序的结构更加清楚。

Page 25: 第  8  章  过程

25 江苏计算机等级考试

Visual Basic 程序设计

Private Sub value(a() As Integer, min As Integer)

Dim i As Integer

min = a(1)

For i = 2 To UBound(a)

If a(i) < min Then min = a(i)

Next i

End Sub

例 :定义一个通用过程用以求一维数组中的最小值

Page 26: 第  8  章  过程

26 江苏计算机等级考试

Visual Basic 程序设计8 . 2 Function 过程

Function 过程的特点是返回一个值,因此我们通常也称之为自定义函数。通常我们利用 Function 过程得到一个数值或一个字符串或一个逻辑值。

[ 格式 ] : [Private|Public] Function < 函数名 >([ 参数列表 ]) [As < 数据类型 >]

< 函数体 >

End Function函数名 = 表达式

函数返回值的类型

Page 27: 第  8  章  过程

27 江苏计算机等级考试

Visual Basic 程序设计

( 1 ) 以 Function 开头,以 End Function 结束,中间是函数体;

( 2 )函数名命名规则、参数列表的表示都和 Sub 过程相同;

( 3 ) As 数据类型:函数过程将由函数名返回一个值,值的类型由 [As 数据类型 ] 定义; ★

( 4 ) 函数体中一定要有对函数名赋值的语句——函数名 = 表达式,否则返回相应类型的初值; ★

( 5 )函数体内可有 Exit Function 语句——无条件退出函数过程,返回主程序。

( 6 ) Function 过程不能嵌套定义,但可嵌套调用。

说 明

Page 28: 第  8  章  过程

28 江苏计算机等级考试

Visual Basic 程序设计

Private Function f(ByVal x As Integer) As Integer

f = 3*x^3-2*x^2+6*x-1

End Function

1623)( 23 xxxxf例:定义函数:函数返回值的类型

函数名 = 表达式

Page 29: 第  8  章  过程

29 江苏计算机等级考试

Visual Basic 程序设计

例 8-1 :编写一个求 n! 的函数。Private Function Fact(Byval n As Integer) As Long

Dim K As Integer

Fact=1

If n=0 Or n=1 Then

Exit Function

Else

For K=1 To N

Fact=Fact*K

Next K

End If

End Function

函数名 = 表达式

函数类型

传值的参数

Page 30: 第  8  章  过程

30 江苏计算机等级考试

Visual Basic 程序设计2 调用 Function 过程

[ 格式 ] : < 函数名 > ( [实在参数表 ] )[ 功能 ] :返回一个函数值。[ 说明 ] :

( 1 )一般情况下,函数的调用出现在赋值语句中,并且在赋值号的右侧;

( 2 )若函数没有参数,函数名后的括号不能省略;

( 3 )虽然 VB允许象调用 Sub 过程那样调用 Function 过程,但这样调用时系统不返回函数值,建议大家不要使用这种调用方法。

Call fact(x)

Fact x 这两种方法均放弃函数的返回值例如:

Page 31: 第  8  章  过程

31 江苏计算机等级考试

Visual Basic 程序设计

Private Function min( a( ) As Integer ) As Integer

Dim i As Integer

min = a(1)

For i = 2 To UBound(a)

If a(i) < min Then min = a(i)

Next i

End Sub

例 :用函数实现求一维数组中的最小值 ,对比前例( Sub )

函数名 = 表达式

函数类型

Page 32: 第  8  章  过程

32 江苏计算机等级考试

Visual Basic 程序设计

Private Function Prime(N As Integer) As Boolean

Dim i As Integer

Prime = False

For i = 2 To N-1

If N Mod i = 0 Then Exit For

Next i

If i =N then Prime = True

End Function

例 :定义函数用以判断一个数是否是素数

函数名 = 表达式

可省略 , 因 Prime 的初始值就是 false

Page 33: 第  8  章  过程

33 江苏计算机等级考试

Visual Basic 程序设计

[例 ] : S=1!+2!+…+10!Private Sub Form_Click() Dim S As Long, i As Integer For i = 1 To 10 Next i Print ”S="; SEnd Sub

Private Function Fact(n As Integer) As Long Dim i As Integer Fact = 1 For i = 1 To n Fact = Fact * i Next iEnd Function

函数名 = 表达式

函数调用 : S = S + Fact(i)

对比 p171

Page 34: 第  8  章  过程

34 江苏计算机等级考试

Visual Basic 程序设计

例 8-3 :利用函数过程编写一个求两个正整数的最大公约数的程序

Private Function Gcd(ByVal A As Integer, ByVal B As Integer) As Integer

Dim R As Integer

R = A Mod B

Do While R <> 0

A = B

B = R

R = A Mod B

Loop

Gcd = B

End Function

使用赋值语句调用函数

P166

Private Sub Form_Click( ) ‘ 主调过程 Dim N As Integer, M As Integer, G As Integer

N = InputBox(" 输入 N")

M = InputBox(" 输入 M")

G = Gcd(N, M)

Print N; " 和 "; M; " 的最大公约数是: "; G

End Sub

Page 35: 第  8  章  过程

35 江苏计算机等级考试

Visual Basic 程序设计8.3.4 调用其他模块中的过程

1 、调用其他窗体模块中的公有过程[ 格式 ] : Call < 窗体名 >.< 过程名 >[ ( <实在参数表> ) ]

[ 功能 ] :调用其他窗体模块中定义的公有过程。

Private Sub Form_Click()

Dim a As Integer

a = 10

Print Form1.Fact(a)

End Sub

在 Form2中调用

Page 36: 第  8  章  过程

36 江苏计算机等级考试

Visual Basic 程序设计2 、调用标准模块中的公有过程

[ 格式 ] : Call [<标准模块名 >.]< 过程名 >[ ( <实参表 > ) ]

[ 功能 ] :调用其他标准模块中定义的公有过程。[ 说明 ] :

若公有过程唯一,则直接调用,不加模块名。若存在同名的公有过程,则:

调用本模块中过程:直接调用,不加模块名调用其它模块中过程:必须加模块名。

被调用的函数和过程必须是公有的;函数也可以这样调用。

Page 37: 第  8  章  过程

37 江苏计算机等级考试

Visual Basic 程序设计3 调用类模块中的过程

[ 格式 ]:

dim democlass as new class1

call democlass.clssub ( [实参表 ] )][注意 ] :

调用类模块中的共有过程,须用该类的某一实例修饰过程。

不做要求

Page 38: 第  8  章  过程

38 江苏计算机等级考试

Visual Basic 程序设计8.4 参数的传递8.4 参数的传递

8.4.1 形式参数和实在参数 形式参数:

过程定义时,在过程名后面的圆括号里的一系列变量; 过程被调用执行时,系统才给形参分配存储空间; 可以是除定长字符串外的任一简单变量; 可以是数组,变量名后接括号; 简称“形参” St As String *3 ×

St( ) As String *3 √St As String √

Page 39: 第  8  章  过程

39 江苏计算机等级考试

Visual Basic 程序设计 实在参数

主调程序中,调用语句中,出现在过程名后面圆括号里的变量,是实在参数,可以是常量、变量或表达式; 过程调用传递参数时,实参按“位置”和形参结合 ;

实在参数和形式参数,要求个数一样,位置对应,类型一致,否则会出错; 定长字符串变量可以作为实在参数; 简称“实参”

Page 40: 第  8  章  过程

40 江苏计算机等级考试

Visual Basic 程序设计

形参 实参

变量 变量、常量、表达式、数组元素

数组 数组

参数结合:

Page 41: 第  8  章  过程

41 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click()

Dim x as single , st as sting*5

Dim a(5) as integer

Call test (x^2 ,true, a, st )

End sub

Private sub test(a as single,loc as booleaan,array1() as integer,chr1 as string)

End sub

举例:

表达式常量 数组

定长字符串

Page 42: 第  8  章  过程

42 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form-click()

Dim x as integer, y as integer

x=10:y=100

Call ExamSub( y ,x )

Print “x=” ; x ; “y=” ; y

End Sub

Private Sub ExamSub( x as integer,y as integer)

x=x+10 : y=y-10

End Sub过程的先后顺序无

所谓

调用子过程时,进行的实际操作是 y=y+10,x=x-10

举例:写出下列程序执行的结果

Page 43: 第  8  章  过程

43 江苏计算机等级考试

Visual Basic 程序设计8.4.2 按值传递参数

[ 格式 ] : ByVal < 变量说明 >

[ 传递方式 ] :

调用时,系统为形参分配一个临时存储单元,并将实参的值存储到该临时单元中。

若在被调用的过程体中改变了形参的值,只是改变了临时存储单元中的数据,对实参的值无任何影响。

Page 44: 第  8  章  过程

44 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click() Dim M As Integer, N As Integer M = 15: N = 20 Call Value_change(M, N) Print "M="; M, "N="; NEnd Sub

Private Sub Value_change(ByVal x As Integer, ByVal y As Integer)

x = x + 20

y = y + 20

Print "X="; x, "Y="; y

End Sub

[ 参数传值传递 ] 举例:

Page 45: 第  8  章  过程

45 江苏计算机等级考试

Visual Basic 程序设计传值是单向的:

实在参数

形式参数

调用时,实参将值传递给形参,两者就无任何关联。过程中形参的值发生变化,对实参无任何影响。

Page 46: 第  8  章  过程

46 江苏计算机等级考试

Visual Basic 程序设计8.4.3 按地址传递参数

[ 格式 ] : ByRef < 变量说明 >

[ 传递方式 ] :

系统在调用执行过程时,为形参分配临时存储单元,并将实参的内存单元地址传送给形参 , 存储在临时存储单元中

在被调用的过程体中一切对形参的操作,都是直接对地址保存在形参中的内存单元中的数据进行的,而实参就是保存在此内存单元中的数据,所以任何对形参的操作也就是对实参的操作;

按地址传递时,形式参数和实在参数共用同一“内存单元”。

Page 47: 第  8  章  过程

47 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click() Dim M As Integer, N As Integer M = 15: N = 20 Call Value(M, N) Print "M="; M, "N="; NEnd Sub

Private Sub Value(x As Integer, y As Integer) x = x + 20 y = y + 20 Print "X="; x, "Y="; yEnd Sub

[参数传址传递 ]举例 :( 对比前例 )

Page 48: 第  8  章  过程

48 江苏计算机等级考试

Visual Basic 程序设计传地址是双向的:

实在参数

形式参数

Page 49: 第  8  章  过程

49 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click() Dim Sum As Integer, I As Integer For I = 5 To 1 Step -1 Sum = Sum + Fact(I) Next I Print "Sum="; SumEnd Sub

Private Function Fact(n As Integer) As Integer Fact = 1 Do While n > 0 Fact = Fact * n n = n - 1 LoopEnd Function

举例:计算 5 ! +4 ! +3 ! +2 ! +1 !

修改:方法一:在形参 n 前加 ByVal

方法二:将调用语句中 fact(i)改为 fact( ( i ) )

P171

Page 50: 第  8  章  过程

50 江苏计算机等级考试

Visual Basic 程序设计

参数有两种传递方式:传值( ByVal )和传地址( ByRef )。 若调用时实参为常量或表达式,这两种方式没有区别 ,无论形参定义的是按值传递还是按地址传递,系统都是按传值方式传递 系统在调用时为形参分配一个临时存储单元,将表达式的值计算出来,存储到该临时单元;调用结束,系统收回临时单元。 调用函数或过程时,将单个变量转换成表达式的方法:将变量放在一对括号中。如用 Fact((I)) 的方式调用函数,系统会按传值来处理。

注 意

Page 51: 第  8  章  过程

51 江苏计算机等级考试

Visual Basic 程序设计

按地址传递时,当实参是变量时,实参与形参必须类型完全一致; 按地址传递时,当实参是常量或表达式时, VB会自动进行类型转换,然后再传递相应的值(即类型无须完全一致); 在算术表达式中,函数的优先级最高,若表达式中有函数的实参,而函数的参数又是按地址传递的,则函数中有可能改变了实参的值,即改变了表达式中变量的值,会引起混淆。

注 意

见例

见例

Page 52: 第  8  章  过程

52 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click()

Dim S As Single

S=125.5

Call Convert((S),”12”+”.5”)

End Sub

Private Sub Convert(Inx As Integer,Sing As Single)

Inx=Inx*2

Sing=Sing+23

Print “Inx=”;Inx,”Sing=”;Sing

End Sub

实际的参数传递方式是按值传递,强制转换后,inx =126 sing=12.5

举例:

Page 53: 第  8  章  过程

53 江苏计算机等级考试

Visual Basic 程序设计

Private function fun_add(a as integer,b as integer,c as integer) as integer

a=a+10 : b=b+10 : c=c+10

fun_add=a+b+c

End function

Private sub command1_click()

Dim v1 as integer,v2 as integer,v3 as integer

V1=2 : v2=3 : v3=4

Debug.print v1+v2+v3*fun_add(v1,v2,v3)

End sub

问题出在哪?

举例:

Page 54: 第  8  章  过程

54 江苏计算机等级考试

Visual Basic 程序设计

( 1 )写出程序运行结果( 2 )若改为按值传递,结果又如何?Dim p As integer, q As integer, r As integer

Private Sub Form_Click()

p = 2: q = 3

Print p, q, r

Call pq(p, q, r)

Print p, q, r

End Sub

Private Sub pq(x As integer, y As integer, z As integer)

x = p + q

y = p - q

z = x + y

End Sub

练 习

Page 55: 第  8  章  过程

55 江苏计算机等级考试

Visual Basic 程序设计

Option Explicit

Private Sub command1_click()

Dim i As Integer, j As Integer

Dim k As Integer

i = 1: j = 2

k = fun(i, fun(i, j)) + i + j

Print "I="; i; "J="; j; "K="; k

End Sub

Private Function fun(a As Integer, ByVal b As Integer) As Integer

a = a + b

b = b + a

fun = a + b

End Function

练 习写程序运行的结果:

Page 56: 第  8  章  过程

56 江苏计算机等级考试

Visual Basic 程序设计8.4.4 数组参数

VB允许把数组作为形式参数,声明数组的格式是: < 数组名 > () As < 数据类型 >

[注意 ] :( 1 )数组参数只能按地址传递,即不能用 ByVal 来修饰数组参数( 2 )定义数组参数时无须说明数组的维数和下标变化范围;( 3 )调用过程时,对应的实在参数也必须是数组,但只需要数组名,无须后跟括号,且数据类型也要一致。 `

( 4 )在过程体或函数体中无须对数组参数再次说明;( 5 )若实参是动态数组,在过程体或函数体中可以使用重定义语句修改数组的维界;

Page 57: 第  8  章  过程

57 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click() Dim a() As Integer, i As Integer Dim n As Integer n = InputBox("请输入数组的初始大小 ") ReDim a(n) For i = 1 To n a(i) = i Next i Call PrintArray(a) Call Array1(a) Call PrintArray(a)End Sub

Private Sub Array1(a() As Integer)

Dim m As Integer, n As Integer n = UBound(a) m = InputBox("请输入新大小 ") ReDim Preserve a(m) Dim i As Integer For i = n + 1 To m a(i) = 0 Next iEnd Sub

输入 5 和 8 ,程序执行结果为:

Private Sub PrintArray(x() As Integer)

Dim i As Integer For i = LBound(x) To UBound(x) Print x(i); Next i PrintEnd Sub

举例

Page 58: 第  8  章  过程

58 江苏计算机等级考试

Visual Basic 程序设计

举例:自定义一个将一维数组按从小到大排序的通用过程。

Private Sub sort(a() As Integer) Dim i As Integer, j As Integer For i = 1 To UBound(a) - 1 For j = i + 1 To UBound(a) If a(i) > a(j) Then temp = a(i) a(i) = a(j) a(j) = temp End If Next j Next iEnd Sub

Private Sub Command1_Click() Dim i As Integer, j As Integer Dim a(10) As Integer For i = 1 To 10 a(i) = Int(8 * Rnd) Picture1.Print a(i); Next i Call sort(a) For i = 1 To 10 Picture2.Print a(i); Next iEnd Sub

Page 59: 第  8  章  过程

59 江苏计算机等级考试

Visual Basic 程序设计

完善程序:本程序的功能是找出 100~200 之间的所有素数。Private Sub Form_Click() Dim i As Integer, x As Integer For i = 100 To 200 If Then Print i Next iEnd SubPrivate Function prime( ) As Boolean Dim i As Integer For i = 2 To Sqr(n) If n Mod i = 0 Then Next i prime = TrueEnd Function

练 习

Prime(i)

ByVal n As Integer

Exit Function

若不希望实参随形参改变,就将参数传递

方式定义为传值

Page 60: 第  8  章  过程

60 江苏计算机等级考试

Visual Basic 程序设计8.4.5 对象参数

在 VB 中,支持过程的形参是对象:

当传递窗体时,定义形参类型是 Form ;

当传递控件时,定义形参类型是 Control.

不做要求

Page 61: 第  8  章  过程

61 江苏计算机等级考试

Visual Basic 程序设计8.5 递归过程

所谓递归,就是在过程定义中,调用过程本身。

Private Sub Form_Click() Dim n As Integer n = InputBox(" 输入一个正整数 ") Print n; "!="; fact(n)End Sub

Private Function fact(ByVal n As Integer) As Long If n = 1 Then fact = 1 Else fact = n * fact(n - 1) End IfEnd Function

例:使用递归函数求 N! 。 [提示 ] : N!=N*(N-1)!

函数调用,调用自身

表示为: fact(n)=n*fact(n-1)

错误的调用: fact(n)=n*fact(n-1)

Page 62: 第  8  章  过程

62 江苏计算机等级考试

Visual Basic 程序设计执行过程分析(以输入 3 为例):

1

Fact(3)3*Fact(2) Fact(2)

2*Fact(1) Fact(1)

Fact(3)6

Fact(2)

2

逐层调用

逐层返回

总结: 使用递归算法,最重要的是要有一个结束递归的条件,可以使递归得以返回,即终止条件或边界条件。

Page 63: 第  8  章  过程

63 江苏计算机等级考试

Visual Basic 程序设计例:使用递归算法计算裴波拉挈数列。

3)2()1(

2,11)(

nnFabnFab

nnFab

Private Function Cal(n As Integer) If n = 1 Or n = 2 Then Cal = 1 Else Cal = Cal(n - 1) + Cal(n - 2) End IfEnd Function

Private Sub Form_Click() Dim n As Integer n = InputBox(" 求数列的第几项 ") Print “ 数列中第” ; n; “项是” ; Cal(n)End Sub

Page 64: 第  8  章  过程

64 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Form_Click() Dim fb() As Integer Dim i As Integer,, n as integer n = InputBox(“ 求数列中第几项的值” ) Redim fb(n) fb(1)=1:fb(2)=1 For i = 3 To n fb(i)=fb(I-1)+fb(I-2) Next i Print " 数列中的第 "; n; "项是 "; fb(n)End Sub

上例的非递归解法——例 5-7 ( P109 )。递推法:利用未知项与已知项之间存在的某种关系,从已知项逐项推出未知项的方法。

Page 65: 第  8  章  过程

65 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Command1_Click() Dim Gcdvalue As Long, M As Long, N As Long If M < > 0 And N < > 0 Then Gcdvalue = Gcd(M, N) Text3.Text = CStr(Gcdvalue) End If End Sub Private Function Gcd(ByVal a As Long, ByVal b As Long)

Dim r As Long r = a Mod b Do While r<>0 a=b b=r r=a Mod b Loop Gcd = bEnd Function

[例 8-9] :编写一个递归函数,求任意两个整数的最大公约数。

Private Function Gcd(ByVal X As Long, ByVal Y As Long) Dim R As Long R = X Mod Y If R = 0 Then Gcd = Y Else X = Y : Y = R : Gcd = Gcd(X, Y) End IfEnd Function

P190

Page 66: 第  8  章  过程

66 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Command1_Click() Dim a As Integer a = 2 Call sub1(a)End SubPrivate Sub sub1(x As Integer) x = x * 2 + 1 If x < 10 Then Call sub1(x) End If x = x * 2 + 1 Print “x=”;xEnd Sub

写出下列程序运行的结果 :

练 习请注意:1、逐层调用, 逐层返回。

2、返回调用程序的调用语句,接着执行下面的语句。

Page 67: 第  8  章  过程

67 江苏计算机等级考试

Visual Basic 程序设计8.6 变量的作用域

关键字 使用位置 作用域

Public 在标准模块的声明段中 全局

Private 和Dim

在模块的声明段中 模块

Dim 在过程中 局部 | 过程

Static 在过程中 局部、静态

Page 68: 第  8  章  过程

68 江苏计算机等级考试

Visual Basic 程序设计8.6.1 过程级变量

在一个过程内部声明的变量,只在过程内部有效,又称为局部变量;

例:Private Sub Command1_Click()

Dim i As Integer i = i + 1 Print i

End SubPrivate Sub Command2_Click()

i = i - 1 Print i

End Sub

问:

( 1)单击两次按钮 1 ,结果是什么?

( 2)先单击按钮 1 ,再单击按钮 2 ,结果又是什么?( 1 ) 1 1

( 2 ) 1 -1

过程级变量,过程开始执行时,系统分配给其存储单元,而一旦过程运行结束,系统就收回存储空间。在其它过程中,不可访问。

Page 69: 第  8  章  过程

69 江苏计算机等级考试

Visual Basic 程序设计8.6.2 模块级变量

在模块的“通用”声明段中用 Private 和 Dim 声明的变量,模块中任何一个过程都可以访问;

模块级变量,在模块加载时,即分配给其内存存储单元,模块中任意过程均可对该变量进行操作,直到模块卸载时,系统才收回存储空间。但在其它模块中,不可访问。

Dim i As integerPrivate Sub Command1_Click() i = i + 1 Print iEnd SubPrivate Sub Command2_Click()

i = i - 1 Print i

End Sub

问:

( 1)单击两次按钮 1 ,结果是什么?

( 2)先单击按钮 1 ,再单击按钮 2 ,结果又是什么?( 1 ) 1 2

( 2 ) 1 0

Page 70: 第  8  章  过程

70 江苏计算机等级考试

Visual Basic 程序设计8.6.3 全局变量

在模块的通用部分用 Public 声明的变量,在整个应用程序中都可访问,即在其他模块也可以访问。全局变量分为两种:第一种——在窗体模块 (.frm) 中定义:

窗体 1 中的程序代码Public I as IntegerPrivate Sub Command1_Click() I=I+1End SubPrivate Sub Command2_Click() Form2.ShowEnd Sub

窗体 2 中的程序代码:Private Sub Form_Click() Print Form1.IEnd Sub

变量 I 是在窗体 1 中的通用部分定义的公有变量,其他模块可以访问它,但必须在变量前加上所属窗体的名称。

问:单击十次按钮 1 ,再单击按钮 2 ,单击窗体 2,结果是什么?

Page 71: 第  8  章  过程

71 江苏计算机等级考试

Visual Basic 程序设计

第二种——在标准模块 (.bas) 中定义:

窗体 1 中的程序代码

Private Sub Command1_Click()

I=I+1

End Sub

Private Sub Command2_Click()

Form2.Show

End Sub

窗体 2 中的程序代码:

Private Sub Form_Click()

Print I

End Sub

变量 I 是在标准模块 1 中的通用中定义的公有变量,其他模块可以直接访问,即无须在变量前加任何修饰。

标准模块 1 中的程序代码:

Public I as Integer

Page 72: 第  8  章  过程

72 江苏计算机等级考试

Visual Basic 程序设计 8.6.4 关于同名变量

当变量的作用域不同时,允许变量的名称相同。

例如 :

Dim i As integerPrivate Sub Command1_Click() i = i + 1 Print iEnd SubPrivate Sub Command2_Click() Dim i As integer i = i + 10 Print iEnd Sub

问:

( 1)单击两次按钮 1 ,再单击按钮 2 ,结果是什么?

1 210

说明:当变量名称相同而作用域不同时,优先访问局限性大的变量,即作用范围小的变量屏蔽作用范围大的变量。

Page 73: 第  8  章  过程

73 江苏计算机等级考试

Visual Basic 程序设计

Option explicitPublic x as integer,y as integer,z as integer

Private sub form_activate() Conflict_x Debug.print “X , Y 和 Z 是:” ,x,y,zEnd sub

Private sub form_load() X=10 : y=20 : z=35End sub

Private sub conflict_x() Dim x as integer x=135 Debug.print “X , Y 和 Z 是:” ,x,y,z End sub

举例:

思考:当把 X改成 form1.x 后,运行结果是什么?

Page 74: 第  8  章  过程

74 江苏计算机等级考试

Visual Basic 程序设计8.6.5 静态变量

在过程内的变量定义时,用 Static 关键字定义的变量。 所谓静态变量,是指仅在过程第一次执行时,分配给该变量内存单元,到过程执行结束时,并不象其它局部变量一样收回存储空间,系统并不收回分配给静态变量的存储空间,其内的内容得以保留,当再次调用执行该过程时,静态变量中保留了上次运行时的数据,本次执行可直接访问。 静态变量只在过程内有效 ,即是局部变量。

Private Sub Command1_Click()

Static i As integer

i = i + 1

Print i

End Sub

问:( 1)单击两次按钮 1 ,结果是什么?

( 2)如果将 Static改为 Dim ,结果又如何?

( 1 ) 1 2( 2 ) 1 1

Page 75: 第  8  章  过程

75 江苏计算机等级考试

Visual Basic 程序设计

Option explicitPrivate sub command1_click() Dim k as integer K=5 Call static-variable(k) Debug.print “第一次调用: k=”;k K=5 Call static-variable(k) Debug.print “第二次调用: k=”;kEnd sub

Private sub static_variable(n as integer) Static sta as integer Sta=n+sta N=sta+nEnd sub

说明:

因二次过程调用时,STA 的初值不同,所以虽然实参一样,但运行结果不同。

举例:

Page 76: 第  8  章  过程

77 江苏计算机等级考试

Visual Basic 程序设计

练 习

Dim a As Integer, b As Integer ‘ 模块级变量Private Sub Form_click() Dim x As Integer, y As Integer a = 5: b = 3 x = x + a: y = y + b Print fun1(x, y) Print fun1(x, y)End SubPrivate Function fun1(m As Integer, n As Integer) As Integer Static k As Integer ‘静态变量 Dim a As Integer, b As Integer ‘ 同名的过程级变量 a = a + m b = b - n k = k + a + b fun1 = kEnd Function

写程序运行结果:

Page 77: 第  8  章  过程

78 江苏计算机等级考试

Visual Basic 程序设计8.7 程序示例8.7 程序示例

例 8-5

例 8-6

例 8-7 ★例 8-11

Page 78: 第  8  章  过程

79 江苏计算机等级考试

Visual Basic 程序设计

[例 8-5] 利用级数法编程求反正弦函数值[例 8-5] 利用级数法编程求反正弦函数值[ 分析 ] :求解这一类累加和的题目,关键是两点:一是通项的表示,二是求解的精度,即当通项小于等于给定的误差值时,就停止累加。

[ 一般形式 ] 如下两种:Do … tx=… s=s+tx n=n+1 Loop While tx>eps

Do … tx=… if tx <=eps then exit do s=s+tx n=n+1Loop

[形式二 ] [形式一 ]

Page 79: 第  8  章  过程

80 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Command1_Click() Dim x As Single, n As Integer, eps As Single Dim s As Single, a As Single, temp As String temp = InputBox(“请输入一个绝对值小于等于 1 的数与允许误差 :” , “ 求函数值” , “0, 1e - 5“ ) temp = Trim(temp) ‘调用函数,删除前后空格 n = InStr(temp, “, ” ) ’找出分隔符,的位置 x = Left(temp, n - 1) ’取X eps = Right ( temp, Len ( temp) – n ) ’取允许误差 s = x : n = 1 Do a = afun(x, n) ’调用自定义函数,求通项 If a <= eps Then Exit Do s = s + a n = n + 1 Loop Label2.Caption = "arcsin(" & CStr(x) & ")=" Text1.text = sEnd Sub

Page 80: 第  8  章  过程

81 江苏计算机等级考试

Visual Basic 程序设计

n

i

i

ii

xix

xxxxx

1

12

753

)12()2(...42

)12(...31

...7642

531

542

31

32arcsin

Private Function afun(ByVal x As Single, ByVal n As Integer) As Single Dim i As Integer, p As Single p = 1 For i = 1 To n p = p * (2 * i - 1) / (2 * i) Next i afun = p * x ^ (2 * n + 1) / (2 * n + 1)End Function

Page 81: 第  8  章  过程

82 江苏计算机等级考试

Visual Basic 程序设计

分析:

传统的冒泡排序法,共进行 N-1轮扫描,每轮依次进行 A( 1)与 A ( 2), A( 2)与 A ( 3),…直至 A ( 10-i )与 A ( 10-i+1 )的比较,一旦前者比后者大,即交换他们的值。

如果有数据序列: 1, 2, 3, 4, 5, 7, 6;其实它只要进行一轮扫描,即排好序;但传统的冒泡排序法,不管它已排好序,还继续进行 5 轮扫描,只是不交换任何元素,这其实毫无意义。

因此,在改进的冒泡排序法中,我们增设了一个开关 Switch在比较过程中,若发生了数据交换,则设为 True ,而若一轮比较下来,没有发生数据交换,即此序列已排好序,就设为 False ,在每轮比较结束时,判断开关 Switch的值,若为 False ,退出循环,结束扫描。

[例 8-6] 改进的冒泡排序法

Page 82: 第  8  章  过程

83 江苏计算机等级考试

Visual Basic 程序设计

ub=Ubound(a) Switch=True Do While swtich Switch=False Ub=ub-1 For j=1 to ub ’n-I If a(j) > a(j+1) Then Switch=True TEMP=A(j) : A(j)=A(j+1):A(j+1)=TEMP End If Next j Loop

[ 改进的冒泡排序程序 ]

Page 83: 第  8  章  过程

84 江苏计算机等级考试

Visual Basic 程序设计例 8-7 把一个任意十进制转换成 N进制数( N<=16)

78

4

0

14

4

16

16

E

商余数

除 N取余法

Page 84: 第  8  章  过程

85 江苏计算机等级考试

Visual Basic 程序设计

二进制的基本元素是 0和 1 ;

八进制的基本元素是 0、 1、 2、 3、 4、 5、 6、7 ;

十六进制的基本元素是 0、 1、 2、 3、 4、 5、6、 7、 8、 9、 A、 B、 C、 D、 E、 F。

可以看出十六进制的基本元素包含其他两种进制的基本元素,因此,我们定义数组 Char(15) ,依次存放最大进制——十六进制的基本元素。

以整除 N的余数作为下标,取数组 Char(15) 中的元素就是需要的结果。

Page 85: 第  8  章  过程

86 江苏计算机等级考试

Visual Basic 程序设计

Option ExplicitDim N As integer, Num As LongPrivate Sub Command2_Click() EndEnd Sub

Private Sub Text1_Change() N = Val(Text1) Label4.Caption = Str$(N) + "进制数 "

End Sub

Private Sub Text2_Change() Num = Val(Text2) End Sub 需转换的数

N进制

Page 86: 第  8  章  过程

87 江苏计算机等级考试

Visual Basic 程序设计

Private Sub Command1_Click() Dim Ch As String, i As integer Dim Char(15) As String Dim Bin() As String

For i = 0 To 9 Char(i) = Str$(i) Next i For i = 0 To 5 Char(10 + i) = Chr$(Asc("A") + i) Next i Print ReDim Bin(1) Call trans(Bin, Char) For i = UBound(Bin) To 1 Step –1 Ch = Ch + Bin(i) Next i Text3 = Ch

End Sub

元素 0 1 2 …9 A B C D E F

下标 0 1 2…..9 10 11 12 13 14 15

数组 Char

调用过程 trans ,实参是数组,只需数组名

逆序输出结果数组 Bin元素

Page 87: 第  8  章  过程

88 江苏计算机等级考试

Visual Basic 程序设计

Private Sub trans(vary() As String, st() As String) Dim R As integer Dim K As integer K = 0

Do Until Num = 0 R = Num Mod N K = K + 1 ReDim Preserve vary(K) vary(K) = st(R) Num = int(Num / N)

LoopEnd Sub

结束条件商为0

将余数依次存放在动态数组 vary中

注意语句的次序

不断增加动态数组上界,以存放新元素

以余数为下标,找出数组中对应的字符

如 :14“E”

Bin Char

或 Num \N

Page 88: 第  8  章  过程

89 江苏计算机等级考试

Visual Basic 程序设计

将待排序的 N个数据存放在数组 SORT中,首先将 SORT( 1)认为已排序子序列,然后依次将 SORT( 2)、 SORT( 3)、… SORT( N)插入到已排好序的子数列中。每插入一个元素都依次进行以下三个操作。 1. 先将待插元素 SORT( I)放入变量 Temp中; 2.寻找插入位置:将 temp 依次与 SORT( I-1 )、 SORT( I-2 )、… 进行比较,一旦 SORT( k) < temp,则停止比较,插入位置即是 SORT( K)之后; 3.空出位置,将元素插入:将 SORT( k+1 ) 至 SORT( I-1 )的元素依次后移一位,再将变量 temp的值放入 SORT( K+1 )中;注意:为避免元素值丢失,必须先将 SORT( I-1 )赋给 SORT( I), SORT( I-2 )赋给 SORT( I-1 ),…,直至 SORT( K+1 )赋给 SORT( K +2 ) . … … 重复上述操作,将每个元素都插入到指定位置中。

[例 8-11] :直接插入排序法——从小到大的顺序。

Page 89: 第  8  章  过程

90 江苏计算机等级考试

Visual Basic 程序设计

3 6 1 5 4

3

6 1 5 4

61 65 65463

Temp

2

2

65432

排序前

排序后

直接排序示例

Page 90: 第  8  章  过程

91 江苏计算机等级考试

Visual Basic 程序设计

Private Sub insertion(sort( ) As Integer) Dim k As Integer, i As Integer, temp As Integer,Ub As Integer Ub = UBound(sort) For i = 2 To Ub temp = sort (i) k = i - 1 Do While temp < sort(k) sort(k + 1) = sort(k) k = k - 1 If k <= 0 Then Exit Do Loop sort (k + 1) = temp Next iEnd Sub

取待排序的元素

一边比较一边后移

temp比已排序的所有元素都小则结束

寻找第一个比 temp 小的元素的位置

为 temp 的插入位置

K指向前一个元素