第八章子过程和函数过程_第1页
第八章子过程和函数过程_第2页
第八章子过程和函数过程_第3页
第八章子过程和函数过程_第4页
第八章子过程和函数过程_第5页
已阅读5页,还剩69页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第八章Sub子过程和Function函数过程本章内容及要求8.1Sub过程的定义和调用8.2Function函数过程的定义和调用8.3参数传递8.4过程的嵌套和递归调用8.5变量及过程的作用域

(1)窗体事件过程PrivateSubForm_事件名(参数列表)<语句组>EndSub

(2)控件事件过程PrivateSub

控件名_事件名(参数列表)<语句组>

EndSub8.1.1事件Sub过程8.1Sub子过程的定义和调用在VB中Sub子过程分为:事件过程和用户自定义过程方法一:通过“工具”菜单中的“添加过程”命令,出现“添加过程”对话框,选择过程类型(子过程、函数、属性、事件)及作用范围(公有的Public、私有的Private),单击确定后得到一个过程定义的结构框架(模板),如:Sub子过程的定义----两种方法8.1.2用户自定义Sub子过程定义PublicSub

Sort()

……EndSub[Public|Private][Static]Sub子过程名([形参表])<局部变量或常数定义>

<语句组>

[ExitSub]

<语句组>EndSub

方法二:直接在代码窗口中输入过程体例1:编一个交换两个整型变量值的子过程。PrivateSubSwap(XAsInteger,YAsInteger)

DimtempAsInteger

Temp=XX=YY=TempEndSub例2:编写求阶乘的子过程。Privatesubfact(nAsInteger,fasDouble)DimiAsIntegerf=1Fori=1Tonf=f*iNextEndsub。说明:(1)子过程名:命名规则与变量名规则相同。子过程名不返回值,而是通过形参与实参的传递得到结果,调用时可返回多个值(2)形式参数列表:形式参数通常简称“形参”,仅表示形参的类型、个数、位置,定义时是无值的,只有在过程被调用时,虚实参结合后才获得相应的值。(3)过程可以无形式参数,但括号不能省。(4)参数的定义形式:[ByVal|ByRef]变量名[()][As类型][,…]ByVal表示当该过程被调用时,参数是按值传递的;ByRef表示当该过程被调用时,参数是按地址传递的,缺省时传址。方法一:Call子过程名(参数列表)方法二:子过程名[参数列表]说明:

(1)参数列表称为实参或实元,它必须与形参保持个数相同,位置与类型一一对应。

(2)调用时把实参值传递给对应的形参。其中值传递(形参前有ByVal说明)时实参的值不随形参的值变化而改变。而地址传递时实参的值随形参值的改变而改变。8.1.3子过程的调用(3)当参数是数组时,形参与实参在参数声明时应省略其维数,但括号不能省。

(4)调用子过程的形式有两种,用Call关键字时,实参必须加圆括号括起,反之则不用加圆括号括起。实参之间用“,”分隔。例:调用上面定义的Swap子过程的形式:

Swapa,bCallSwap(a,b)在某个事件过程中调用已定义的阶乘的过程fact:PrivateSubCommand1_Click()DimnAsInteger,mAsLongn=5Callfact(n,m)PrintmEndSubPrivateSubCmdOK_click()……CallSwap(a,b)……Swapa,bEndSubPrivateSubSwap(x%,y%)Dimtemp%Temp=XX=YY=TempEndSub

过程调用的执行过程:

VisualBasic函数分为内部函数和外部(自定义)函数,外部函数是用户根据需要用Function关键字定义的函数过程,与子过程不同的是函数名将返回一个值。

8.2Function函数过程的定义和调用方法一:通过“工具”菜单中的“添加过程”命令,出现“添加过程”对话框,选择过程类型(子过程、函数、属性、事件)及作用范围(公有的Public、私有的Private),单击确定后得到一个函数定义的结构框架(模板),如:PublicFunction

Sort()

……EndFunction8.2.1Function函数过程的定义Function函数过程过程的定义----两种方法[Public|Private][Static]Function函数名([<参数列表>])[As<类型>]<局部变量或常数定义><语句块>[函数名=返回值][ExitFunction]<语句块>[函数名=返回值]EndFunction方法二:直接在代码窗口中输入函数体Functionfact(nAsInteger)AsDoubleDimiAsInteger,fAsDoublef=1Fori=1Tonf=f*iNext

fact=fEndFunction把例2阶乘的sub子过程改为Function函数过程说明:(1)函数名:命名规则与变量名规则相同。但不能与系统的内部函数或其它通用子过程同名,也不能与已定义的全局变量和本模块中模块级变量同名。(2)在函数体内,函数名可以当变量使用,函数的返回值就是通过对函数名的赋值语句来实现的,在函数过程中至少要对函数名赋值一次。(3)AS类型:是指函数返回值的类型,若省略,则函数返回变体类型值(Variant)。(4)ExitFunction:表示退出函数过程,常常是与选择结构(If或SelectCase语句)联用,即当满足一定条件时,退出函数过程。(5)形参数列表:形参的定义与子过程完全相同。调用形式如下:

函数名(实参列表)说明:在调用时实参和形参的数据类型、顺序、个数必须匹配。函数调用只能出现在表达式中,其功能是求得函数的返回值。8.2.2函数过程的调用调用阶乘的过程:PrivateSubCommand1_Click()DimSAsIntegerS=5Printfact(S)EndSub2009-03-29以下关于过程及过程参数的描述中,错误的是A)过程的参数可以是控件名称

B)调用过程时使用的实参的个数应与过程形参的个数相同

C)只有函数过程能够将过程中处理的信息返回到调用程中

D)窗体可以作为过程的参数课堂练习2010-03-22下面是求最大公约数的函数的首部Functiongcd(ByValxAsInteger,ByValyAsInteger)AsInteger若要输出8、12、16这3个数的最大公约数,下面正确的语句是

A)Printgcd(8,12),gcd(12,16),gcd(16,8)

B)Printgcd(8,12,16)

C)Printgcd(8),gcd(12),gcd(16)

D)Printgcd(8,gcd(12,16))VisualBasic中不同模块(过程)之间数据的传递有两种方式:

通过过程调用实参与形参的结合实现;使用全局变量来实现各过程中共享数据。

1、形式参数

是指在定义子过程和函数时,出现在Sub过程名或Function函数名后面括号内的变量,是用来接收传送给Sub过程或Function的数据,形参表中的各个变量之间用逗号分隔。8.3参数传递8.3.1形式参数与实际参数2、实际参数实际参数是指在调用Sub或Function时,出现在子过程名或函数名后括号内的参数,其作用是将它们的数据(数值或地址)传送给Sub或Function过程与其对应的形参变量。实参可由常量、表达式、有效的变量名、数组名(如A())组成,实参表中各参数用逗号分隔。

参数传递指主调过程的实参(调用时已有确定值和内存地址的参数)传递给被调过程的形参。参数的传递有两种方式:按值传递、按地址传递。形参前加“ByVal”关键字的是按值传递,缺省或加“ByRef”关键字则按地址传递。8.3.2传地址与传值传址:形参得到的是实参的地址,当形参值的改变同时也改变实参的值。因为它们共用一个地址。传值:形参只得到的是实参的值,形参值的改变不会影响实参的值。因为形参并不知道实参的地址。SubSwap2(x%,y%)DimTemp%Temp=x:x=y:y=TempEndSubSubSwap1(ByValx%,ByValy%)DimTemp%Temp=x:x=y:y=TempEndSub什么是传址和传值呢?传值传址传值PrivateSubCmdOK_Click()Dima%,b%a=10:b=20

Swap1a,b‘传值

Print"A1=";a,"B1=";ba=10:b=20

Swap2a,b'传地址

Print"A2=";a,"B2=";bEndSubSubSwap2(x%,y%)DimTemp%Temp=x:x=y:y=TempEndSubSubSwap1(ByValx%,ByValy%)DimTemp%Temp=x:x=y:y=TempEndSub值传递的执行过程如下图:通过地址传递数据的执行过程

在子过程和函数过程调用时,如果实参是常量(包括系统常量、用Const自定义的符号常量)或表达式,无论在定义时使用值传递还是地址传递,此时都是按值传递方式将常量或表达式计算的值传递给形参变量。如果形参定义是按传地址方式,但调用时想使实参变量按值方式传递,可以把实参变量加上括号,将其转换成表达式即可。

8.3.3有关过程之间数据传递的几点说明

解决一个问题既可以使用子过程,也可以使用函数过程,是使用子过程还是使用函数过程呢?如果是需要求得一个值,一般情况使用函数过程,如不是为了求一个值,而是完成一些操作,或需要返回多个值,则使用子过程比较方便。使用子过程还是使用函数过程?

VisualBasic中数组作参数是通过传地址方式传送。在传送数组时,除遵守参数传送的一般规则外,还应注意以下几点:

1.为了把一个数组的全部元素传送给一个过程,应将数组名写入形参表中,并略去数组的上下界,但括号不能省略。PrivateSubSort(a()Assingle)

……EndSub其中形参“a()”即为数组。8.3.4数组作为过程的参数2.被调过程可通过Lbound和Ubound函数确定实参数组的上、下界。3.当用数组作形参时,对应的实参必须也是数组,且类型一致。4.实参和形参结合是按地址传递,即形参数组和实参数组共用一段内存单元。例如:定义了实参数组b(1to8),给它们赋了值,调用Sort()函数过程的形式如下:Sortb()或CallSort(b())实参数组后面的括号可以省略,但为便于阅读,建议一般不要省略为好。课堂练习FunctionFirProc(zAsInteger,yAsInteger,zAsInteger)

FirProc=2x+y+3z

EndFunction

FunctionSecProc(xAsInteger,yAsInteger,zAsInteger)

SecProc=FirProc(x,y,z)+x

EndFunction

PrivateSubCommand1_Click()

DimaAsInteger,bAsInteger,cAsInteger

a=2:b=3:c=4

PrintSecProc(c,b,a)

EndSub

A)21B)19C)17D)34

课堂练习2010-9-22以下关于局部变量的叙述中错误的是A)在过程中用Dim语句或Static语句声明的变量是局部变量B)局部变量的作用域是它所在的过程C)在过程中用Static语句声明的变量是静态局部变量D)过程执行完毕,该过程中用Dim或Static语句声明的变量即被释放课堂练习下列程序的输出结果是10110。PrivateSubsub1(ByValaAsInteger,bAsInteger) a=a+b:b=b+aEndSubPrivateSubForm_Click() DimxAsInteger,yAsInteger x=10:y=20 Callsub1(x,y) sub1x,y Printx;yEndSub过程的嵌套:类似选择结构和循环结构的嵌套。也就是指一个过程中包含了另一个过程的调用。

8.4.1过程的嵌套8.4过程的嵌套和递归调用Subform_click()…Callsub1…EndsubSubsub1…Y=F1(n)…EndsubFunctionF1(x)…F1=….…EndFunction过程的递归:简单说就是自己调用自己。

8.4.2过程的递归Functionfact(n%)AsDoubleDimiAsInteger,fAsDoublef=1Fori=1Tonf=f*iNext

fact=fEndFunctionFunctionfact(n%)AsDoubleIfn=1thenfact=1elsefact=n*fact(n-1)EndFunction用递归实现阶乘不用递归实现阶乘Functionfact(n%)AsDoubleIfn=1thenfact=1elsefact=n*fact(n-1)EndFunction现在假N=4,观察执行过程Fact(4)=4*fact(3)Fact(3)=3*fact(2)Fact(2)=2*fact(1)Fact(1)=1Fact(2)=2*1Fact(3)=3*2Fact(4)=4*6注意VB语言不允许过程的嵌套定义,即一个过程内不能包含另一个过程.VB语言允许过程的嵌套调用,即在调用一个过程的过程中,又调用另一个过程.窗体模块:文件扩展名为.frm

窗体模块是VB程序的基础,与窗体对应,存放着该窗体的所有信息,如窗体及其上各控件对象的界面信息、属性、事件过程、通用过程、变量和常量的声明等。可以通过记事本打开查看。8.5.1窗体模块和标准模块8.5变量及过程的作用域标准模块:文件扩展名为.Bas

它们可以包含变量、常数、类型、外部过程和全局过程的全局(在整个应用程序范围内有效的)声明或模块级声明。写入标准模块的代码不必绑在特定的应用程序上,则在许多不同的应用程序中可以重用标准模块。当一个过程要被多个不同对象或不同模块中的程序调用时,那么该过程一般可放在标准模块中。

在VB中,由于可以在过程中和模块中声明变量,根据定义变量的位置和定义变量的语句不同,变量可以分为:局部变量(过程级变量)窗体/模块级变量(私有的模块级变量,能被本模块的所有过程和函数使用)全局级变量(公有的模块级变量)。8.5.2变量的作用域关于变量的生存期变量的生存期:是指变量的值能够保留多长时间,即分配给变量的存储空间能够被保留多长时间。1、局部变量Dim声明的局部变量在本过程执行期间有效Static声明的局部变量在整个应用程序运行期间有效2、模块变量在整个应用程序运行期间有效3、全局变量在整个应用程序运行期间有效局部变量:在过程内声明的变量,只能在本过程中使用。

在过程内部使用Dim或者Static关键字来声明的变量,只在声明它们的过程中才能被访问或改变该变量的值,别的过程不可访问。所以可以在不同的过程中声明相同名字的局部变量而互不影响。8.5.2.1局部变量—过程级变量例:PrivateSubForm_Load()Dimn%n=10EndSubPrivateSubFrom_Click()

Dimn%Print“n=“;nEndSub程序运行后单击窗体,其输出结果是什么?局部变量局部变量

窗体/模块级变量:在“通用声明”段中用Dim语句或用Private语句声明的变量,可被本窗体/模块的任何过程访问。但其他模块却不能访问该变量。例如:在“通用声明”段声明如下变量

PrivatesAsStringDimaAsInteger,bAsSingle8.5.2.2窗体模块级变量

全局变量也称公有的模块级变量,在窗体模块或标准模块的顶部的“通用”声明段用Public关键字声明,它的作用范围是整个应用程序,即可被本应用程序的任何过程或函数访问。例如:

PublicaAsInteger,bAssingle8.5.2.3全局级变量3种变量声明及使用规则如下表:全局变量与局部变量同名在不同过程中定义同名变量,它们互不影响,但若在一过程中定义使用了与全局变量同名的变量,则就应注意。

注意:当变量名相同而作用域不同时,将优先访问作用域小的变量。8.5.2.4关于多个变量同名小PublicxAsInteger'定义全局变量PrivateSubForm_Load()

x=1'将全局变量x的值设置成

1EndSubPrivateSubCommand1_Click()DimxAsInteger'定义局部变量

x=2'将局部变量x的值设置成

2Print“x=";x

Print“x=";Form1.xEndSubPrivateSubCommand2_Click()Print“x=";x

EndSub窗体将输出什么?全局变量与全局变量同名如果不同模块中的全局变量使用同一名字,则通过同时引用模块名和变量名就可以在代码中区分它们。例如,如果有一个在Form1和Module1中都声明了公用的Integer变量X,则把它们作为Module1.X

和Form1.X

来引用便得到正确值。也就是说如果不同模块中的全局变量使用同一名字,引用时就需要使用“模块名.变量名”的形式来区分它们。每次调用过程时重新分配存贮单元,初始化变量过程调用结束后释放存贮单元,变量内容自动消失动态变量与静态变量动态变量第一次调用过程时分配存贮单元,初始化变量以后每次调用过程时不再重新分配存贮单元,变量保持上次调用结束时的值过程名前加Static,表示该过程内的局部变量都是静态变量静态变量(由static定义)[Public|Private]Sub子过程名([形式参数列表])……EndSubSub过程和Function函数既可写在窗体模块中也可写在标准模块中,在定义时可选用关键字Private(局部)和Public(全局),来决定它们能被调用的范围。8.5.3过程与函数的作用域1、窗体/模块级过程:

加Private关键字的过程,只能被定义的窗体或模块中的过程调用。2、全局级过程:

加Public关键字(或缺省)的过程,可供该应用程序的所有窗体和所有标准模块中的过程调用。按过程的作用范围来划分,过程可分为:

模块级过程

全局级过程总结归纳过程的定义及作用域如下表后面的内容请课后阅读8.7过程的嵌套和递归调用8.7.1过程的嵌套

在程序中调用一子过程,而在子过程中又调用另外的子过程,这种程序结构称为过程的嵌套。过程的嵌套调用执行过程如下图:8.7.2过程的递归调用用自身的结构来描述自身,称递归。例如,对阶乘的定义:VisualBasic允许在一个Sub子过程和Function过程的定义内部调用自己,即递归Sub子过程和递归Function函数。例编求阶乘fac(n)=n!的递归函数PrivateFunctionfac(nAsInteger)AsIntegerIfn=1Then fac=1Else fac=n*fac(n-1)EndIfEndFunctionPrivateSubForm_Click() Print“fac(4)=”;fac(4)EndSub程序的递归过程:说明:递归处理一般用栈来实现,分递推和回归两个过程,如上图所示。递推过程:每调用一次自身,把当前参数(形参、局部变量、返回地址等)压入栈,直到递归结束条件成立。回归过程:然后从栈中弹出当前参数,直到栈空。递归算法设计简单,解决同一问题,使用递归算法消耗的机时和占据的内存空间要比使用非递归算法大。使用递归算法必须要满足以下的递归条件:(1)存在递归结束条件及结束时的值;(2)能用递归形式表示,且递归向终止条件发展。*8.8过程的可选参数与不定数量参数8.8.1可选参数(Optional)概念:当然用户在自定义子过程或函数时也可以定义可选参数。要指定某个形参为可选参数,这就是在形参变量前加入Optional关键字即可。如果一个过程某个形参为可选参数,则在调用此过程时可以不提供对应于这个形参的实参,若一个过程有多个形参,当它的一个形参被设定为可选参数,则这个参数之后面的其它参数也必是可选的,并且要用Optional关键字来声明。例可选参数的使用PrivateSubNadres(xAsString,OptionalyAsString)Text1.text=xText2.text=yEndSub

PrivateSubCommand1_Click()DimstrNameAsStringDimstrAddressAsStringstrName="张玉"strAddress="杭州市学院路85号"‘提供了两个参数。

CallNadres(strName,strAddress)

EndSub说明:1、

检测可选参数是否被省略使用VB的内部函数IsMissing(可选参数名)来测试过程被调用时,某个参数是否被省略。如果可选参数被省略了,则返回True,未省略,返回False。注意:若可选参数是其它类型,则IsMissing()总是返回False,不能起到检测的作用。例:PrivateSubNadres(xAsString,OptionalyAsVariant)Text1.Text=xIfNotIsMissing(y)ThenText2.Text=yEndIfEndSub2.指定可选参数的缺省值

也可以给可选参数指定缺省值。在下例中,如果未将可选参数传递到函数过程,则返回一个缺省值。SubNadres(xAsString,OptionalyAsString="杭州市学院路85号")Text1.text=xText2.text=yEndSub

PrivateSubCommand1_Click()DimstrNameAsStringstrName="张玉"

'未提供第二个参数。

CallNadres(strName)EndSub8.8.2使用不定数量的参数一般说来,过程调用中的参数个数应等于过程说明的参数个数。可用ParamArray

关键字指明,过程将接受任意个数的参数。

其定义形式如下:Sub过程名(ParamArray数组名())Function函数名(ParamArray数组名())As数据类型8.9应用举例8.9.1查找问题例

使用顺序查找法,在一组数中查找某给定的数x算法设计:设一组数据存放在数组a(1)---a(n)中,待查找的数据放在x中,把x与a数组中的元素从头到尾一一进行比较查找。用变量p表示a数组元素下标,p初值为1,使x与a(p)比较,如果x不等于a(p),则使p=p+1,不断重复这个过程;一旦x等于a(p)则退出循环;另外,如果p大于数组长度,循环也应该停止,则可由以下语句来实现它。ForP=1tonIFa(p)=xthenExitForNext

下面编写一查找函数Find(),若找到x则返回下标值,找不到返回0PrivateFunctionFind(a()AsSingle,xAsSingle)AsIntegerDimn%,p%,m%m=Lbound(a)n=Ubound(a)ForP=mtonIFa(p)=xthenExitForNextIfp>nthenp=0Find=pEndFunction例

使用折半查找法,在一批有序数列中查找给定的数x。分析:设n个有序数(从小到大)存放在数组a(1)----a(n)中,要查找的数为x。用变量bot、top、mid分别表示查找数据范围的底部(数组下界)、顶部(数组的上界)和中间,mid=(top+bot)/2,折半查找的算法如下:(1)x=a(mid),则已找到退出循环,否则进行下面的判断;(2)x<a(mid),x必定落在bot和mid-1的范围之内,即top=mid-1;(3)x>a(mid),x必定落在mid+1和top的范围之内,即bot=mid+1;(4)在确定了新的查找范围后,重复进行以上比较,直到找到或者bot<=top。8.9.2插入问题例

把一个给定数插到有序数列中,插入后数列仍然有序分析:设n个有序数(从小到大)存放在数组a(1)—a(n)中,要插入的数x。首先确定x插在数组中的位置p;(可由以下语句实现)ReDimPreservea(n+1)

'让数组长度增加1,以便存放插入的数p=1dowhilex>a(p)andp<=np=p+1loopa(p)—a(n)元素向后顺移一个位置以空出a(p)元素放入x。(可由以下语句实现)fori=ntopstep-1a(i+1)=a(i)nextia(p)=x将其写成一插入函数如下:PrivateSubInstert(a()AsSingle,xAsSingle)Dimp%,n%,i%n=UBound(a)ReDimPreservea(n+1)'让数组长度增加1,以便存放插入的数

p=LBound(a)DoWhilex>

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论