第八章 过程
过程、函数的定义和使用
参数的传递
变量的作用域
本章主要内容
8.1 过程的定义与调用
?在程序设计中,为将复杂问题简单化,便于代码
的调试与维护,提高代码的利用率,往往将应用
按功能或其他目的划分为若干个模块,而每个模
块还可继续细分为子模块。这此模块或子模块,
都是可重复使用的、独立的 过程 。
?VB中常用的两种过程,
? 系统提供的内部函数和事件过程 ;
? 用户根据应用需要而设计的过程 。
8.1.1 Sub子过程的定义与调用
? Sub子过程定义的一般格式
[Static][Private][Public] Sub 过程名(形参列表)
语句块
[Exit Sub]
语句块
End Sub
? 参数与参数之间用,,, 分隔。
说明,
?Static,静态过程。过程中定义的局部变量均
为静态变量,即程序退出过程时,局部变量的
值仍保留并作为下次调用的初值。
?Private,私有过程。只能在本模块中调用,不
能被其它模块调用。
?Public,公有过程。能被程序中的所有模块调
用。
?Exit Sub, 在过程中终止过程的运行。
?End Sub, 过程结束标志。
?过程的调用方法
? 方法一,Call 过程名 [(实参列表 )]
? 方法二:过程名 [实参列表 ]
?过程的形参与实参
? 形参(形式参数):是用于接收过程中要使用
的数据的变量。
? 实参(实际参数):是传给 Sub过程的、有确
定值的变量或常数。 实参与形参类型应尽量一
致。
例 8-0 无参数静态过程
Private Sub Command1_Click( )
Call test ‘或 Call test ( ) 或 test
End Sub
Static Sub test( ) ‘过程中均为静态变量
Dim a(2) As Integer
a(0) = a(0) + 1
a(1) = a(1) + 1
Print a(0); a(1)
End Sub
?例 8-1 求 n!
Private Sub Command1_Click()
Call N(Val(Text1.Text))
End Sub
Public Sub N(a As Integer)
Dim i As Integer
Dim f As Long
f = 1
For i = 1 To a
f = f * i
Next i
Form1.Label3.Caption = Str(f)
End Sub
形式参数及类型
实参
?例 8-2 求矩形面积
Private Sub Command1_Click()
Call AREA(Val(Text1.Text),Val(Text2.Text))
End Sub
Public Sub AREA(A As Single,b As Single)
Dim sum As Double
sum = A * b
Label3.Caption = "求得的面积为," & sum
End Sub
形式参数及类型
实参
8.1.2 Function函数过程的定义与调用
? 子过程没有返回值,而函数过程有返回值。
? Function 过程定义的一般格式
[Static][Private][Public] Function 函数名 (参数列表 ) [As 类型 ]
语句块
[Exit Function]
语句块 [给函数名赋返回值 ]
End Function
说明,
? [Static][Private][Public],与子过程相同。
? As 类型, 指定返回函数值的类型。
? Exit Function,在函数过程中终止过程的运行。
? End Function,函数结束标志。
? 例 8-3判定成绩函数
Private Sub Command1_Click()
Text2.Text = Afirm(Val(Text1.Text))
End Sub
Private Function Afirm(cj As Integer) As String
Select Case cj
Case Is < 60
Afirm = "不及格 "
Case 60 To 69
Afirm = "及格 "
Case 70 To 79
Afirm = "中 "
Case 80 To 89
Afirm = "良 "
Case Is >= 90
Afirm = "优 "
End Select
End Function
? 例 8-4求最大公约数函数
Private Sub Command1_Click()
Dim a As Integer,b As Integer,x As Integer
a = Text1.Text
b = Text2.Text
If a < b Then '交换部分不要也可
x = a,a = b,b = x
End If
Label3.Caption = "最大公约数为," & Gcd(a,b)
End Sub
Public Function Gcd(x As Integer,y As Integer) As Integer
Dim ret As Integer
Do While y <> 0
ret = x Mod y
x = y
y = ret
Loop
Gcd = x
End Function
?思考题,
? 将例 8-1,8-2改为用函数来实现。
? 分别用子过程与函数实现以下算法,
? 求两个整数和的最小公倍数。
? 求三个、四个整数的最大公约数与最小公倍数。
? 求 n个整数的最大公约数与最小公倍数。
8.2 函数与过程的参数传递
?在调用过程时,过程中使用的是实际参数,它要
与定义过程时的形式参数一一对应,并以适当的
形式将实参传给形参,这便是参数传递,也是虚
(形参)实(实参)结合。
?VB中参数传递方式有两种,
? 传值,将实参的值传给形参后,实参与形参间便无任
何联系,即形参的变化不会对实参产生任何影响。传
值时,在形参前用 ByVal来界定。
? 传址 (默认方式,也叫引用):形参与对应实参用相
同的内存地址,形参的改变将影响实参,形参实际上
是实参的别名。
?例 8-5 按值传递
Private Sub Command1_Click() '按值传递
x = 10
y = 20
Cls
Print "x="; x,"y="; y,"调用前实参 "
Call temp1(x,y)
Print "x="; x,"y="; y,"调用后实参 "
End Sub
Sub temp1(ByVal x,ByVal y) '按值传递
x = x + 100
y = x * 60
Print "x="; x,"y="; y,"调用过程中的参数 "
End Sub
?例 8-7 按址传递
Private Sub Command1_Click() ‘按址传递
x = 10
y = 20
Cls
Print "x="; x,"y="; y,"调用前实参 "
Call temp1(x,y)
Print "x="; x,"y="; y,"调用后实参 "
End Sub
Sub temp1(x,y) ‘按址传递
x = x + 100
y = x * 60
Print "x="; x,"y="; y,"调用过程中的参数 "
End Sub
?例 8-6 计算并显示 x1,x2,x3,x4,x5,
x6,其中 x=5。
Private Sub Form_click()
Dim i As Integer,r As Single
For i = 1 To 6
r = temp(5,i)
Print r,
Next i
End Sub
Function temp(x As Integer,ByVal y As Integer) As Single
Dim p As Single
p = 1
Do While y > 0
p = p * x
y = y - 1
Loop
temp = p
End Function
此处的 y是按传值方式的,
若用传址方式,则会因循
环变量被非法修改而引起
错误,甚至死机。
而 x则按传值或传址都可以
(循环体中 x的值不变)。
?例 8-8 传值与传址对比
Private Sub Command1_Click()
Dim a As Single,b As Single
a = Val(Text1.Text),b = Val(Text2.Text)
If Option1.Value = True Then
Call testcall1(a,b) '传值
Else
Call testcall(a,b) '传址
End If
Label5.Caption = a & " " & b
End Sub
Private Sub testcall1(ByVal a As Single,ByVal b As Single)
a = 8,b = 9
Label4.Caption = a & " " & b
End Sub
Private Sub testcall(aa As Single,bb As Single)
aa = 8,bb = 9
Label4.Caption = aa & " " & bb
End Sub
传值方式
传址方式
数组作为过程的参数
?用数组名作为形参或实参
?用数组元素作为实参
?注意事项
? 用数组名作为参数时,相当于传值方式,在参
数列表中说明数组不需要说明维数的定义,但
括号不能省。
? 用数组元素作为实参时,应具体指明数组元素,
即必须有下标。
例 8-9 数组作参数,求 n× n方阵所有角元素之和。
Dim a() As Integer
Private Sub Command1_Click()
ReDim a(6,6)
Print "方阵为,"
For i = 1 To UBound(a,1) ' a()的第 1维上界 (最大下标 )
Print Tab(10); '格式:每行右移 10个字符
For j = 1 To UBound(a,2) 'a()的第 2维上界
a(i,j) = 10 * Rnd * i
Print a(i,j);
If a(i,j) < 10 Then Print " "; '格式对齐
Next j
Print
Next i
End Sub
( 待续)
(接上)
Private Sub Command2_Click()
Call sumdia(a())
End Sub
Private Sub sumdia(a() As Integer)
For i = 1 To UBound(a,1)
For j = 1 To UBound(a,2)
Sum = Sum + a(i,j)
Next j
Next i
Print "所有元素之和为,"; Sum
End Sub
例 8-10 求数组元素的最大值函数
Dim a( ) As Integer
Private Sub Command1_Click( )
ReDim a(10),Picture1.Cls
For i = 1 To UBound(a) ' 或 (a( ),1) 或 (a,1)
a(i) = 10 * Rnd + 1
Picture1.Print a(i);
Next i
End Sub
Private Sub Command2_Click( )
Label2.Caption = "最大元素值为," & maxvalue(a( ))
End Sub
Function maxvalue(a() As Integer)
max = a(1)
For i = 2 To UBound(a)
If max < a(i) Then max = a(i)
Next i
maxvalue = max
End Function
对象作为过程的参数
? VB中可用对象作为形参或实参
? TypeOf,判断控件的类型
例 对象参数
Private Sub Picture1_Click()
If TypeOf Picture1 Is Picture Then MsgBox
"Picture1 is PictureBox!"
End Sub
Private Sub Text1_Click()
If TypeOf Text1 Is TextBox Then MsgBox "Text1
is TextBox!"
End Sub
8.3 变量、过程的作用域
?在程序中我们定义的变量、过程、函数均有其作
用范围即作用域,作用域分为三个层次,
? 过程:作用域最小,仅限于过程内部。
? 模块:仅在某个模块或文件内。
? 全局(工程):作用域最大,作用在整个工程内。
VB应用程序组成
VB应用程序
(.VBP)
至少一个或若
干个窗体模块
(.Frm)文件
可有一个或若
干个标准模块
(.Bas)文件
可有一个或若
干个类模块
(.Cls)文件
事件过程 (Sub)
自定义过程 (Sub)
自定义函数过程 (Function)
自定义过程 (Sub)
自定义函数过程 (Function)
自定义属性过程 (Property)
自定义方法过程 (Sub或 Function)
自定义事件过程 (Event)
8.3.1 过程的作用域
?过程一般分为两级,
? 模块级(文件级):只能在本模块或本文件中被调用。
? 全局级(工程级):在整个工程内均能被调用。
?不同作用范围的 2种过程定义及调用规则
作用范围
模块级
全局级
窗体
标准模块
窗体
标准模块
定义方式
过程名加
Private
过程名加 Public
或缺省
过程名加 Public或缺省
能否被本
模块调用




能否被其
它模块调



能,但须在过程
名前加窗体名

8.3.2 变量的作用域
?变量一般分为三级,
? 过程级(局部级):过程内部定义的变量只能在过程
中使用。定义方式,Dim,Static。
? 窗体 /模块级:只能在本模块中被调用。定义方式:在
,通用声明, 中用 Dim或 Private声明。
? 全局级(工程级):在整个工程内均能被调用。必须
用 Public定义。
?不同作用范围的 3种变量定义及调用规则
作用范围
局部变量
窗体 /模块级变

全局变量
窗体
标准模块
声明方式
Dim,Static
Dim,Private
Public
声明位置
过程中
“通用声明”段
“通用声明”段
能 否 被本 模
块调用



能 否 被其 它
模块调用


能,但须
在过程名
前加窗体


8.3.3 静态变量
? Static 变量名 [As 类型 ]
? Static Function 函数名(参数列表) [As 类型 ]
? Static Sub函数名(参数列表)
用 Static定义的静态变量,只进行一次初始化,在程序运行过程
中,可保留变量的值。
用 Static声明的函数、过程,表示该函数、过程中所有变量均为
静态变量。
例 8-11 静态变量与动态变量的比较
Private Sub Form_click()
For i = 1 To 5
isum = sum(i)
Print "isum="; isum,
Next i
Print
End Sub
Private Function sum(n)
Dim j '比较与 Static j 的区别
j = j + n
sum = j
End Function
8.4 递归
? 递归:在调用一个函数的过程中,又直接或间接地调用该
函数本身。
例 8-12 用递归法求 n!
Private Sub Command1_Click()
n = Val(InputBox("请输入一个正整数,"))
Print n & "!="; FN(n)
End Sub
Public Function FN(n)
If n = 1 Or n = 0 Then
FN = 1
Else
FN = n * FN(n - 1)
End If
End Function
例 8-13 用递归法画三角形
Private Sub Picture1_Click()
Dim n As Integer
n = Val(InputBox("Input n:"))
Picture1.Print Tab(5); "递归 N=" & n; "时的图形。 "
Picture1.Scale (0,600)-(600,0) ‘定义 Picture1的座标系统,
Call triangle(30,320,570,30,570,n)
End Sub
Private Sub triangle(x1!,x2!,x3!,y1!,y2!,k%)
Dim u1!,u2!,v1!,v2!
If k > 1 Then
u1 = (x1 + x2) / 2
u2 = (x2 + x3) / 2
v1 = (y1 + y2) / 2
Call triangle(u1,x2,u2,v1,y2,k - 1)
Call triangle(x1,u1,x2,y1,v1,k - 1)
Call triangle(x2,u2,x3,y1,v1,k - 1)
Else
Picture1.Line (x1,y1)-(x3,y1)
Picture1.Line (x1,y1)-(x2,y2)
Picture1.Line (x2,y2)-(x3,y1)
End If
End Sub