完整word版计算机等级考试二级vb过程讲解.docx
《完整word版计算机等级考试二级vb过程讲解.docx》由会员分享,可在线阅读,更多相关《完整word版计算机等级考试二级vb过程讲解.docx(39页珍藏版)》请在冰豆网上搜索。
![完整word版计算机等级考试二级vb过程讲解.docx](https://file1.bdocx.com/fileroot1/2023-2/24/728d0352-6164-4182-81e0-c5b17eb372fd/728d0352-6164-4182-81e0-c5b17eb372fd1.gif)
完整word版计算机等级考试二级vb过程讲解
计算机等级考试二级vb过程讲解
第8章过程
教学要求
掌握VB的两种过程:
事件过程和通用过程
掌握Sub过程的定义
掌握Function过程的定义
掌握过程的调用
掌握参数的传递——按值传递和按地址传递
掌握递归算法
掌握变量的作用域
8.1Sub过程
8.1.1事件过程
当对象识别某事件后,进行的操作处理——以代码的形式存储在事件过程中。
分类:
窗体事件过程
控件事件过程
1定义事件过程
[形式]:
PrivateSubForm_事件名([参数列表])
[局部变量和常数声明]
语句块
EndSub
Initialize(初始化)事件——配置窗体时触发
Load(加载)事件——窗体装入内存时触发
Activate(激活)事件——窗体被激活时触发
Gotfocus事件(得到焦点)事件——窗体成为当前焦点时触发
窗体上无可视控件时,触发窗体的Gotfocus事件;
窗体上有可视控件时,触发控件的Gotfocus事件;
执行次序:
InitializeLoadActivateGotfocus
窗体的Initialize、Load事件发生在窗体被显示之前,其中可放置系统初始化命令,但其中语句有所限制;
窗体加载后,只要不被卸载,就不会再执行Initialize、Load事件,但Activate事件会多次发生;
当访问另一窗体上的“非可视”数据或调用其中定义的全局过程时,只会触发该窗体的Initialize事件,而Load事件不触发;
当访问另一窗体上的“可视”数据时,会同时触发该窗体的Initialize和Load事件;
3定义控件的事件过程
[一般形式]:
PrivateSub控件名_事件名([参数列表])
[局部变量和常数声明]
语句块
EndSub
8.1.2通用过程
完成某一特定功能的程序段
——通用过程(自定义)
必须显式调用方可执行;
分为:
公有过程(Public)
私有过程(Private)
1通用Sub过程的定义
[一般形式]:
[Private|Public][static]Sub<过程名>([<参数列表>])
<过程体>
EndSub
[说明]:
(1)以Sub开头,EndSub结束,,中间是过程体——包括变量声明和语句块;
(2)以Private为前缀的过程是模块级的,以Public为前缀的过程是应用程序级的,缺省默认是Public;
(3)Static选项说明过程中的局部变量是静态变量;
(4)过程名的命名规则和变量名相同,在同一个模块中,过程名必须是唯一的;
(5)参数列表中的参数称为形式参数,可以没有,但无参数时圆括号不能省略;有多个参数时,参数之间用逗号间隔;
(6)参数说明格式:
[Optional][ByVal|ByRef]<变量名>[()][As<数据类型>]
其中:
a)若参数是数组,则在变量名后面加一对圆括号,但无维界定义
b)ByVal:
指明参数传递方式是传值;
c)ByRef:
指明参数传递方式是传地址,为缺省值;
d)若参数是字符型的,必须是不定长字符串;
e)Optional:
参数是可选的,必须定义在必选参数后面。
(7)当过程调用结束,即执行到EndSub语句,系统自动返回调用程序的调用语句处,执行调用语句的下一条语句;
(8)过程不能嵌套定义,但可嵌套调用;
(9)ExitSub语句的功能是提前退出过程调用,返回调用语句。
例:
PrivateSubExchange(xAsInteger,yAsInteger)
DimTempAsInteger
Temp=x:
x=y:
y=Temp
EndSub
该通用过程实现交换功能,包含两个参数,均是ByRef形式的参数。
3Sub过程调用
必须在事件过程或其它通用过程中显示调用。
Sub过程调用
[格式一]:
Call<过程名>[(<实在参数表>)]
[格式二]:
<过程名>[<实在参数表>]
[功能]:
对已定义的过程进行调用。
如:
CallFact(x)
Factx
(1)调用的过程必须是已经定义的,否则系统会出现“子程序或函数未定义”的信息提示;
(2)实在参数可以是常量、变量或表达式;
(3)实在参数的数目及类型要和定义时必选参数保持一致,否则系统会出现“参数不可选”的信息提示,参数之间用逗号间隔;
(4)若子程序没有参数,则格式一中的括号可以省略;
(5)格式一和格式二的区别在于:
格式二的参数表无须括号,而是和过程名之间用空格隔开;
例8-2试编写一个找出任意一个正整数的因子的程序
OptionExplicit
PrivateSubCommand1_Click()
DimintaAsInteger,stAsString
inta=Text1
Callfactor(inta,st)
Text2=st
EndSub
PrivateSubfactor(ByValnAsInteger,sAsString)
DimiAsInteger
Fori=1Ton-1
IfnModi=0Thens=s&Str(i)
Nexti
EndSub
优点:
程序即Sub过程的使用不仅可以缩短程序的长度,还能够使程序的结构更加清楚。
例:
定义一个通用过程用以求一维数组中的最小值
PrivateSubvalue(a()AsInteger,minAsInteger)
DimiAsInteger
min=a
(1)
Fori=2ToUBound(a)
Ifa(i)Nexti
EndSub
8.2Function过程
Function过程的特点是返回一个值,因此我们通常也称之为自定义函数。
通常我们利用Function过程得到一个数值或一个字符串或一个逻辑值。
[格式]:
[Private|Public]Function<函数名>([参数列表])[As<数据类型>]
<函数体>
EndFunction
(1)以Function开头,以EndFunction结束,中间是函数体;
(2)函数名命名规则、参数列表的表示都和Sub过程相同;
(3)As数据类型:
函数过程将由函数名返回一个值,值的类型由[As数据类型]定义;★
(4)函数体中一定要有对函数名赋值的语句——函数名=表达式,否则返回相应类型的初值;★
(5)函数体内可有ExitFunction语句——无条件退出函数过程,返回主程序。
(6)Function过程不能嵌套定义,但可嵌套调用。
例:
定义函数:
PrivateFunctionf(ByValxAsInteger)AsInteger
f=3*x^3-2*x^2+6*x-1
EndFunction
例8-1:
编写一个求n!
的函数。
PrivateFunctionFact(ByvalnAsInteger)AsLong
DimKAsInteger
Fact=1
Ifn=0Orn=1Then
ExitFunction
Else
ForK=1ToN
Fact=Fact*K
NextK
EndIf
EndFunction
2调用Function过程
[格式]:
<函数名>([实在参数表])
[功能]:
返回一个函数值。
[说明]:
(1)一般情况下,函数的调用出现在赋值语句中,并且在赋值号的右侧;
(2)若函数没有参数,函数名后的括号不能省略;
(3)虽然VB允许象调用Sub过程那样调用Function过程,但这样调用时系统不返回函数值,建议大家不要使用这种调用方法。
Callfact(x)
Factx这两种方法均放弃函数的返回值
例:
用函数实现求一维数组中的最小值,对比前例(SUB)
PrivateFunctionmin(a()AsInteger)AsInteger
DimiAsInteger
min=a
(1)
Fori=2ToUBound(a)
Ifa(i)Nexti
EndSub
例:
定义函数用以判断一个数是否是素数
PrivateFunctionPrime(NAsInteger)AsBoolean
DimiAsInteger
Prime=False
Fori=2ToN-1
IfNModi=0ThenExitFor
Nexti
Ifi=NthenPrime=True
EndFunction
[例]:
S=1!
+2!
+…+10!
PrivateSubForm_Click()
DimSAsLong,iAsInteger
Fori=1To10
Nexti
Print”S=";S
EndSub
PrivateFunctionFact(nAsInteger)AsLong
DimiAsInteger
Fact=1
Fori=1Ton
Fact=Fact*i
Nexti
EndFunction
例8-3:
利用函数过程编写一个求两个正整数的最大公约数的程序
PrivateSubForm_Click()‘主调过程
DimNAsInteger,MAsInteger,GAsInteger
N=InputBox("输入N")
M=InputBox("输入M")
G=Gcd(N,M)
PrintN;"和";M;"的最大公约数是:
";G
EndSub
PrivateFunctionGcd(ByValAAsInteger,ByValBAsInteger)AsInteger
DimRAsInteger
R=AModB
DoWhileR<>0
A=B
B=R
R=AModB
Loop
Gcd=B
EndFunction
2、调用标准模块中的公有过程
[格式]:
Call[<标准模块名>.]<过程名>[(<实参表>)]
[功能]:
调用其他标准模块中定义的公有过程。
[说明]:
若公有过程唯一,则直接调用,不加模块名。
若存在同名的公有过程,则:
调用本模块中过程:
直接调用,不加模块名
调用其它模块中过程:
必须加模块名。
被调用的函数和过程必须是公有的;
函数也可以这样调用。
8.4参数的传递
8.4.1形式参数和实在参数
形式参数:
过程定义时,在过程名后面的圆括号里的一系列变量;
过程被调用执行时,系统才给形参分配存储空间;
可以是除定长字符串外的任一简单变量;
可以是数组,变量名后接括号;
简称“形参”
实在参数
主调程序中,调用语句中,出现在过程名后面圆括号里的变量,是实在参数,可以是常量、变量或表达式;
过程调用传递参数时,实参按“位置”和形参结合;
实在参数和形式参数,要求个数一样,位置对应,类型一致,否则会出错;
定长字符串变量可以作为实在参数;
简称“实参”
举例:
写出下列程序执行的结果
PrivateSubExamSub(xasinteger,yasinteger)
x=x+10:
y=y-10
EndSub
PrivateSubForm-click()
Dimxasinteger,yasinteger
x=10:
y=100
CallExamSub(y,x)
Print“x=”;x;“y=”;y
EndSub
8.4.2按值传递参数
[格式]:
ByVal<变量说明>
[传递方式]:
调用时,系统为形参分配一个临时存储单元,并将实参的值存储到该临时单元中。
若在被调用的过程体中改变了形参的值,只是改变了临时存储单元中的数据,对实参的值无任何影响。
[参数传值传递]举例:
PrivateSubForm_Click()
DimMAsInteger,NAsInteger
M=15:
N=20
CallValue_change(M,N)
Print"M=";M,"N=";N
EndSub
PrivateSubValue_change(ByValxAsInteger,ByValyAsInteger)
x=x+20
y=y+20
Print"X=";x,"Y=";y
EndSub
传值是单向的:
调用时,实参将值传递给形参,两者就无任何关联。
过程中形参的值发生变化,对实参无任何影响。
8.4.3按地址传递参数
[格式]:
ByRef<变量说明>
[传递方式]:
系统在调用执行过程时,为形参分配临时存储单元,并将实参的内存单元地址传送给形参,存储在临时存储单元中
在被调用的过程体中一切对形参的操作,都是直接对地址保存在形参中的内存单元中的数据进行的,而实参就是保存在此内存单元中的数据,所以任何对形参的操作也就是对实参的操作;
按地址传递时,形式参数和实在参数共用同一“内存单元”。
[参数传址传递]举例:
(对比前例)
PrivateSubForm_Click()
DimMAsInteger,NAsInteger
M=15:
N=20
CallValue(M,N)
Print"M=";M,"N=";N
EndSub
PrivateSubValue(xAsInteger,yAsInteger)
x=x+20
y=y+20
Print"X=";x,"Y=";y
EndSub
传地址是双向的:
举例:
计算5!
+4!
+3!
+2!
+1!
PrivateSubForm_Click()
DimSumAsInteger,IAsInteger
ForI=5To1Step-1
Sum=Sum+Fact(I)
NextI
Print"Sum=";Sum
EndSub
PrivateFunctionFact(nAsInteger)AsInteger
Fact=1
DoWhilen>0
Fact=Fact*n
n=n-1
Loop
EndFunction
将传地址修改为传值的方式为:
方法一:
在形参n前加ByVal
方法二:
将调用语句中fact(i)改为fact((i))
参数有两种传递方式:
传值(ByVal)和传地址(ByRef)。
若调用时实参为常量或表达式,这两种方式没有区别,无论形参定义的是按值传递还是按地址传递,系统都是按传值方式传递
系统在调用时为形参分配一个临时存储单元,将表达式的值计算出来,存储到该临时单元;调用结束,系统收回临时单元。
调用函数或过程时,将单个变量转换成表达式的方法:
将变量放在一对括号中。
如用Fact((I))的方式调用函数,系统会按传值来处理。
按地址传递时,当实参是变量时,实参与形参必须类型完全一致;
按地址传递时,当实参是常量或表达式时,VB会自动进行类型转换,然后再传递相应的值(即类型无须完全一致);
在算术表达式中,函数的优先级最高,若表达式中有函数的实参,而函数的参数又是按地址传递的,则函数中有可能改变了实参的值,即改变了表达式中变量的值,会引起混淆。
PrivateSubForm_Click()
DimSAsSingle
S=125.5
CallConvert((S),”12”+”.5”)
EndSub
PrivateSubConvert(InxAsInteger,SingAsSingle)
Inx=Inx*2
Sing=Sing+23
Print“Inx=”;Inx,”Sing=”;Sing
EndSub
8.4.4数组参数
VB允许把数组作为形式参数,声明数组的格式是:
<数组名>()As<数据类型>
[注意]:
(1)数组参数只能按地址传递,即不能用ByVal来修饰数组参数
(2)定义数组参数时无须说明数组的维数和下标变化范围;
(3)调用过程时,对应的实在参数也必须是数组,但只需要数组名,无须后跟括号,且数据类型也要一致。
`
(4)在过程体或函数体中无须对数组参数再次说明;
(5)若实参是动态数组,在过程体或函数体中可以使用重定义语句修改数组的维界;
举例
PrivateSubForm_Click()
Dima()AsInteger,iAsInteger
DimnAsInteger
n=InputBox("请输入数组的初始大小")
ReDima(n)
Fori=1Ton
a(i)=i
Nexti
CallPrintArray(a)
CallArray1(a)
CallPrintArray(a)
EndSub
PrivateSubPrintArray(x()AsInteger)
DimiAsInteger
Fori=LBound(x)ToUBound(x)
Printx(i);
Nexti
Print
EndSub
PrivateSubArray1(a()AsInteger)
DimmAsInteger,nAsInteger
n=UBound(a)
m=InputBox("请输入新大小")
ReDimPreservea(m)
DimiAsInteger
Fori=n+1Tom
a(i)=0
Nexti
EndSub
输入5和8,程序执行结果为:
举例:
自定义一个将一维数组按从小到大排序的通用过程
PrivateSubCommand1_Click()
DimiAsInteger,jAsInteger
Dima(10)AsInteger
Fori=1To10
a(i)=Int(8*Rnd)
Picture1.Printa(i);
Nexti
Callsort(a)
Fori=1To10
Picture2.Printa(i);
Nexti
EndSub
PrivateSubsort(a()AsInteger)
DimiAsInteger,jAsInteger
Fori=1ToUBound(a)-1
Forj=i+1ToUBound(a)
Ifa(i)>a(j)Then
temp=a(i)
a(i)=a(j)
a(j)=temp
EndIf
Nextj
Nexti
EndSub
本程序的功能是找出100~200之间的所有素数。
PrivateSubForm_Click()
DimiAsInteger,xAsInteger
Fori=100To200
Ifprime(i)ThenPrinti
Nexti
EndSub
PrivateFunctionprime(byvalnasinteger)AsBoolean
DimiAsInteger
Fori=2ToSqr(n)
IfnModi=0Then
Nexti
prime=True
EndFunction
8.5递归过程
所谓递归,就是在过程定义中,调用过程本身。
例:
使用递归函数求N!
。
[提示]:
N!
=N*(N-1)!
PrivateSubForm_Click()
DimnAsInteger
n=InputBox("输入一个正整数")
Printn;"!
=";fact(n)
EndSub
PrivateFunctionfact(ByValnAsInteger)AsLong
Ifn=1Then
fact=1
Else
fact=n*fact(n-1)
EndIf
EndFunction
总结:
使用递归算法,最重要的是要有一个结束递归的条件,可以使递归得以返回,即终止条件或边界条件。
例:
使用递归算法计算裴波拉挈数列。
PrivateSubForm_Click()
DimnAsInteger
n=InputBox("求数列的第几项")
Print“数列中第”;n;“项是”;Cal(n)
EndSub
PrivateFunctionCal(nAsInteger)
Ifn=1Orn=2Then
Cal=1
Else
Cal=Cal(n-1)+Cal(n-2)
EndIf
EndFunction
递推法:
利用未知项与已知项之间存在的某种关系,从已知项逐项推出未知项的方法。
PrivateSubForm_Click()
Dimfb()AsInteger
DimiAsInteger,,nasinteger
n=InputBox(“求数列中第几项的值”)
Redimfb(n)
fb
(1)=1:
fb
(2)=1
Fori=3Ton
fb(i)=fb(I-1)+fb(I-2)
Nexti
Print"数列中的第";n;"项是";fb(n)
EndSub
[例8-9]:
编写一个递归函数,求任意两个整数的最大公约数。
PrivateSubCommand1_Click()
DimGcdvalueAsLong,MAsLong,NAsLong
IfM<>0AndN<>0Then
Gcdvalue=Gcd(M,N)
Text3.Text=CStr(Gcdvalue)
EndIf
EndSub
PrivateFunctionGcd(ByValXAsLong,ByValYAsLong)
DimRAsLong
R=XModY
IfR=0Then
Gcd=Y
Else
X=Y:
Y=