《VB自定义函数与子过程.ppt》由会员分享,可在线阅读,更多相关《VB自定义函数与子过程.ppt(45页珍藏版)》请在三一办公上搜索。
1、第八章 自定义函数与子过程,几个概念,一、VB程序的基本构成是过程。二、VB6.0中过程有两大类:内部过程和外部过程。1、内部过程:系统提供的,不需要用户编写,如内部函数。2、外部过程:用户根据需要定义的,供调用的程序段,外部过程分为子过程、函数过程。,几个概念,三、在VB中使用过程编程有两个优点:1、过程可使程序划分成离散的逻辑单元,每个单元都比没有使用过程的整个程序容易调试。2、一个程序中的过程,往往不必修改或只需稍作改动,便可以成为另一个程序的构件。四、Visual Basic 的两类过程:1、Sub 过程(子过程),不返回值或多个返回值。2、Function 过程(函数过程),有一个返
2、回值。,8.2 自定义函数过程,例8.1 设计程序将50,100区间内的偶数拆成两个素数之和分析:可先将偶数拆分成两个数之和,在分别对这两个数进行素数判定,若都是素数就输出。例如:可将50拆分为:3+47、4+46、.47+3,然后对每种组合中的两个数分别进行素数判断。因此,可以定义一个专门用于素数判断的函数过程。,8.2 自定义函数过程,Private Function prime(ByVal x As Integer)As Boolean Dim I%prime=True 函数赋初值True For I=2 To Sqr(x)If x Mod I=0 Then 判断x是否可被i整除 pri
3、me=False 函数取值False,则x不是素数 Exit Function 函数结束 End If Next IEnd Function,在事件过程中调用以上定义的函数,得到结果。Private Sub Form_Click()Dim I%,N,K%I=1 计数 For N=50 To 100 Step 2 取偶数 For K=3 To N/2 第一个数的取值区间折半 If prime(K)And prime(N-K)Then 二次调用结果都是素数输出 Print I;:;N;=;K;+;N-K Exit For 退出k循环 End If Next K I=I+1 Next NEnd Su
4、b,8.2 自定义函数过程,8.2.2 函数过程的定义 函数过程在被调用前,一定要先定义,函数定义的方式一般有两种:1利用“添加过程”对话框定义 打开窗体或模块的代码窗口,单击“工具”菜单,选择“添加过程”命令,即可打开“添加过程”对话框。,8.2 自定义函数过程,在“添加过程”对话框中输入并选择相应的内容和项目即可。在“名称”文本框内输入待定义函数过程的名称,在“类型”选项组中选择“函数”单选按钮。单击确定按钮,则可建立一个函数过程的框架。,8.2 自定义函数过程,2直接在代码窗口定义 进入代码窗口后,在左侧显示对象名的下拉列表框中选择“(通用)”,在右侧显示过程的下拉列表框中选择“(声明)
5、”,然后输入Function及函数名即可。自定义函数过程的格式如下:Public|PrivateStaticFunction()As 函数名=Exit Function 函数名=End Function,8.2 自定义函数过程,1)Public或Private:表示函数是“公有的”或“私有的”。Public表示该函数为公有过程,定义后整个程序范围内均可调用该函数,但调用时必须加上该函数所在的窗体或标准模块作为前辍,而Private表示私有子过程,用它定义的函数只能在本窗体或模块中被调用。缺省默认是公有的。2)Static:表示函数中的局部变量是静态变量,在函数被调用后,其值仍然被保留;,说明,
6、3)():该项中的参数为形式参数,又称哑元,可以是变量名或数组名,当参数为数组名时,形参和实参在参数声明时应省略其维数,但括号()不能省略。当参数有多项时,参数间要用逗号分隔开。使用格式为ByVal|ByRefAs4)ByVal:表示调用时参数为值传递方式,实参的值不随形参值的变化而变化;,说明,说明,5)ByRef:参数默认选项,表示参数为地址传递方式,实参的值随形参值的改变而改变,数组只能以传地址的方式引用;6)As 表示函数返回值的类型,默认为变体型。在函数体内至少应对对函数名赋值一次。7)函数名=,用于函数运行后返回一个值。如在定义中未对函数名赋值,则将返回一个默认值。其中,数值型为0
7、,字符型为“”,变量型为Empty。8)Exit Function用于退出函数过程,该项一般嵌套在if结构中使用,在满足if条件时退出该函数过程。,例8.2 设计一个程序统计字符串中西文字符个数。算法:汉字的Asc()函数的返回值小于0;西文字符的Asc()函数的返回值大于0。Function CountXw%(ByVal S$)Dim I%,T%,K%,C$For I=1 To Len(S)C=Mid(S,I,1)逐个地取出字符 If Asc(C)0 Then K=K+1 字符ASCII码大于0,则个数累加1 Next I CountXw=K 返回函数值End Function,例8.2 设
8、计一个程序统计字符串中西文字符个数。Private Sub Command1_Click()Dim C1%C1=CountXw(Text1.Text)调用CountXw函数 Picture1.Print Text1 在Picture1中显示统计的结果 Picture1.Print 有;C1;个西文字符数End Sub,8.2.3 函数过程的调用1函数调用的形式其调用形式如下:变量=函数过程名(实参列表)其中,实参列表中的实参是传递给被调用过程的变量或表达式。例题8.2中的C1=CountXw(Text1.Text)就是一次函数调用。注意:调用函数后,函数过程名将有一个返回值,函数是一个特殊的表
9、达式。因此,函数不能作为单独的一条语句,而必须要以给变量赋值或与命令一起使用的形式。例如:If prime(K)And prime(N-K)Then,8.2 自定义函数过程,8.2 函数过程的定义和调用,2函数过程调用的执行流程 在事件过程调用一个函数过程时,程序在执行这两个过程时的流程如下图所示。,Function Hypotenuse(x%,y%)Hypotenuse=Sqr(x 2+y 2)End FunctionPrivate Sub Command1_Click()s=Hypotenuse(a,b)End Sub,函数过程调用的执行流程图,过程调用时执行顺序如下:1)事件过程Comm
10、and1_Click()在执行到函数过程调用语句“s=Hypotenuse(a,b)”时,程序执行控制权转移到Hypotenuse()函数过程中;2)执行控制权转移时,实参a和b的值将分别传递给Hypotenuse()函数中的形参x和y;,3)x和y获得初值后,即可执行函数过程中的程序代码并给函数过程名赋值,该值即为整个函数过程的返回值;4)函数执行结束后,函数的返回值将赋给主调事件过程的变量s;5)变量s得到赋值后,接着执行调用函数过程后面的剩余语句。,8.3 子过程的定义和调用,引例 调用函数后,将得到函数的返回值,但是,在有些问题的中,过程执行结束后不需要返回值,用函数过程实现就会非常困
11、难,而应该使用子过程的形式。例8.3 试编写一个将两个数进行交换的过程供其它过程多次调用。分析:先编写一个具有将两个数进行交换的子过程,需要进行两数交换时,调用该子过程,同时将待交换的两个数传送到该子过程中,在子过程实现两数交换。子过程执行结束后,将被交换后的两个数返回到主调过程中。,Cp()子过程的定义Private Sub Cp(A As Integer,B As Integer)形参为传址方式 If A=0 Then Exit Sub End If A=A+B A和B的值交换,带回主调过程 B=A-B A=A-B Print 在子过程中交换后的值 Print A=;A,B=;BEnd S
12、ub,主调程序Cp子过程Private Sub Command1_Click()Dim Str1$,Va%,Vb%Str1$=输入对话框 Va=InputBox(Va=,Str1$)Vb=InputBox(Vb=,Str1$)Print 在主调过程中调用子过程前的值 Print Va=;Va,Vb=;Vb 输出原始值 Call Cp(Va,Vb)Print 在主调过程中调用子过程后的值 输出经子过程处理过后的返回值 Print Va=;Va,Vb=;VbEnd Sub,运行结果:,程序运行后,单击窗体以触发Form_Click()事件过程,运行结果如下图所示。从程序中可以看到,Va和Vb的初值
13、分别是45和23,而在窗体中输出时Va和Vb的值分别是23和45,达到了两个数交换的目的。,8.3 子过程的定义和调用,8.3.1 子过程的定义 子过程以过程名来标识,被其它过程调用。子过程与事件过程有一定区别,事件过程可以在该事件触发或调用时执行,而用户自定义的子过程只有在被其它过程调用时才能执行。子过程的定义跟函数过程的定义相类似,在代码窗口中输入Sub及子过程名即可,系统会自动加上End Sub与子过程名后的一对括号(),然后即可在子过程的框架中输入程序代码。,子过程的定义格式:Private|PublicStatic Sub()Exit Sub End Sub说明:Public|Pri
14、vate与Static:它们的含义和作用与函数过程中相应的这些关键词相同。():该项中参数的形式和调用方法也与函数过程相同。Exit Sub:退出过程,该项一般嵌套在if结构中使用,在满足if条件时退出该过程。,6.2 子过程的定义和调用,例:分别计算两个数的和与差,而当两个数的值均为0时则不进行任何计算。Sub Operation(x As Integer,y As Integer)Dim t1 as Integer,t2 as Integer If x=0 and y=0 Then Exit Sub End If t1=x+y t2=x-y Print“t1=”;t1;“t2=”;t2En
15、d Sub,6.2 子过程的定义和调用,在Sub 过程与Function 过程之间的区别:1)子过程名无类型说明,在子过程中不能对子过程名进行赋值。2)子过程的形式参数没有具体的值,只代表参数的个数、位置、类型。3)子过程的调用必须是一条独立的语句。,8.3 子过程的定义和调用,8.3.2 子过程的调用1使用Call语句调用格式:Call 子过程名(实参列表)说明:实参的个数,数据类型都应与被调用过程的形参一一对应。用Call语句调用时,若有实参,括号不能省略,否则,可以省略括号。若子过程要通过实参向主调过程中返回值,则实参只能是简单变量、数组名或自定义类型变量。,8.3 子过程的定义和调用,
16、例如:Private Sub Command1_Click()a=”Visual Basic”b=“6.0”Call Link(a,b)End Sub 此时,将输入的值a和b作为实参调用Link子过程,通过调用将两个实参传递给形参,然后在过程中计算。,8.3 子过程的定义和调用,2直接使用过程名调用格式:子过程名 实参列表说明:此形式调用子过程时,实参不用加括号,否则在有的编译版本中出现编译错误,若有多个实参,则实参之间用逗号分隔。例如:Private Sub Command1_Click()a=”Visual Basic”b=“6.0”Link a,b End Sub,8.4 参数传递,8.
17、4.1 形参与实参 1、形参 指出现在Sub 和Function过程形参表中的变量名、数组名,该过程在被调用前,没有为它们分配内存,其作用是说明自变量的类型和形态以及在过程中的作用。形参可以是除定长字符串变量之外的合法变量名,也可以带括号的数组名。2、实参 实参就是在调用Sub 和Function过程时,从主调过程传递给被调用过程的参数值。实参可以是变量名、数组名、常数或表达式。在过程调用传递参数时,形参与实参是按位置结合的,形参表和实参表中对应的变量名可以不必相同,但它们的数据类型、参数个数及位置必须一一对应。,8.4 参数传递,3、形参与实参的关系 形参如同公式中的符号,实参就是符号具体的
18、值,在调用过程前必须得到赋值;调用过程就是实现形参与实参的结合,把实参的值通过调用传递给形参,相当于把值代入公式进行计算。,8.4 参数传递,8.4.2 地址传递与值传递 在Visual Basic中,实参与形参的结合有两种方式,即地址传递(ByRef)与值传递(ByVal),地址传递又称为引用。,10,10,20,a的地址,地址传递,值传递,实参b,形参y,实参 a,形参 x,8.4 参数传递,1地址传递 在VB6.0中,在形参前加ByRef或在缺省该关键字,则实参与形参的结合就是地址传递方式。例8.5通过调用子过程实现将两个字符串进行互换。分析:首先定义一个能够实现字符串交换的子过程Swa
19、p1,该子过程包含两个形参。在主调过程中,分别对两个字符变量A和B进行赋值,将这两个变量作为调用子过程Swap1的实参,要使得形参的改变能够影响实参的值,应该采用地址传递的方式。,8.4 参数传递,程序代码如下:传址子过程Swap1Public Sub Swap1(X As String,Y As String)Dim T As String T=X 下面三行语句用于交换形参的值 X=Y Y=T Print“传址子过程中互换变量值后:”;“X1=”;X;“”;“Y1=”;Y;Print“_ PrintEnd Sub,8.4 参数传递,以下为主调过程(事件过程)Private Sub Form_
20、Click()Dim A As String,B As String 定义字符串变量A、B Cls 清除窗体文字 A=ABCDE 为变量A赋值 B=12345 为变量B赋值 Print 主过程在调用子过程之前:;A1=;A;B1=;B Print _ Print Swap1 A,B 调用子过程Sub1 Print 主过程调用传址子过程之后:;A1=;A;B1=;BEnd Sub,8.4 参数传递,程序运行结果如下图:从程序的运行结果可以看出,对形参的改变就是对实参的改变。如果不希望这种改变,则在被调用过程中不要出现对形参值改变的语句,或使用按值传送方式传递数据,将不会引起实参值的改变。,8.4
21、 参数传递,2值传递 传值就是通过传送实参的值而不是传送地址的方法给被调用过程中传递数据。这样,被调用的过程并没有访问实参的地址,因而也不会改变实参的值。格式:Private Sub Jc(ByVal a%)End Sub,8.4 参数传递,例8.6将两个字符串在子过程中实现互换,但主调过程的字符串不互换。分析:首先定义一个能够实现字符串交换的子过程Swap1,该子过程包含两个形参。在主调过程中,分别对两个字符变量A和B进行赋值,将这两个变量作为调用子过程Swap1的实参,要使得子过程中形参的值进行互换而不影响主调过程的实参,应该采用值传递的方式。,8.4 参数传递,代码如下:传值子过程Swa
22、p1Public Sub Swap1(ByVal X As String,ByVal Y As String)Dim T As String T=X X=Y Y=T Print 传值子过程中互换变量值后的变量数据:;X1=;X;Y1=;YEnd Sub,8.4 参数传递,以下为主调过程(事件过程)Private Sub Form_Click()Dim A As String,B As String Cls 清除窗体文字 A=ABCDE B=12345 Print 主过程在调用子过程之前的原变量数据:;A1=;A;B1=;B Print _ Swap1 A,B Print 主过程调用传值子过程之
23、后的变量数据:;A1=;A;B1=;BEnd Sub,8.4 参数传递,运行结果如下图所示。从程序的运行结果可以看出,使用按值传送方式传递数据,将不会引起实参值的改变。也就是说,两个形参的值虽然进行了互换,但没有影响实参的值,实参的值在调用子过程后仍然保留了初值。,8.4 参数传递,8.4.3 数组参数的传递 在VB6.0中,允许使用数组作为实参传递到子过程的形参中,数组传递必须采用地址传递的方式来传递参数,数组参数在传递时应注意以下两个问题:在实参和形参列表中只写数组名,忽略维数的定义,但圆括号不能省,当数组作为参数传递时,系统将实参数组的起始地址传给过程,使形参数组也具有与实参数组相同的起
24、始地址,若参数是多维数组,每维以逗号分隔;被调过程可分别通过Lbound和Ubound函数确定实参数组的下界和上界。,8.4 参数传递,例8.6 在主调过程定义一个4*4的二维数组,在子过程中将数组对角线上的元素均加上常数15.函数过程:Private Sub ArrayAdd(A()数组作为形参只有传址方式 Dim I%,J%For I=0 To 3 For J=0 To 3 If I=J Then A(I,J)=A(I,J)+15 主对角上元素加15 Next J Next IEnd Sub,8.4 参数传递,Private Sub Command1_Click()Dim C(3,3),I%,J%,I1%,J1%Print 调用前 For I=0 To 3 For J=0 To 3 C(I,J)=Int(Rnd*101):Print Tab(J*5+1);C(I,J);Next J Print Next I Call ArrayAdd(C()For I1=0 To 3 返回后C数组发生改变 For J1=0 To 3 Print Tab(J1*5+1);C(I1,J1);Next J1 Print Next I1End Sub,8.4 参数传递,程序运行后如下图所示。此时,采用传址方式,实现数组的整体赋值。,