Private Sub Command1_Click() Dim a As Integer, b As Integer a = 3: b = 4
swap1 a, b ‘调用传值方式过程 Print \ a = 5: b = 6
swap2 a, b ‘调用传地址方式过程 Print \End Sub
运行程序可以看到,过程swap1不能实现变量值的交换,这是因为它采用的是传值方式,过程中交换的是形参x和y的值,交换的结果不会影响实参a和b;而过程swap2采用的是传地址方式,形参与实参共用同一存储单元,过程中对形参的交换实际上就是在交换实参,所以可以完成对两个变量值的交换。
使用过程编写程序时,初学者往往思想比较混乱,总觉得无从下手,为此,建议如下: 首先,定义过程时,应根据处理问题的需要,确定形参的个数及其作用,明确参数传递方式,以确定对形参与实参具体要求。在形参前加ByVal和ByRef(或省略ByRef),确定形参的类型和作用。
其次,调用过程时,要根据形参个数、数据类型及参数传递方式,确定实参个数与类型。 在选择参数传递方式时,遵照如下原则:
(1)过程中处理的对象是数组时,只能采用传地址方式。
(2)过程的运算结果需要通过参数返回时,必须采用传地址方式。 应用上述思想,将求两个数的最大公约数gys过程定义为: Sub gys(ByVal m As Integer, ByVal n As Integer, t As Integer) 有如下优点:
第一,过程中各参数作用明确,形参m和n接受的是实参的值,形参t可以返回过程运算结果,参数传递方式分别是传值和传地址。
第二,调用过程时,格式简单,实参不需要加括号。如,调用gys过程语句Call gys(a, b, x),无论实参a、b带括号与否,均不会出现错误的。
第三,调用过程时,对实参的数据类型可稍宽松。在传值方式下,实参与形参数据类型只要相容图6-1 实参与形参类型不一致时的出错信息 即可。比如,若形参为双精度时,实参可以是任何
数值型数据。而在传地址方式时,实参的类型必须与形参一致,否则会出现如图6-1所示错误。
例6-5 编写求一组整数平均值的过程,并在主程序中调用。 分析:编写过程代码时,首先考虑形参个数及参数传递方式。因为要处理的是一组整数,个数并没有确定,所以设置一个整型形参数组接受处理对象。而运算结果只有一个平均值,所以设置1个普通变量返回(平均值),参数传递方式均为传地址方式。过程调用时,实参的个数应与形参个数一样,第一个实参应为数组,第二个实参只能为变量。 实现求一组整数平均值的过程如下:
Sub Tj(x() As Integer, aver As Single)
Dim m As Integer, n As Integer, i As Integer, s As Integer m = LBound(x)
-144-
n = UBound(x) For i = m To n s = s + x(i) Next i
aver = s / (n - m + 1) End Sub
调用上述过程的代码为: Private Sub Command1_Click() Dim a%(1 To 10), i%, aver! For i = 1 To 10
a(i) = Int(Rnd() * 10) '数组元素值随机产生,以方便读者调试程序 Print a(i); Next i Print
Call Tj(a, aver) '调用过程,获得平均值 Print \这些数的平均值为:\End Sub
如果需要从过程中获得多个处理结果,则需要设置多个参数。例如:
例6-6 编写能获得一组整数的平均值、最大值和最小值的过程并调用。代码如下: Sub Tj(x%(), max%, min%, aver!) Dim m%, n%, i%, s% m = LBound(x) n = UBound(x)
max = x(m): min = x(m): s = x(m) For i = m+1 To n
If max < x(i) Then max = x(i) If min > x(i) Then min = x(i) s = s + x(i) Next i
aver = s / (n - m + 1) End Sub
Private Sub Command1_Click()
Dim a%(1 To 10), i%, x%, y%, z! For i = 1 To 10
a(i) = Int(Rnd() * 10) Print a(i); Next i Print
Call Tj(a, x, y, z) '用x,y,z分别去对应形参的max,min,aver Print \这组数的最大值为:\ Print \这组数的最小值为:\ Print \这组数的平均值为:\End Sub
-145-
6.3 Function过程
如果过程只需要返回一个值,如计算N!及求一组数的平均值,使用VB提供了Function(函数)过程,可以使定义和调用都更加简便。Function过程不仅可以和Sub过程一样通过参数传递返回过程处理结果,还可以通过过程名返回一个处理结果。
6.3.1 Function过程的定义
定义Fucntion过程格式为:
[Static] [Private|Public] Function 过程名([参数列表]) [As 数据类型]
语句组 End Function 说明:
(1)与Sub过程相比,Function过程的过程名不仅标识函数过程,而且还有返回函数运算结果的功能,所以比Sub过程多了数据类型声明。
(2)语句组中一般应有一条语句将过程的运算结果赋给过程名。格式为:
过程名=表达式
(3)如果在过程体中含有Exit Function 语句时,表示强行退出过程。
6.3.2 Function过程的调用
Function过程一经定义,调用方式就与系统提供的内部函数完全相同。 例6-7 求组合数Cn?mn!的值,设m=6,n=10。函数过程及调用代码如下:
m!(n?m)!Function fact(ByVal n As Integer) As Double Dim i As Integer, f As Double f = 1
For i = 1 To n f = f * i Next i
fact = f '将处理结果通过函数名返回 End Function
Private Sub Command1_Click() Dim s As Double
s = fact(10)/ fact(6)/ fact(4) '注意调用方式 Print \End Sub
比较例6-1可以看出,使用函数过程时,定义时因为函数名可以返回一个值,所以就可以少一个形式参数;调用时因为函数名就带着处理结果,所以可以像使用内部函数一样直接写入表达式中。
实际上,将过程定义为Sub过程还是Function过程没有必然的界限。可以这样考虑:使用Sub过程能实现的功能,也一定能使用Funtion过程实现,反之亦然。但一般情况下,如果不需要过程返回处理结果,或者需要返回多个处理结果,则选择Sub过程;如果需要返回的运算结果只有一个,则选择Funtion过程会更方便些。
如将例6-6中的Sub过程中的关键字“Sub”换成“Function”,程序其它部分可以不作任
-146-
何变动,同样可以得到正确结果。
6.4 过程和变量的作用域
前面所述的过程代码均写在某一个窗体中,这些过程代码均被保存在它所在的窗体文件中。VB还允许将用户自己编写的过程代码单独保存成一个文件(扩展名默认为bas),这类文件叫标准模块文件。一个VB的应用程序一般是由若干个窗体和标准模块文件组成,每一个窗体可由若干个事件过程和自定义过程组成,每一个标准模块也可由若干个自定义过程组成。
过程在工程中所处的位置及声明方式不同,调用的范围也不同。过程可被调用的范围称为过程的作用域。
同样,变量是过程代码中必不可少的数据载体,变量声明的方式及位置不同,可被访问的范围也不一样,变量可被访问的范围称为变量的作用域。
6.4.1 过程的作用域
过程的作用域分为模块级和全局级两种。 1.模块级过程
模块级过程是指在窗体或标准模块通用声明段定义的、用Private关键字限制的过程,这类过程只能被它所属的窗体或标准模块中的其它过程调用。
例如:在窗体1的通用声明段定义一个模块级过程fact,分别被窗体1下的Command1_Click()和Form_Click()所调用是允许的。若在窗体2下调用窗体1中定义的过程“fact”,会出现如图6-2所示的提示信息。
Private Function fact(ByVal n As Integer) As Double Dim p!, i% p = 1
For i = 1 To n p = p * i Next i fact = p End Function
在Command1_Click()下调用fact函数过程:
图6-2 调用无效过程时提示信息 Private Sub Command1_Click()
Dim s!, i% s = 0
For i = 1 To 4
s = s + fact((i)) Next i Print s End Sub
在Form _Click()下调用fact函数过程: Private Sub Form_Click() Dim i%, s! s = 0
For i = 3 To 6
-147-
s = s + fact(i) Next i Print s End Sub
2.全局级过程
在窗体或标准模块中定义的过程默认是全局的,也可用Pub1ic关键字显式声明。全局级过程可供该应用程序中所有窗体和所有标准模块中的过程调用,但根据过程所处的位置不同,其调用方式有所区别:
(1) 在窗体中定义的全局级过程,该窗体之外的其它过程要调用,必须在过程名前加该过程所在的窗体名。
例如:定义在Form1通用段的函数过程fact。
Public Function fact(ByVal n As Integer) As Double Dim p!, i% p = 1
For i = 1 To n p = p * i Next i fact = p End Function
该函数可以被Form1的所有过程调用,也可以被同工程的任何窗体的任何过程调用。但在其它窗体中调用窗体1的“fact”过程,计算5的阶乘,调用格式为:Form1.fact(5)。
(2) 在标准模块中定义的全局级过程,该工程的任何过程都可以直接调用。 例如:在标准模块中定义函数过程“fact1”。
Public Function fact1(ByVal n As Integer) As Double Dim p!, i% p = 1
For i = 1 To n p = p * i Next i Fact1 = p End Function
在Form1的Command1_Click()下调用fact1函数过程:
Private Sub Command1_Click() s = 0
For i = 1 To 4
s = s + fact1(i) Next i Print s End Sub
在Form2中的Form_Click()下调用fact1函数过程:
Private Sub Form_Click() s = fact1(5) Print s End Sub
-148-
百度搜索“77cn”或“免费范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,免费范文网,提供经典小说综合文库第06章 模块化程序设计(2)在线全文阅读。
相关推荐: