资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,05 十一月 2026,第章 VB子程序和函数过程,本章主要介绍:,定义Sub过程,定义Function函数过程,调用Sub过程或Function函数过程,调用事件过程,变量的存储类别和作用域。,编写过程,可以实现代码重复使用。,2,程序设计教程,8.1.1,什么是过程,过程是编写程序的功能模块,使用过程主要有以下两方面的原因:,1可以把复杂的问题简单化,任务分解为子任务,子任务用过程实现,使程序结构清晰、易读,也便于调试和维护。,2可以实现代码重复使用,可以避免重复编写的烦琐,可以减少出错。,8.1 概述,3,程序设计教程,8.1.2,过程分类与调用流程,VB中的过程分成两大类:,事件过程:,由对象的某个事件驱动执行,如Click事件过程、Load事件过程等,通用过程,由用户自已定义的完成某一功能的过程。,通用过程不属于任一对象,不由事件驱动,使用专用的调用语句来执行它,4,程序设计教程,通用过程又分两类:,Sub过程(子过程、子程序),往往用于处理不需要有返回值的一些基本任务,如显示矩阵。,Function函数过程:,可作为函数使用,它一般应有一个返回值,如求阶乘。,5,程序设计教程,调用流程如图:,VB的应用程序就是由若干个过程构成的。,6,程序设计教程,【例8-1】设计程序,其作用是根据姓名查电话号码。,输入姓名后,单击“确定”或按回车键,使姓名与内部储存的一批姓名核对,若存在,则显示“欢迎查询”内并使窗体只显示标签,且文字为姓名和对应的电话号码。最多允许输入3遍。,控件:,1个标签、1个文本框,1个“确定”命令按钮,8.2 查询电话号码,7,程序设计教程,过程:,Form_Load事件:储存一批姓名和电话号码等,Command1_Click事件:核对姓名,显示提示,Text1_KeyPress事件:核对姓名,显示提示,CheckName 函数过程:判断此人是否存在,得下标/-1。,姓名和电话号码为模块级变量、N为静态变量。,8,程序设计教程,Dim Name1,Phone 声明Name1,Phone为模块级Variant类型变量Private Sub Command1_Click(),核对姓名,显示提示 Static N As Integer 声明N为静态整型变量 Dim T As Integer T=CheckName(Text1.Text)以姓名为参数,调用函数CheckBook If T -1 Then MsgBox 欢迎查询!,提示 Text1.Visible=False:Command1.Visible=False Label1.Caption=姓名:&Text1.Text&Chr(13)&电话:&Phone(T)Label1.Left=(Form1.ScaleWidth-Label1.Width)/2 让标签在中间,9,程序设计教程,Else N=N+1 核对次数加1 If N Max Then Max=b If c Max Then Max=cEnd Function,35,程序设计教程,以上函数过程的过程名为Hello,形式参数a、b、c为整型,函数体中多次使用了函数名Max,并使用了参数,特别说明:不能写成Max(a,b,c)=a。,36,程序设计教程,8.5.2,调用,Function,函数过程,函数调用方式如同调用VB内部函数,调用格式:函数过程名(实参数列表),调用函数往往在可以使用表达式的代码中出现,只要类型相同就可以了。,如对Max函数过程,可以使用:A=Max(1,43,5):Print Max(Max(1,3,21),56,4),如果函数定义在窗体模块中而调用语句在其它模块中,则调用时应在函数名前加上所属的窗体名。,实参用法和要求,与子过程调用相同。,37,程序设计教程,【例8-4】编程计算,在本文框输出。要求计算n!使用函数过程Factorial(n)实现。,控件:2个文本框、3个标签 1个命令按钮。,过程:,通用函数过程Factorial(n):求阶乘,Command1_Click事件:求,属性:,大部分属性在Form_Load中设置,命令按钮为图形按钮,更改Style、Caption和Picture属性,38,程序设计教程,Function Factorial(N As Integer)As Double 通用函数过程,求n!Dim i As Integer,T As Double T=1 For i=1 To N:T=T*i:Next i Factorial=T,End Function,Private Sub Command1_Click()计算结果,要求mn Dim M As Integer,N As Integer M=Val(Text1.Text):N=Val(Text2.Text)If M N Then 当mn时,给出提示,清除数据,跳出过程,39,程序设计教程,MsgBox m必须大于等于n。,提示“,Text1.Text=:Text2.Text=:Text1.SetFocus,Exit Sub,End If,Label3.Caption=答案:&,Factorial(M)/(Factorial(N)*Factorial(M-N),End Sub,Private Sub Form_Load(),初始化控件属性,Label1.Caption=m=:Label2.Caption=n=:Label3.Caption=“,Text1.Text=:Text2.Text=“,End Sub,40,程序设计教程,8.5.3 Exit Function,语句,使用Exit Function语句跳出Function函数过程。,Exit Function语句一般与If语句合用,即在满足某种条件时退出该函数过程,返回调用处。,如修改例8-4中的Factorial函数过程,当N0时显示“参数错误”并退出Factorial函数过程。则可以增加:,If N0 Then Factorial=1:MsgBox 参数错误:Exit Function,注意:在函数过程中途退出不能使用End Function。,41,程序设计教程,形式参数(形参)是过程定义时的参数,实际参数(实参)是过程调用时的参数,过程调用时,实参向形参传递数据,传递的方法分为:,“引用传递”(“引用调用”),“按值传递”(“按值调用”),(这里的过程是统指子过程和函数过程),8.6 引用调用和按值调用,42,程序设计教程,8.6.1,引用调用,引用调用:形参变量与实参变量,共享,一个内存单元。,此时,过程中对形参的修改,影响实参变量,即可实现把过程中对形参修改的结果带回调用过程。,前面格式中,所有参数都采用引用调用,除非实参是表达式。,单击Command1后,N1和N为同一个内存单元,所以N1的值就变成8。最终窗体显示8。,43,程序设计教程,引用调用的形参说明,可使用格式:,ByRaf 参数名 As 类型说明,缺省ByRaf表示引用调用。如:,Sub Abc1(N As Integer)N=N+5 End Sub Private Sub Command1_Click()Dim N1 As Integer N1=3:Call Abc1(n1):Print N1 End Sub,44,程序设计教程,8.6.2,按值调用,按值调用时,实参值被复制到形式参数中,如果实参为变量,相当于两者用了不同的存储单元,对形参的操作不会影响实参的内容。,按值调用的形式参数的说明,使用格式:,ByVal,参数名,As 类型说明,若实参是表达式,则一律使用按值调用,单击Command1后,N1和N实际上是不同的内存单元,调用时只将N1的值送入形参N中,最终显示3。,45,程序设计教程,如:,Sub Abc2(ByVal N As Integer)N=N+5 End Sub Private Sub Command1_Click()Dim N1 As Integer N1=3:Call Abc2(N1)Print N1 End Sub,46,程序设计教程,【例8-5】编写求一元二次方程实数解的过程并调用它。,由于方程有两个解。而函数返回一个值。解决方法:,编写Sub过程Root,X1和X2为引用调用,A、B、C为按值调用。,Sub Root(ByVal A As Single,ByVal B As Single,_,ByVal C As Single,X1 As Single,X2 As Single)Dim D As Single D=B*B-4*A*C If A=0 Then MsgBox 不是一元二次方程!:Exit Sub If D 0 Then MsgBox 方程无实数解!:Exit Sub X1=(-B+Sqr(D)/(2*A):X2=(-B-Sqr(D)/(2*A)End Sub,47,程序设计教程,Private Sub Command1_Click(),Dim A As Single,B As Single,C As Single,X1 As Single,X2 As Single,A=3:B=9:C=5,Root A,B,C,X1,X2 A、B、C按值,X1和X2引用调用,Print X1,X2,End Sub,程序调用前,X1和X2没有赋过值,通过引用调用,使它们得到了方程的实数解。,48,程序设计教程,8.6.3,传递数组,传递数组,形式参数的格式:参数名()As类型说明,数组不能按值调用,只能引用调用,【例8-6】随机产生两个34的矩阵A和B,矩阵元素值为150的整数。求两个矩阵的和C。并输出矩阵A、B和C。运行如,图,。,矩阵加法使元素C(i,j)=A(i,j)+B(i,j),49,程序设计教程,编写过程:,通用过程PrintM:实现矩阵输出,通用过程CreateM:产生矩阵,事件过程Form_Load:初始化随机数种,事件过程Command1_Click:调用通用过程并实现题目,50,程序设计教程,8.6.3,传递数组-矩阵加法,Sub CreateM(A()As Integer),创建,For i=1 To UBound(A,1),For j=1 To UBound(A,2),A(i,j)=Int(Rnd*50)+1,Next j,Next i,End Sub,51,程序设计教程,Sub PrintM(A()As Integer)输出,For i=1 To UBound(A,1),For j=1 To UBound(A,2),Print A(i,j),Next j,Print,Next i,End Sub,说明:UBound函数的第2个参数指数组的维,当该数为1时,指它的第1维上界,该数为2时,指它的第2维上界。,52,程序设计教程,Private Sub Command1_Click()Dim A(3,4)As Integer,B(3,4)As Integer Dim C(3,4)As Integer,i As Integer,j As Integer CreateM A 创建矩阵A CreateM B 创建矩阵B For i=1 To 3 矩阵加法 For j=1 To 4 C(i,j)=A(i,j)+B(i,j)Next j Next i,Cls,53,程序设计教程,Print Tab(22);A 矩阵:PrintM A 输出A Print Tab(22);B 矩阵:PrintM B 输出B Print Tab(22);C 矩阵:PrintM C 输出C,End Sub,Private Sub Form_Load()Randomize,End Sub,54,程序设计教程,8.6.4,可选参数,可选参数表示调用时该参数可选(可不写),定义可选参数是在形参的前加Optional关键字,若该形参后还有参数,则后面必须都定义为可选。,IsMissing函数判断是否提供可选参数,若未提供,则值为True。,这时两个过程调用语句可分别改为:Print_triangle Ch,Line 2个参数Print_triangle Ch,Line,-1 3个参数。,55,程序设计教程,如例8-3的Print_triangle过程,可将第3个参数Flag设置为可选:若调用时不用Flag表示输出正三角形:,Sub Print_triangle(S As String,Line As Integer,Optional,Flag As Integer)Dim A As Integer,B As Integer,C As Integer,i As Integer,j As Integer Cls:A=1:B=Line:C=1 If Not IsMissing(Flag)Then If Flag M Then M=A(i)Next i Max=MEnd Function,Private Sub Command1_Click(),调用时,参数个数可以不限 Print Max(6,4,3,2,1)使用了,5,个参数 Print Max(10,34,5,56,2,55,67,83,9)使用了,9,个参数End Sub,58,程序设计教程,8.6.6,对象参数,过程可以使用对象,如在7.8节的“选择联系人”例子中,List1_KeyDown事件过程和List2_KeyDown事件过程的代码除了对象名不同外,其它是可以相同,因此可用参数为对象的通用过程Delete:,59,程序设计教程,Sub Delete,(a As,Object,keyCode As Integer)将a定义为对象变量 Dim i As Integer If keyCode=vbKeyDelete Then 按下了Delete键,删除已选项目,For i=,a.,ListCount-1 To 0 Step-1 If,a.,Selected(i)=True Then,a.,RemoveItem i Next End If,End Sub,Private Sub List1_KeyDown(keyCode As Integer,Shift As Integer),Delete List1,keyCode,End Sub,Private Sub List2_KeyDown(keyCode As Integer,Shift As Integer),Delete List2,keyCode,End Sub,60,程序设计教程,变量是存放数据的单元,其中的数据随着程序的运行而变化。,过程中使用Dim语句声明的变量,将随着过程的结束而消失,其中的储存的数据也就不再存在。,其实,程序还可以使用多种存储类别的变量:,可以整个应用程序都可使用,可以在定义的过程中继续使用,8.7 存储类和作用域,61,程序设计教程,8.7.1,存储类别,根据存储类别,变量分成静态变量和动态变量。,1动态变量,指程序运行进入变量所在过程时,才给变量分配内存空间,退出该过程时,变量所占用内存空间自动释放,其值消失,变量不再存在。,在过程中使用Dim语句声明的变量属于动态变量。,62,程序设计教程,如有以下过程:Private Sub Command1_Click()Dim A As Integer A=A+1:Print AEnd Sub,窗体启动后,无论用户单击Command1多少次,显示的数据总是1。,63,程序设计教程,8.7.1,存储类别,2静态变量,静态变量指程序运行中虽然退出变量所在的过程,但变量所占用的空间没有释放,值仍保留,若下次再进入该过程,原值仍可使用。,使用Static语句在过程中声明的变量属于静态变量。,Static变量只能在过程中声明。格式:Static 变量名 As 类型说明,64,程序设计教程,例如以下事件过程,单击显示:,Private Sub Command1_Click()Dim A As Integer A为动态变量 Static B As Integer B为静态变量 A=A+1:B=B+1:Print A,BEnd Sub,1 1,1 2,1 3,65,程序设计教程,8.7.2,作用域,作用域指变量或符号常量在程序哪个范围中有效。,作用域分成:局部的、模块级的和全局的三类。,1局部变量/局部符号常量,局部变量是指在过程中声明的变量,它在过程内采用Dim语句或Static语句声明,局部符号常量是指在过程中定义的符号常量,它在过程内采用Const语句定义。,它们只能在该过程中有效。,66,程序设计教程,其它过程中出现同名量,则代表着另一个量。如:,Private Sub Command1_Click()事件过程Command1 Dim X As Integer X变量仅在该过程中有效 Const PI=3.1415926 符号常量PI仅在该过程中有效 X=3:Print 有效的值;X*PIEnd SubPrivate Sub Command2_Click()事件过程Command2 Print X,PI 无效End Sub,若用了Option Explicit语句,单击Command2时还会出错,67,程序设计教程,2模块级变量/模块级符号常量,模块级变量或符号常量可在一个模块的各过程中使用,窗体模块级变量/常量是在通用对象的声明部分用Dim或Private语句声明变量,或用Const定义符号常量。如:,Private X As Integer 也可以使用Dim,将x声明为模块级变量Private Sub Form_Load()X=5End Sub,68,程序设计教程,Private Sub Cmd1_Click()X=X+1 Print 过程中的 X=;XEnd SubPrivate Sub Cmd2_Click()X=X+1 Print 过程中的 X=;XEnd Sub,按序单击Cmd1和Cmd2,显示:过程中的 X=6过程中的 X=7只要应用程序不停止运行,即使窗体卸下后再次装载,原值仍可用,69,程序设计教程,8.7.2,作用域,3全局变量/全局符号常量,全局变量在整个应用程序中有效,全局变量在窗体通用对象或标准模块中,Public,声明:,Public 变量名 As 类型说明,定义全局符号常量的格式为:,Public Const 符号常量名=常量表达式,70,程序设计教程,说明:,过程中不能用Public和Private声明变量和定义符号常量;,窗体模块中不能用Public定义全局符号常量,也不能声明数组、定长字符串和用户自定义类型,它们只能在标准模块中用。,71,程序设计教程,标准模块中声明的全局变量,在其它模块中可直接使用,窗体模块声明的全局变量,其它模块采用格式:窗体名.变量名 如:Form1.X=100,与模块级变量一样,全局变量在静态存储区分配空间。,72,程序设计教程,8.7.3,生存期,生存期是指变量的存在时间,只有动态变量,生存只在过程的一次执行中,静态变量、模块级变量和全局变量的生存期将持续到整个应用程序运行结束。,73,程序设计教程,8.7.4,过程的作用域和局部变量存储类别,定义过程时,可加上作用域关键字Public或Private,可加存储类别的关键字Static。,过程定义首行格式可以写成:,Private|PublicStatic Sub 过程名(参数列表),Private|PublicStatic Function 函数名(参数列表)As 类型说明,Public:表示所有过程都可以调用该过程,定义在窗体模块中,其他模块调用时使用:,窗体名.过程名,如果定义在标准模块或本模块中,可以直接使用。,缺省Public,也没有Private关键字,则等同Public的特性。,74,程序设计教程,Private:表示该过程只能在本模块中可以调用,Static:表示过程中所有局部变量都作为静态变量。如:Static Sub Bb()Dim A As Integer A=A+1 MsgBox Bb&AEnd Sub,若Cmd1的Click中有Call Bb语句,则单击Cmd1将显示:,Bb1、Bb2、Bb3,75,程序设计教程,8.8.1,用递归实现求阶乘,递归调用是指在一个过程内直接或间接调用自己。,【例8-7】利用递归调用编写的求n!的函数Fact(n)。,求n!时,n!=n(n-1)!,(n-1)!=(n-1)(n-2)!,若知道1!=1或0!=1,则可回推可以算出n!。,在求n!时要调用Fact(n-1),产生了递归调用。,Function Fact(n As Integer)As Double If n=0 Or n=1 Then Fact=1 Else Fact=n*Fact(n-1)End IfEnd Function,8.8 程序举例,76,程序设计教程,编写递归过程,需要两个必须的条件:,形成递归式。如:Fact=n*Fact(n-1),必须有一个出口。如:If n=0 Or n=1 Then Fact=1,77,程序设计教程,8.8.2,冒泡分类法,【例8-8】实现30个数据的排序输出。要求使用冒泡分类法。其中数据排序、产生和输出分别用通用过程实现。,冒泡分类法的基本思想:大的数逐层往下沉,而小的数逐层往上浮,就气泡上浮一样。算法:,1从数组元素a(1)到a(N),将相邻的两个数两两进行比较(共比较N-1次),若前一个数大于后一个数,则进行对调。一趟操作后,a(N)已为最大数。,78,程序设计教程,2再从数组元素a(1)到a(N-1)作同样操作后,结果是a(N-1)成为次大数。,3重复以上步骤,直至只剩a(1)和a(2)作比较。,由此可见,对N个数据第1趟比较N-1次,第2趟比较N-2次,第i趟比较N-i次。共进行N-1趟比较就可以排好顺序。,79,程序设计教程,Sub OrderArray(A()As Integer)排序 Dim i As Integer,j As Integer,N As Integer,T As Integer N=UBound(A)For i=1 To N-1 开始冒泡排序,共进行n-1趟 For j=1 To N-i If A(j)A(j+1)Then T=A(j):A(j)=A(j+1):A(j+1)=T Next j Next i,End Sub,80,程序设计教程,Sub CreateArray(A()As Integer)产生数据Dim i As IntegerRandomizeFor i=1 To UBound(A)A(i)=Int(Rnd*90)+10Next I,End Sub,Sub PrintArray(A()As Integer),输出Dim i As IntegerFor i=1 To UBound(A)Print A(i);If i Mod 10=0 Then PrintNext I,End Sub,81,程序设计教程,Private Sub Command1_Click()Dim A(30)As Integer CreateArray A 产生数据 PrintArray A 输出排序前数据 OrderArray A 排序 PrintArray A 输出排序后数据End Sub,82,程序设计教程,8.8.3,标签沿窗体四周运动,【例8-9】编制动画程序:窗体上有一“OK”标签,沿窗体四周移动,标签的背景色随机改变。要求分别为标签的上下移动和左右编写过程。,因动态变化,要使用定时器控件。,将左右移动编写为一个过程,则至少必须提供一个确定运动方向的参数,如用1表示从左向右,-1从右向左。到窗体角,要改方向。,程序用Dire变量表示总方向,值03分别表示向右、向下、向左和向上运动。,使用两个定时器控制移动和背景改变,83,程序设计教程,Dim Dire As IntegerSub Left_Right(D As Integer,),实现左右移动 If Label1.Left0 And D=-1 Or Label1.Left 0 And D=-1 Or Label1.Top Form1.ScaleHeight-Label1.Height And D=1 Then,Label1.Top=Label1.Top+10*D,Else,Dire=(Dire+1)Mod 4,End If,End Sub,Private Sub Form_Load(),Label1.Caption=OK,Label1.FontSize=20,Label1.Height=Label1.Width,Timer1.Interval=20:Timer2.Interval=500,End Sub,85,程序设计教程,
展开阅读全文