版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章过程在一个程序中,如果需要在多处执行完成同一功能的程序段,那么,重复书写一相同的程序段,是一项相当繁琐且容易出错的工作。能否对这样的程序段只书写一次而又多次调用呢?VisualBasic提供了设计过程和自定义函数的功能,利用过程和自定义函数就能满足以上的需要。把需要在多处重复使用的程序段编写成一个相对独立的程序模块,这个程序模块就称为过程或自定义函数。这样,在一个程序中,需要完成这个程序模块功能的地方就不用再重复编制程序了,而是通过调用该过程或用户自定义函数来完成,这就是“结构化”程序设计的思想。
结构化程序设计思想的重点之一就是对一个复杂的问题采用“分而治之”的策略—模块化,把一个较大的程序划分为若干个模块,每个模块只完成一个或若干个功能。使用“过程”是实现结构化程序设计思想的重要方法。。
【主要内容】本章要求用户重点掌握以下内容。Sub过程和Function过程的定义格式。Sub过程和Function过程的调用。重点掌握Sub过程和Function过程中参数的传递方式,掌握值传递和地址传递的区别,并能灵活应用。了解Shell函数的使用。
7.1引例【引例】在名称为Form1的窗体画两个名称分别为Command1和Command2,外观属性分别为“输入成绩”和“成绩处理”的命令按钮,四个标签分别作提示性的说明,通过四个文本框分别用来输出数据,从键盘输入10个学生的成绩,求他们的平均成绩,最高分,最低分,并从高到低排名。程序的运行界面如图7.1所示。
图7.1【引例】运行界面
分析:在【引例】中,要求用户完成五项功能:输入10个学生的成绩,求平均成绩,最高分,最低分,排名。当然,这五项功能可以编写在一个事件过程中完成,但程序显得很复杂,如果把程序分成几个独立功能模块来完成,而由主程序调用,程序结构就显得比较清晰,容易调试和修改。
程序设计步骤(1)设计用户界面图7.2【引例】设计界面根据题目的分析,设计如图7.2所示用户界面。图7.2【引例】设计界面
(2)属性设置各相关控件的属性设置见表7.1。表7.1【引例】属性设置控件名称属性属性值Label1Caption最高成绩Label2Caption最低成绩Label3Caption平均成绩Label4Caption从高到底排序Text1TextText1Text2TextText2Text3TextText3Text4TextText4Command1Caption输入成绩Command2Caption成绩处理
完成属性设置的用户界面如图7.3所示。图7.3【引例】设计界面
(3)编写程序代码'在窗体模块中定义数组stscore(1To10),全局变量的定义Dimstscore(1To10)AsSingle'初始化输出控件PrivateSubForm_Load()Text1=""'初始化输出控件,使文本框的初始内容为空
Text2=""Text3=""Text4=""EndSub
'输入10个学生的成绩PrivateSubCommand1_Click()Fori=1To10
stscore(i)=InputBox("请输入学生的成绩")NextiEndSub
'对成绩进行处理PrivateSubCommand2_Click()
st_sum'调用st_sum过程
Max_min'调用Max_min过程
sort'调用sort过程EndSub
'编写求平均成绩过程st_sumPublicSubst_sum()Fori=1To10Sum=Sum+stscore(i)NextiText3=Sum/10'在文本框中输出EndSub'编写求最高,最低成绩过程Max_minPublicSubMax_min()Max=stscore(1)Min=stscore(1)Fori=1To10IfMax<stscore(i)ThenMax=stscore(i)IfMin>stscore(i)ThenMin=stscore(i)NextiText1=Max'在文本框中输出
Text2=Min'在文本框中输出EndSub
'编写排名过程sortPublicSubsort()Fori=1To9Forj=i+1To10Ifstscore(i)<stscore(j)Thent=stscore(i):stscore(i)=stscore(j):stscore(j)=tEndIfNextjNextiFori=1To10Text4=Text4&stscore(i)&Space(1)'在文本框中输出NextiEndSub
(4)运行程序
程序运行时,单击“输入成绩”命令按钮,弹出输入成绩对话框,如图7.4所示,依次输入10个学生的成绩,单击“确定”按钮,把输入的10个学生的成绩保存在全局数组stscore(1To10)中,单击“成绩处理”命令按钮,在文本框中显示程序对成绩处理的结果。如图7.1所示。图7.4【引例】运行界面
说明:在程序【引例】中,通过命令按钮Command1_Click()事件过程,完成了数据的输入,同时编写了求平均成绩过程st_sum,求最高和最低成绩过程Max_min,排名过程sort,并通过命令按钮Command2_Click()事件过程调用通用过程st_sum,Max_min,sort,从而完成了对数据的处理。在程序【引例】中,实际上把一个复杂的问题分成几个独立的功能模块来实现。如果某个模块没有实现预定的功能,便可有针对性的去修改,而不必检查整个程序,从而简化了程序设计的任务,避免重复的工作,便于设计和修改。这是处理问题的一个重要方法,同时,过程也可以被其它程序所共享。下面就过程的定义和使用作详细说明。
7.2过程7.2.1过程的概念1过程过程是构成程序的一个模块,往往用来完成一个相对独立的功能。过程可以使程序更清晰,更具有结构性,所以把程序分割成较小的逻辑部件就可以简化程序设计的任务,这些部件称为过程。2用过程编程有两大好处
(1)过程可以把程序划分成离散的,较小的逻辑单元,每个单元都比无过程的整个程序容易调试,而且过程可用于压缩重复任务或共享任务。(2)一个程序中的过程,往往不必修改或只需稍作改动,便可以成为另一个程序的构件。3VisualBasic中过程的分类
(1)通用过程通用过程包括子程序过程(或称作Sub过程)和函数过程(或称作Function过程)。(2)事件过程
7.2.2过程的建立定义子过程和函数过程有以下两种方法。1利用“工具”菜单下的“添加过程”命令定义过程。(1)为想要编写函数和子程序过程的“窗体”或“标准模块”打开代码窗口,如图7.5。(2)单击“工具”菜单下的“添加过程”命令,显示“添加过程”对话框,如图7.6。(3)在图7.6中的“名称”框中输入过程名mypro(过程名中不允许有空格)。(4)在类型组中选取“子程序”定义子过程,选取“函数”定义函数过程。(5)在范围组中选取“公有的”定义一个公共级的全局过程,选取“私有的”定义一个标准模块级或窗体级的局部过程。(6)单击“确定”按钮,这时VisualBasic会自动在“代码”窗口中创建一个子过程或函数过程的框架,即过程的开始和结束语句,如图7.5所示。用户就可以在该过程中编写所需要的代码。
图7.6添加过程对话框图7.5向mypro过程添加代码
2利用代码窗口直接定义过程为想要编写函数或子程序过程的窗体/标准模块打开代码窗口,把插入点放在所有过程之外,键入Sub子过程名或Function函数过程名,然后按回车即可,如图7.5所示的mypro过程的编写。
7.3子程序过程7.3.1子程序过程的定义Sub过程的定义格式
[Private|Public][Static]Sub
过程名(参数列表)
语句
[ExitSub]
语句EndSub
1格式说明
Sub过程以Sub开头,以EndSub结束,在Sub和EndSub之间是描述过程操作的语句块,称为“过程体”或“子程序体”。其中,过程名的命名规则与变量的命名规则相同,注意不要与VisualBasic关键字重名,也不要与WindowsAPI函数重名,也不能与同一级别的变量名重名,过程名在一个程序中要具有唯一性。2关键字说明格式中的Private,Public,Static用来指定过程的访问类型,“参数列表”含有在调用时传送给该过程的简单变量名或数组名,名字与名字之间用逗号隔开。“参数列表”指明了调用时传送给过程的参数的类型和个数。
(1)Private:表示Sub过程是私有过程,只能被本窗体中的其它过程访问,不能被其它窗体(指多窗体工程)中的过程访问。该窗体中的任何事件过程都可调用该过程,下一次调用时,该过程中的所有局部变量被重新初始化(数值类型初始化为0,字符类型初始化为空串)。(2)Static:指定过程中的局部变量在内存中的存储方式。如果使用了Static关键字,则该过程中的局部变量就是“Static”类型,局部变量的值保持不变;如果省略了“Static”,则局部变量就默认为“自动”类型,即在每次调用过程时,局部变量被初始化为0或空字符串,Static对在过程之外定义的变量没有影响。其它窗体调用时,必须加上该过程所在的窗体名称。(3)Public:表示Sub过程是公有过程,可以在程序的任何地方调用。主要应用于标准模块或窗体模块中,而且关键字Public可以省略。
在窗体模块中定义的Public过程,在其它窗体模块也可以使用,但必须加过程所在的窗体名称,如:Form1.add,而且每次调用该过程,过程中的局部变量被重新初始化。【例7.1】求1*2+2*3+3*4+…+n*(n+1)的值,假定n=5。要求:求1*2+2*3+3*4+…+n*(n+1)的值的过程用过程实现。程序的运行界面如图7.7(a)所示。分析:1*2+2*3+3*4+…+n*(n+1)中每一项的通项公式为n*(n+1),可通过循环结构,用累加求和的方式来完成,程序的中心语句为:sum=sum+(i+1)*i。
图7.7(a)【例7.1】运行界面
设计步骤(1)设计用户界面根据题目的要求,在窗体上创建两个命令按钮和文本框,设计如图7.7(b)所示的用户界面,并根据图7.7(a)设置相关控件属性。图7.7(b)【例7.1】设计界面
(2)属性设置【例7.1】各控件的主要属性设置见表7.2。表7.2【例7.1】属性设置控件名称属性属性值Text1TextText1Command1Caption第一次调用Command2Caption第一次调用Form1Caption用Private定义过程
(3)编写代码'定义过程PrivateSubfunc(nAsInteger)DimsumAsInteger'过程中的局部变量
Fori=1Tonsum=sum+(i+1)*iNextiText1=sumEndSub'第一次调用过程PrivateSubCommand1_Click()DimaAsIntegera=5
funca'过程调用EndSub
'第二次调用过程PrivateSubCommand2_Click()DimaAsIntegera=5
funca'过程调用EndSub
(4)运行程序程序运行时,如果单击“第一次调用”命令按钮,则在文本框中显示运行结果70,单击“第二次调用”命令按钮,在文本框中显示运行结果仍然是70。说明:为什么两次调用的结果相同呢?原因是在定义过程func时用Private关键字指明了该过程的访问类型,则该过程中的局部变量sum的值在第二次调用该过程时被重新初始化为0,所以两次调用的结果完全相同。如果在【例7.1】中把定义过程func中的关键字Private改为Static,则程序的运行结果将完全不同。
程序运行时,如果单击“第一次调用”命令按钮,则在文本框中显示运行结果70,单击“第二次调用”命令按钮,则在文本框中显示运行结果140。原因是在定义过程func时用Static关键字指明了该过程的访问类型,则该过程局部变量sum的值在第二次调用该过程时并没有被重新初始化,而是保留了第一次调用结束时sum的值70。当再次执行sum=sum+(i+1)*i语句时,sum的初始值是70,而不是0,所以运行结果为140。
通过【例7.1】的学习,读者应掌握以下知识点:①用Private关键字定义过程,该过程中的局部变量在每次调用时重新初始化。②用Static关键字定义的过程,在程序退出之前的每次调用,该过程中的局部变量都保留上一次调用结束时的值。③累加器的使用:sum=sum+(i+1)*i
7.3.2子程序过程的调用通过【引例】和【例7.1】的学习,读者对过程的调用格式有了初步的认识,那么究竟如何调用过程呢?过程调用实际上是过程的执行,即要执行一个过程,必须调用该过程。子程序过程的调用有两种方式,一种是把过程名放在一个Call语句中,另一种是把过程名作为一个语句来使用。1用Call语句调用Sub过程格式:Call过程名[(实际参数)]Call语句把程序控制传送到一个VisualBasic的Sub过程。“实际参数”是传送给Sub过程的变量或常数。如:Callcompute(1,2)。其中:compute是过程名,1,2是实参列表。2把过程名作为一个语句来使用
在调用Sub过程时,如果省略关键字Call,就成为调用Sub过程的第二种方式。与第一种方式相比,它有两点不同:(1)去掉关键字Call;(2)去掉实际参数的括号。如:Compute1,2。其中:Compute为过程名。在过程名和实参之间至少要有一个空格。【例7.2】合并排序,将两个有序的数组合并成为另一个有序的数组。假设有序的数组为a,b。合并后的数组为c。程序的运行结果见7.8图。
图7.8【例7.2】合并排序
分析:要进行合并排序,首先介绍合并排序的思想:(1)先在a,b数组中各取第一个元素进行比较,将小(递增次序)的元素放入c数组中。(2)取小的元素所在数组的下一个元素与上次比较后较大的元素比较,重复上述比较过程,直到某个数组被先排完。(3)将另一个数组剩余元素抄入c数组中,合并排序完成。设计步骤(1)设计程序界面在当前窗体上建立三个名称为Picture1、Picture2和Picture3的图片框,用三个名称为Label1,Label2和Label3的标签控件作提示性的说明,一个名称为Command1,外观属性为“合并”的命令按钮,设置完属性的界面如图7.8所示。
第一种方法Dima()AsVariant,b()AsVariant,c(100)AsVariantPrivateSubForm_Load()a=Array(2,4,6,8,10)'对a,b数组赋初值
b=Array(1,3,5,7,9,11,13,15)EndSub下面的输出数组代码没有使用过程输出数组PrivateSubCommand1_Click()Fori=0ToUBound(a)'在Picture1中输出数组aPicture1.Printa(i);If(i+1)Mod10=0ThenPicture1.PrintNexti
Fori=0ToUBound(b)'在Picture2中输出数组bPicture2.Printb(i);If(i+1)Mod10=0ThenPicture2.PrintNextiCallinsort(a,b,c)'调用合并排序过程
Fori=0ToUBound(c)'在Picture3中输出数组cPicture3.Printc(i);If(i+1)Mod10=0ThenPicture3.Print'每行输出10个元素
NextiEndSub
'定义合并排序过程PublicSubinsort(x()AsVariant,y()AsVariant,z()AsVariant)DimixAsInteger,iyAsInteger,izAsIntegerDoWhileix<=UBound(x)Andiy<=UBound(y)Ifx(ix)<y(iy)Then
z(iz)=x(ix):ix=ix+1
Else
z(iz)=y(iy):iy=iy+1EndIf
iz=iz+1Loop
DoWhileix<=UBound(x)'a数组的剩余元素抄入c数组
z(iz)=x(ix):ix=ix+1:iz=iz+1LoopDoWhileiy<=UBound(y)'b数组的剩余元素抄入c数组
z(iz)=y(iy):iy=iy+1:iz=iz+1LoopEndSub
第二种方法'对数组进行初始化Dima()AsVariant,b()AsVariant,c(100)AsVariantPrivateSubForm_Load()a=Array(2,4,6,8,10)'对a,b数组赋初值
b=Array(1,3,5,7,9,11,13,15)EndSub用调用输出数组的过程输出结果。PrivateSubCommand1_Click()Callprarray(a,Picture1)'调用输出数组过程
Callprarray(b,Picture2)Callinsort(a,b,c)'调用合并排序过程
Callprarray(c,Picture3)EndSub
'定义输出数组过程PublicSubprarray(x()AsVariant,pAsControl)Fori=0ToUBound(x)
p.Print
x(i);If(i+1)Mod10=0Thenp.Print'每行输出10个元素
NextiEndSub
'定义合并排序过程PublicSubinsort(x()AsVariant,y()AsVariant,z()AsVariant)DimixAsInteger,iyAsInteger,izAsIntegerDoWhileix<=UBound(x)Andiy<=UBound(y)Ifx(ix)<y(iy)Then
z(iz)=x(ix):ix=ix+1
Else
z(iz)=y(iy):iy=iy+1EndIf
iz=iz+1LoopDoWhileix<=UBound(x)'a数组的剩余元素抄入c数组
z(iz)=x(ix):ix=ix+1:iz=iz+1LoopDoWhileiy<=UBound(y)'b数组的剩余元素抄入c数组
z(iz)=y(iy):iy=iy+1:iz=iz+1LoopEndSub
说明:在【例7.2】中,数组的输出分别用两种方法输出,从第一种方法来看,对数组a,b,c输出格式完全相同,重复书写代码,很繁琐,而在第二种方法中,把数组的输出用一个过程来完成,压缩了重复任务,简化了程序代码,程序显得很清晰,修改也很方便。这就是采用过程编程的优势。知识点:①比较用过程编程和非过程编程的优缺点。②掌握合并排序的思想。③掌握如何用图片框输出数据。④掌握用Array函数对数组赋值,该函数只能对一维数组赋值。
7.4函数过程前面介绍了子程序过程,它不直接返回值,可以作为独立的基本语句调用。而函数过程要返回一个值,通常出现在表达式中。这一节将介绍函数过程的定义和调用。7.4.1函数过程的定义VisualBasic包含许多内部函数,如Sqr、Cos
或Chr。此外,还可用Function语句编写自己的Function过程。函数实际是实现一种映射,它通过一定的映射规则,完成运算并返回结果。函数的定义方式与Sub过程很相似,可以说只不过用Function关键字取代Sub关键字,同时加入返回值类型说明即可定义函数过程。自定义函数过程的语法格式为:
[Private|Public|Static]Function过程名([参数表列])[As类型]
语句 函数名=表达式
ExitFunction
语句块EndFunction
说明:(1)Function过程以Function开头,以EndFunction结束,在两者之间是描述函数过程操作的语句块,即“过程体”或“函数体”。(2)调用Sub函数相当于执行一个语句,不直接返回值;而调用Function过程要返回一个值,因此可以象内部函数一样在表达式中使用。(3)因为过程不能嵌套,因而不能在事件过程中定义通用过程,只能在事件过程内调用通用过程。“函数名=表达式”中,函数名是函数过程的名称,它遵循变量的命名规则,表达式的值是函数过程的返回值,通过赋值符号将其赋给函数名。如果无此项,则函数过程返回一个默认值,数值型函数返回0,字符型函数返回空字符串。
7.4.2函数过程的调用Function过程的调用比较简单,可以像使用VisualBasic内部函数一样来调用Function过程。实际上,由于Function过程只能返回一个值,因此完全可以把它看成是一个函数,它与内部函数(如Sqr、Str$、Chr$等)没有什么区别,只不过内部函数由语言系统提供,而Function过程由用户自己定义。
【例7.3】在文本框中输出所有的“水仙花数”。要求:求“水仙花数”的过程用函数实现。程序的运行界面如图7.9所示。图7.9【例7.3】运行界面
分析:所谓“水仙花数”是指一个三位数整数,其各位数字的立方和等于该数本身。例如153是一个水仙花数,因为13+53+33=153。所以,处理问题的关键是如何求出一个三位整数中个位,十位,百位上的数字。可以通过hadr=Int(n/100)语句求得百位上的数字,ten=Int((n-hadr*100)/10)语句求得十位上的数字,div=n-hadr*100-ten*10求得个位上的数字。
该过程用函数来实现,可定义一个返回值为Boolean类型的函数,通过该函数判断每一个数是否为“水仙花数”,若函数的返回值为True,则把该数显示在文本框中。设计步骤(1)设计用户界面根据程序的运行界面,在窗体上建立一个名称为Label1的标签,一个名称为Text1的文本框和一个名称为Command1的命令按钮,并设置相关的属性,如图7.9所示。(2)编写代码PrivateSubForm_Load()Text1=""EndSub
'函数的调用PrivateSubCommand1_Click()DimiAsInteger,xAsIntegerFori=100To999Ifsxh(i)=TrueThenText1=Text1&i&Space(1)'函数的调用
EndIfNextiEndSub
'求“水仙花数的函数”PublicFunctionsxh(nAsInteger)AsBooleanDimdivAsInteger,tenAsInteger,hadrAsInteger'求3位数中各位上的数字
hadr=Int(n/100)'百位数字
ten=Int((n-hadr*100)/10)'十位数字
div=n-hadr*100-ten*10'个位数字
Ifhadr^3+ten^3+div^3=nThen'条件
sxh=True'函数的返回值
EndIfEndFunction
(3)运行程序程序运行时,如果单击“水仙花数”命令按钮,则在文本框中显示所有的“水仙花数”如图7.9所示。通过【例7.3】的学习,读者应掌握以下知识点:①掌握“水仙花数”的定义和算法。②掌握如何定义函数和函数返回值的类型。③掌握用文本框输出数据的形式——字符串的连接,中心语句为:Text1=Text1&i&Space(1)。通过以上的介绍,读者已掌握了如何定义函数和过程,并掌握了函数和过程的调用方式。希望读者能够上机通过编程来实现和掌握。
7.5事件过程7.5.1事件过程的定义事件过程也是Sub过程,但它很特殊,它附加在窗体和控件上。一个控件的事件过程由控件的实际名字、下划线和事件名组成;而窗体事件过程由“Form”、下划线和事件名组成。控件事件过程的定义格式如下:[Private|Public]Sub
控件名_事件名(参数表)语句组EndSub窗体事件的一般格式为:[Private|Public]SubForm_事件名(参数表)语句组EndSub
7.5.2事件过程的调用可以看出,除了名字外,控件事件过程与窗体事件过程的格式基本上一样。多数情况下是事件过程调用通用过程。通用过程可以放在标准模块中,也可以放在窗体模块中,而事件过程只能放在窗体模块中,不同模块中的过程可以互相调用。当过程名唯一时,可以直接通过过程名调用;如果两个或两个以上的标准模块中含有相同的过程名,则在调用时必须用模块名限定,其一般格式为:模块名.过程名(参数表)如:假定已经建立一个Command1_Click()的事件过程,能否通过Command2_Click()的事件来调用Command1_Click()呢?下面的程序说明了事件过程之间的相互调用方式。
'Command1_Click()的事件PrivateSubCommand1_Click()Print"事件过程的调用"EndSub'在Command2的事件过程中调用Command1的事件过程PrivateSubCommand2_Click()Command1_Click()EndSub
7.6参数的传递在调用一个过程时,必须把实际参数传送给过程,完成形式参数与实际参数的结合,然后用实际参数执行调用的过程。那么,什么叫形参,什么叫实参,形参和实参有何区别,它们如何使用,这是本节的难点,也是重点。7.6.1形参与实参通过以上内容的介绍,读者对如何定义和调用过程和函数有了比较深刻的认识,在函数和过程的调用过程中,参数的传递是一个十分重要的内容,直接影响到过程和函数的执行结果。下面的章节就参数传递的各种形式作一个归纳和说明,希望读者通过本节的学习能够灵活应用。
参数可分为两种类型,一种是在Sub、Function过程定义中出现的变量名,称为形式参数(简称形参),另一种是在调用Sub或Function过程时传送给Sub或Function过程的常数、变量、表达式或数组,称为实际参数(简称实参)。实参与实参之间用逗号分隔,它必须与形参保持一致,位置与类型一一对应,但它们的名字可以不相同。
【例7.4】用函数来完成计算两个数的和,要求:从文本框中输入两个数,把结果从第三个文本框中输出。程序设计和运行界面如图7.10所示。图7.10【例7.4】程序设计和运行界面
根据题目的要求,设计如图7.10所示的程序界面,同时设置相关控件的属性,程序的代码为:'初始化控件PrivateSubForm_Load()Text1=""Text2=""Text3=""EndSub'定义求和函数过程PrivateFunctionadd(xAsInteger,yAsInteger)'x,y为形参
DimsumAsIntegersum=y+xadd=sumEndFunction
'用事件过程调用函数过程:PrivateSubCommand1_Click()Text3=add(Val(Text1),Val(Text2))'Val(Text1),Val(Text2)为实参EndSub
说明:该函数过程add(xAsInteger,yAsInteger)中的参数x,y称为函数的形参,而把事件过程Command1_Click()中调用函数语句Text3=add(Val(Text1),Val(Text2))时的参数Val(Text1),Val(Text2)称为函数的实参。在【例7.4】中,调用add函数时,把文本框中输入的数值12和23作为实参分别传递给形参x和y,这种传递按参数一一对应。通过【例7.4】的学习,读者应掌握以下知识点:①形参和实参的概念②参数传递时,只能由实参传递给形参。③参数传递时形参和实参一一对应。其实在VisualBasic中,参数传递有各种各样的形式,每一种如何使用,它们之间有何差别,这是参数传递的重点和难点,需要读者上机反复实践才能熟练掌握。
7.6.2参数的传送方式1按位置传送按位置传送是指实参的位置次序与形参的位置次序必须一致,形参的个数和实参的个数必须相等,实参与形参的类型必须相同。形式参数表中各个变量之间用逗号隔开,形参表中的变量可以是除定长字符串之外的合法变量名;后面跟有左、右括号的数组名。实际参数表中的各项用逗号隔开,实参可以是:常数;表达式;合法的变量名;后面跟有左、右括号的数组名等。
【例7.5】从键盘输入任意三个整数,求出它们的最大值和最小值,并分别显示在两个文本框中。要求:求最大值和最小值用过程来完成,输入数据用InputBox函数输入,用命令按钮的单击事件来调用过程。程序的运行界面如图7.11所示。分析:一个函数只能返回一个值,而一个过程可以返回或输出多个值,因此,求最大值和最小值的过程只能用子程序过程来完成,而不能用函数过程。图7.11【例7.5】运行界面
设计步骤(1)设计程序界面根据题目的要求,在窗体上创建一个名称为Command1,外观属性为“确定”命令按钮,两个名称分别为Text1,Text2的文本框,并用两个标签作提示性说明,设计完成以后的界面如图7.11。(2)编写程序代码'求最大值和最小值的Sub过程
PublicSubMax_Min(xAsInteger,yAsInteger,zAsInteger)'先从小到大排序
DimtAsIntegerIfx>yThent=x:x=y:y=tEndIf
Ifx>zThent=x:x=z:z=t
EndIfIfy>zThent=y:y=z:z=tEndIfText1=xText2=zEndSub
PrivateSubCommand1_Click()DimaAsInteger,bAsInteger,cAsIntegera=InputBox("请输入a的值")b=InputBox("请输入b的值")c=InputBox("请输入c的值")CallMax_Min(a,b,c)'调用过程EndSub
(3)运行程序程序运行时,单击“确定”命令按钮,则弹出“输入对话框”,在数据输入区域依次输入12,1,45数值,则a=12,b=1,c=45,在调用过程CallMax_Min(a,b,c)时,对输入的3个数进行从小到大排序,并且a中存放最小值,c中存放最大值。通过【例7.5】的学习,读者应掌握以下知识点:①子程序过程和函数过程的选择:只有一个返回值时,可以用子程序过程,也可以用函数过程;如果有多个返回值时,只能用子程序过程。②按位置传送参数传递时,只能由实参传递给形参,而且形参和实参一一对应。在本例中,实参a只能传递给形参x,实参b只能传递给形参y,实参c只能传递给形参z,而且实参的个数必须与形参相同,位置必须一致。③不改变实参变量的顺序,把数据按升序或降序排序。
2指名传送所谓指名参数传送,就是显式的指出与形参结合的实参,把形参用“:=”与实参连接起来。与按位置传送方式不同,指名传送方式不受位置次序的限制。如果在【例7.5】中把参数的传递改为指名传送,程序的代码应改变为:
'求最大值和最小值的Sub过程PublicSubMax_Min(xAsInteger,yAsInteger,zAsInteger)'先从小到大排序
DimtAsIntegerIfx>yThent=x:x=y:y=tEndIf
Ifx>zThent=x:x=z:z=t
EndIfIfy>zThent=y:y=z:z=tEndIfText1=xText2=zEndSub
'求最大值和最小值的Sub过程PrivateSubCommand1_Click()DimaAsInteger,bAsInteger,cAsIntegera=InputBox("请输入a的值")b=InputBox("请输入b的值")c=InputBox("请输入c的值")CallMax_Min(y:=a,z:=b,x:=c)'调用过程EndSub
说明:从CallMax_Min(y:=a,z:=b,x:=c)语句可以看出,指名传送明确的指出了与形参结合的实参,只要参数的传递方式是指名传送,则形参y:=a,z:=b,x:=c的位置次序可以任意改变,但无论如何变化,实参a只能传递给形参y,实参b只能传递给形参z,实参c只能传递给形参x,而且实参的个数必须与形参相同,跟按位置传送的唯一区别是,形参的位置不受限制。知识点:①在表面上来看,指名结合传送比按位结合传送繁琐,因为要多写一些东西,但它能改善过程调用的可读性,能明确表示出与形参结合的实参;此外,当参数较多时,指名结合比按位置结合出错的可能性小。但应注意,有些方法的调用不能使用指名参数,在使用时请查阅相关的帮助信息。
②图7.12(a),7.12(b)是按位置传送和指名传送的比较,请读者注意它们的区别。过程调用:CallMax_Min(a,b,c)过程定义SubMax_Min(xAsInteger,yAsInteger,zAsInteger)图7.12(a)按位置传送参数过程调用:CallMax_Min(y:=a,z:=b,x:=c)过程定义SubMax_Min(xAsInteger,yAsInteger,zAsInteger)图7.12(b)指名传送参数
3按值传递和按地址传递参数在VisualBasic中,按参数传递的内容,参数传递的形式可分为两种,即传地址和传值,其中传地址习惯上称为引用。传地址是指在调用一个过程时,将实参的地址传递给形参,所以,实参和形参在内存中公用同一内存单元,形参值的改变将改变实参的值,传递地址在VisualBasic中是缺省的,有时也可以用ByRef关键字来指明是地址传送。值传递是指在调用一个子过程时,系统将实参的值复制给形参,形参与实参断开了联系。被调用过程中的操作是在形参的存储单元中进行,当过程调用结束时,形参所占存储单元同时被释放,因此在过程中对形参的任何操作都不会影响到实参。值传递必须用ByVal关键字指明。
【例7.6】交换任意两个整数的值,分别用值传递和地址传递来定义交换过程。程序的运行界面如图7.13(a)所示。图7.13(a)【例7.5】运行界面
设计步骤(1)界面设计根据图7.13(a)设计如图7.13(b)所示的程序设计界面。图7.13(b)【例7.6】设计界面界面
(2)属性设置见表7.3。表7.3【例7.6】属性设置控件名称属性属性值Label1Caption交换前Label2Caption交换后Label3Caption实参aLabel4Caption实参bText1Text空白Text2Text空白Text3Text空白Text4Text空白Command1Caption值传递Command2Caption地址传递Form1Caption值传递和地址传递
(3)编写代码'值传递过程PublicSubswap1(ByValxAsInteger,ByValyAsInteger)DimtempAsIntegertemp=xx=yy=tempEndSub'地址传递过程PublicSubswap2(xAsInteger,yAsInteger)DimtempAsIntegertemp=xx=yy=tempEndSub
'调用值传递过程PrivateSubCommand1_Click()DimaAsInteger,bAsIntegera=10b=20Text1=aText2=bswap1a,b'调用过程swap1Text3=aText4=bEndSub'调用地址传递传递过程PrivateSubCommand2_Click()DimaAsInteger,bAsIntegera=10b=20Text1=aText2=bCallswap2(a,b)'调用过程swap2Text3=aText4=bEndSub
(4)运行程序程序运行时,单击“值传递”命令按钮,则在文本框中显示在调用值传递过程swap1之前和之后实参的变化,由程序的运行结果可以看出,程序在调用值传递过程swap1之后,实参的值没有发生变化。单击“地址传递”命令按钮,则在文本框中显示在调用地址传递过程swap2之前和之后实参的变化,由程序的运行结果可以看出,程序在调用地址传递过程swap2之后,实参a和b的进行了交换。如图7.13(a)所示。
说明:在调用值传递过程swap1时,首先把实参a,b的值复制到形参的存储单元x,y中,然后被调用过程中的操作是在形参的存储单元x,y中进行,所以,当过程swap1调用结束时,形参x,y的值发生了变化,而实参a,b的值不变。如图7.14(a),7.14(b)所示。20101020实参a形参bxy7.14(b)过程调用结束hou20102010实参a形参bxy7.14(a)调用过程前在形式上看,值只能由实参传递给形参,而不能由形参传递给实参,所以,值传递是“单向传递”。
20101020实参a形参bxy7.14(b)过程调用结束hou
20102010实参a形参bxy7.14(a)调用过程前
地址传递实际是把实参的地址传递给形参,所以形参x和实参a公用同一存储单元,形参y和实参b公用同一存储单元,实参a,b的值随着形参x和y值的变化而变化,在形式上看,值好象是由实参传递给了形参,又由形参传递给了实参,所以,地址传递是“双向传递”。见图7.14(c)。使用地址传送参数,提高了程序的效率。a,xb,y图7.14(c)地址传递2010
本节知识点:①值传递是把实参的内容复制到形参的存储单元,是“单向”传递。②地址传递是把实参的地址传递给形参,是“双向”传递。③值传递时,形参必须用ByVal关键字指明,地址传递时,形参可以用ByRef关键字指明,也可以省略。④使用地址传递参数时,对应的实参不能是表达式,常数和数值,但可以是变量,数组名。
4数组参数的传递如果用子程序过程或函数过程来处理大批量的数据,那么传递给形参的变量就不是一个或多个简单变量,而是整个数组的起始地址。VisualBasic允许把数组作为实参传送到过程中。例如,定义了如下过程:SubS(a(),b())……EndSub该过程有两个形参,这两个形参都是数组。可以用下面的语句调用该过程:CallS(p(),q())这样就把数组p和q传送给过程中的数组a和b。当数组作为过程的参数时,使用的是“传地址”方式,而不是“传值”方式。即不是把p数组中每个元素的值一一传送给过程中的a数组,而是把p数组的起始地址传给该过程,使a数组也具有与p数组相同的起始地址。
【例7.7】从键盘输入一个二维数组,如图7.15所示,求数组中最大元素的值,最大元素所在的行号和列号。要求:求二维数组中元素的最大值,以及最大值元素所在的行号和列号用过程来实现。图7.15【例7.7】运行界面
分析:从键盘输入数组元素可以通过多种方式,为了使输入的数据更加灵活,采用InputBox函数输入数组元素。首先把数组中第一个元素arr(1,1)看作是最大值,即Max=arr(1,1),然后把Max的值依次和所有的数组元素进行比较,如果Max<arr(i,j),则Max=arr(i,j),同时记录arr(i,j)的行号row=i和列号col=j,最后输出最大值Max,行号row和列号col。
设计步骤:(1)界面设计根据图7.15程序的运行界面,在窗体上创建两个命令按钮,三个文本框控件用来输入和输出数据,同时用三个标签控件作提示性的说明,设计界面如图7.15所示(2)编写代码'定义全局数组Dimarr(1To3,1To3)AsInteger'求二维数组中的元素的最大值,以及最大值元素所在的行号和列号的过程
PrivateSubcult(x()AsInteger)'数组作为形参
Max=x(1,1)Fori=1To3Forj=1To3IfMax<x(i,j)ThenMax=x(i,j)'最大值
row=i'行号
col=j'列号
EndIfNextjNexti'在文本框中显示结果
Text1=MaxText2=rowText3=colEndSub
'给数组赋初值PrivateSubCommand1_Click()Fori=1To3Forj=1To3
arr(i,j)=InputBox("请输入数组元素的值")NextjNexti'输出二维数组
Fori=1To3PrintForj=1To3Printarr(i,j);NextjNextiEndSub
'调用过程cult,数组作为实参PrivateSubCommand2_Click()cultarr'调用过程cult,数组作为实参EndSub
(3)运行程序程序运行时,单击“输入”命令按钮,则从键盘输入一个二维数组并在窗体上输出,单击“确定”命令按钮,则在相应文本框中输出最大值,最大值元素所在的行号和列号。程序的运行结果如图7.15所示。知识点:①数组作为函数的形参,定义数组的形参时,一定要用“数组名()”,如:sub过程名(a()asinteger),当然,也可以用一个参数来传递数组元素的个数,如:sub过程名(a()asinteger,nasinteger)。②数组作为函数的实参,定义数组的实参时,如果传递的是整个数组元素,则实参的形式必须是“数组名”或“数组名()”,而如果只传递某一个数组元素,则一定要指明下标。
5记录(结构体)的传送当子程序过程或函数过程中的参数是记录类型时,必须先定义记录类型的数据,可以在窗体模块中关键字Private定义记录类型,也可在标准模块中用关键字Public定义记录类型,【例7.8】说明了当过程中传递的参数是记录类型时,如何定义数据类型以及参数为记录类型时如何传递。用户自定义类型用途很广,也很使用,要熟练掌握。
【例7.8】编写程序,要求用户输入一个学生的基本信息:“姓名”,“年龄”,“身高”,然后将输入的数据通过文本框控件显示出来,显示用过程完成。程序的运行界面如图7.16(a)所示。图7.16(a)【例7.8】运行界面
设计步骤(1)设计程序界面在窗体上建立三个文本框用来输出学生信息,三个标签作提示性说明和一个命令按钮用来输入数据,程序设计截面和属性设置见图7.16(a)所示。(2)程序代码'定义数据类型PrivateTypetstudentNameAsString*10AgeAsIntegerHeightAsDoubleEndType
'显示过程,传送记录类型的数据PrivateSubShowStudent(stuAststudent)'形式参数为记录类型
Text1.Text=stu.NameText2.Text=stu.AgeText3.Text=stu.HeightEndSub'调用过程PrivateSubCommand1_Click()DimstudentAststudent
student.Name=InputBox("请输入学生的“姓名”")
student.Age=InputBox("请输入学生的“年龄”")
student.Height=InputBox("请输入学生的“身高”")CallShowStudent(student)'实参为整体传送EndSub
(3)运行程序图7.16(b)【例7.8】数据输入程序运行时,依次在输入框中输入每个学生的基本信息,如图7.16(b)所示,然后单击图7.16(a)中的“输出”按钮,将在文本框中显示学生相应的信息。图7.16(b)【例7.8】数据输入
知识点:①学会定义记录类型的数据②如何引用记录类型变量的成员③记录类型的变量作为函数或过程的参数时,形参和实参必须是整体传送。6可选的参数和可选参数的缺省值如果一个过程中的形式参数是固定的,调用时提供的实参也是固定的,也就是说,如果一个过程有3个形参,则调用时必须按相同的顺序和类型提供3个实参。在VisualBasic6.0中,可以指定一个或多个参数作为可选参数。例如:假定建立了一个计算两个数的和的过程,该过程可选择地求第三个数的和。在调用时,既可以给它传送2个参数,也可以给它传送3个参数。
为了定义具有可选参数的过程,必须在过程的参数列表中列入Optional关键字,指定过程的参数为可选的。并且在过程中通过IsMissing函数测试调用时是否传递可选参数。【例7.9】求10,11或10,11,12的和,求和用“一个”过程来完成。分析:以前学过的过程,一个过程中的参数的个数是固定的,例如:过程头部为Submypro(xAsInteger,yAsInteger)的过程,每调用过程mypro一次,则只能求出两个参数的操作,如果把过程的头部改为Submypro(xAsInteger,yAsInteger,OptionalkAsVariant),由于参数k前面列入了关键字Optional,所以参数k为可选参数,通过过程mypro,既可求出两个参数x和y的操作,也可以求出x、y和k三个数的操作。这样,大大提高了过程的通用性。
编写具有可选参数的过程'可选参数的应用PrivateSubadd1(xAsInteger,yAsInteger,OptionalkAsVariant)DimsumAsIntegersum=x+yIfNotIsMissing(k)Thensum=sum+kEndIfPrintsumEndSub调用具有可选参数的过程PrivateSubCommand1_Click()add110,11'提供了2个参数,结果为21。
add110,11,12'提供了第3个参数(可选参数),结果为33。EndSub
【例7.9】的知识点:①可选参数要用Optional关键字来声明,而且可选参数的类型必须是Variant。②如果指定了可选参数,则参数表中此参数后面的其它参数也必须是可选。③是否传递可选参数,用IsMissing(可选参数名)来测试。也可以给可选参数指定缺省值。在【例7.9】中,如果未将可选参数传递到函数过程,则返回一个缺省值。如果把例题【例7.9】可改为:
'定义可选参数的确省值PrivateSubadd2(xAsInteger,yAsInteger,OptionalkAsVariant=10)DimsumAsIntegersum=x+yIfNotIsMissing(k)Thensum=sum+kEndIfPrintsumEndSub下面的事件过程在调用Subadd2(xAsInteger,yAsInteger,OptionalkAsVariant=10)时,虽然只提供了2个参数,但第3个可选参数按确省值10计算,结果为13PrivateSubCommand2_Click()add21,2EndSub
7使用不定数量的参数一般说来,过程调用中的参数个数应等于过程说明的参数个数,如果参数(形参和实参)的个数不确定,可用ParamArray
关键字指明,这时,过程将接受任意个数的参数。可变参数过程的一般格式为:Sub过程名(ParamArray
数组名)这里的“数组名”是形式参数,只有名字和括号,没有上下界。由于省略了类型变量,“数组”的类型默认为Variant。
【例7.10】计算任意个数据的和。分析:通过定义一个可选参数过程,可以实现对多个参数的操作,但最多能对多少个数据进行操作,主要看可选参数过程中固定参数和可选参数的个数,比如:Subadd2(xAsInteger,yAsInteger,OptionalkAsVariant=10,Optionalz)过程中有两个必须提供的参数x和y,还有两个可选参数k和z,因此该过程最多可操作四个参数,最少可操作两个参数,因此仍然有一定的局限。能不能定义这样一个过程,可以实现对任意个数的参数进行操作,答案是肯定的。
'使用不定量参数的过程PrivateSubSum(ParamArray
intNums())DimxAsVariant,intSumAsIntegerForEachxInintNumsintSum=intSum+xNextxPrintintSumEndSubPrivateSubCommand1_Cl
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 机电设备销售员工工作总结
- 2025-2030全球无线智能振动监测传感器行业调研及趋势分析报告
- 2025-2030全球FinFET 3D晶体管行业调研及趋势分析报告
- 2025-2030全球无人潜水器用于海上石油和天然气行业行业调研及趋势分析报告
- 2025-2030全球手机支付安全行业调研及趋势分析报告
- 2025年全球及中国纳米粒度及Zeta电位分析仪行业头部企业市场占有率及排名调研报告
- 2025-2030全球高效粘泥剥离剂行业调研及趋势分析报告
- 2025区域代理合同模板范本
- 供水工程承包合同
- 音响设备购销合同范本
- 输变电工程监督检查标准化清单-质监站检查
- 2024-2025学年北京海淀区高二(上)期末生物试卷(含答案)
- 【超星学习通】马克思主义基本原理(南开大学)尔雅章节测试网课答案
- 2024年中国工业涂料行业发展现状、市场前景、投资方向分析报告(智研咨询发布)
- 化工企业重大事故隐患判定标准培训考试卷(后附答案)
- 工伤赔偿授权委托书范例
- 食堂餐具炊具供货服务方案
- 员工安全健康手册
- 2024化工园区危险品运输车辆停车场建设规范
- 自然科学基础(小学教育专业)全套教学课件
- 华为客服制度
评论
0/150
提交评论