第6章过程本章内容6.1过程概述6.2Sub过程6.3Function过程6.4参数传递6.5过程的递归6.6变量的作用域6.7过程的作用域6.1过程概述(1)1.过程的概念及优点过程是完成一定任务的一个VisualBasic语句块优点:过程允许将程序分为不连续的逻辑单元避免代码重复问题2.过程的调用从代码中的其他某处调用过程,称为过程调用6.1过程概述(2)3.参数调用过程时,过程需要处理不同的数据。将这些信息作为过程调用的一部分传递给过程,这些信息就称之为参数。过程可以定义零个或多个参数,而每个参数都代表过程希望传递给它的一个值。4.过程的类型Sub过程事件处理过程Property过程Function过程6.2Sub过程(1)6.2.1事件过程控件事件过程的格式为[Private|public]Sub控件名_事件名(参数表)语句组EndSub窗体事件过程的格式为[Private|public]SubForm_事件名(参数表)语句组EndSub6.2Sub过程(2)例如:PrivateSubCommand1_Click()PrintHelloEndSubPrivateSubForm_Load()Command1.Caption=HelloEndSub说明:事件过程只能放在窗体模块中。语句组为处理事件而编写的程序代码。可以通过双击对象,然后再在代码视图下选择相应事件的方法来自动生成事件过程。6.2Sub过程(3)6.2.2自定义Sub过程Sub过程的定义格式如下:[Public|Private]Sub过程名([形式参数])语句块ExitSub语句块EndSub例如:PublicSubMax(xAsInteger,yAsInteger)DimcAsIntegerIfxyThenc=xElsec=yEndIfPrintcEndSub6.2Sub过程(4)说明:Public和Private表明Sub过程的有效范围,Public的有效范围为整个工程,Private的有效范围为当前模块,默认为Private。过程名必须符合变量的命名规则。过程必须以EndSub结束。可以根据实际情况选择形式参数的类型和个数,当过程无形式参数时,括号不能省略。使用ExitSub语句可以强制退出过程。图6-1添加过程对话框在VisualBasic中所有的过程都是并列关系,不允许在一个子过程内部再定义一个子过程。6.2Sub过程(5)6.2.3过程的调用调用方式:Call过程名([实际参数列表])过程名[实际参数列表]例如:SubArea(rAsSingle)DimsAsSingles=3.14*r*rMsgBoxarea=&sEndSubPrivateSubForm_Click()DimaAsSinglea=Val(InputBox(输入一个半径))CallArea(a)EndSub6.2Sub过程(6)说明:在调用过程时,实际参数一定要和形式参数在类型和个数上匹配。在使用Call调用过程时,一定要用括号将实际参括起来,除非没有参数。通过过程名直接调用过程时,一定要去掉参数两边的括号,通过空格字符将过程名与参数分隔开。实际参数可以是变量、常量、表达式或数组。在调用过程时,一定要注意不要形成循环调用,即避免定义A过程时,调用了B过程,而定义B过程时,又调用了A过程。6.3Function过程(1)6.3.1Function过程的定义定义格式如下:[Public|Private]Function过程名([形式参数])[As类型]语句块ExitFunction语句块过程名=返回值EndFunction例如:PublicFunctionMax(aAsInteger,bAsInteger)AsIntegerDimcAsIntegerIfabThenc=aElsec=bEndIfMax=c'将最大值返回EndFunction6.3Function过程(2)说明:过程名必须符合变量的命名规则,同时不能与系统函数或其他过程同名。“As类型”表示Function过程的返回值类型,如果省略表示返回值类型位变体类型(Variant)。可以通过ExitFunction强制退出Function过程。Function过程通过过程名称将返回值返回。Function过程的实际返回值的类型应该与定义的返回值类型一致。6.3Function过程(3)6.3.2Function过程的调用调用格式如下:过程名([实际参数列表])【例6.1】编写程序计算1!+2!+3!+…+m!,其中m由用户通过文本框输入6.4参数传递(1)6.4.1参数传递1.值传递在形式参数前面加上ByVal关键字,按值传递过程内对参数的值进行了修改,调用完成后将不会影响到实际参数的值2.地址传递默认传递方式为地址传递或者加上ByRef关键字双向传递,过程内对参数的修改,影响实参的值如果实际参数是常量或表达式时,无论形式参数定义为值传递还是地址传递,此时,都将按值传递将常量或表达式的值传递给被调用的过程。6.4参数传递(2)【例6.2】编写程序,试验参数的值传递和地址传递。程序代码如下:'形式参数m定义为地址传递,形式参数定义为值传递SubAdd(mAsInteger,ByValnAsInteger)m=m+10n=n+10EndSubPrivateSubForm_Click()DimaAsIntegerDimbAsIntegera=10b=10Print调用前a=;a,b=;bAdda,bPrint调用后a=;a,b=;bEndSub6.4参数传递(3)6.4.2数组参数注意以下几点:为了把一个数组的全部元素传递给一个过程,应将数组名分别写入形式参数和实际参数列表中,并略去数组的上下界,但括号不能省略实际参数也应该是数组,且类型应该与形式参数的数组类型一致数组作为参数时,按地址传递的方式将数组传递给过程数组作为参数时,数组的上下界可以通过UBound和LBound函数获取在使用数组参数调用过程时,作为实际参数的数组的大小可以任意定义6.4参数传递(4)【例6.3】编写过程实现数组的生成、首尾对调和输出功能6.4参数传递(5)6.4.3可选参数如果需要将某个参数设置为可选参数,必须在该参数前加Optional关键字FunctionMax(aAsInteger,bAsInteger,OptionalcAsInteger)DimmAsIntegerIfabThenm=aElsem=bEndIfIfNotIsMissing(c)ThenIfmcThenm=cEndIfEndIfMax=mEndFunction6.4参数传递(6)说明:一个过程允许定义多个可选参数,所有可选参数必须位于所有参数的最后。可以通过IsMissing函数检测可选参数是否被省略,如果省略IsMissing函数的结果为True,否则为False。如果需要为可选参数加上默认值,需要在定义参数时在后面直接加上“=值”的方式即可。具有可选参数的过程在被调用时,可选参数可以根据情况选择是否输入,如上例中的Max过程通过d=Max(5,9)调用,也可以通过d=Max(5,9,11)调用。6.5过程的递归(1)找出过程参数为n和过程参数为n−1之间的规律【例6.4】利用递归过程,计算n!【例6.5】猴子吃桃问题:猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多吃了一个第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一天剩下的一半零一个。到第10天早上想再吃时,见只剩下一个桃子了。求第一天共摘了多少。6.6变量的作用域(1)6.6.1过程变量程变量的定义格式为Dim|Static变量名[As类型]例如:DimaAsInteger注意:一个过程变量的值无法被另外一个过程访问在不同的过程内可以使用相同的过程变量名例如:Subt1()DimaAsIntegera=5EndSubSubt2()PrintaEndSub6.6变量的作用域(2)6.6.2模块级变量定义格式为Private|Dim变量名[As类型]定义位置:窗体模块或标准模块的声明部分有效范围当前模块6.6变量的作用域(3)6.6.3全局变量全局变量的定义格式为:Public变量名[As类型]例如:PublicnAsInteger有效范围整个工程注意:标准模块声明的全局变量,在其他模块可直接通过变量名访问在窗体模块中声明的全局变量,在其他模块中需要通过“窗体名.全局变量名”的方式访问6.6变量的作用域(4)6.6.4变量的同名问题1.作用域不同的变量同名如果两个同名的变量的作用域不同,在变量访问时,优先访问作用域较小的变量如果全局变量与模块级变量或是过程变量同名,需要访问全局变量时,可以通过“模块名.全局变量名”的方式访问2.全局变量同名如果不同模块的两个全局变量同名,可以通过“模块名.全局变量名”的方式访问这两个全局变量6.6变量的作用域(5)6.6.5静态变量定义格式为Static变量名[As类型]退出过程时,变量所占的内存单元不被释放例如:PrivateSubForm_Click()StaticaAsInteger'定义静态过程变量aDimbAsInteger'定义普通过程变量ba=a+10b=b+10Printa=;a,b=;bEndSub6.7过程的作用域1.模块级过程在过程前面使用Private关键字,即可将一个过程定义为模块级过程有效范围:当前模块2.全局过程过程前不使用Private关键字或在过程前面使用Public关键字均表示该过程为全局过程