- Visual Basic从入门到精通(第2版)
- 龙马高新教育策划 国家863中部软件孵化器编著
- 216字
- 2020-06-27 13:11:10
第5章 应用程序提升的法宝—内置函数与过程
本章视频教学录像:1小时13分钟
使用Visual Basic中的内置函数,程序员在实现许多功能的同时可以减少大量代码的编写,而巧妙地使用过程则可使计算机完成特定的功能。本章主要介绍Visual Basic中常用的内置函数、Sub过程和Function过程。
本章要点(已掌握的在方框中打钩)
□ 了解数学函数
□ 了解字符串函数
□ 了解转换函数
□ 了解时间日期函数
□ 了解随机函数
□ 了解判断函数
□ 了解格式化函数
□ 了解Shell函数
□ 掌握过程及过程的嵌套与递归调用
□ 了解参数传递
5.1 秘密武器——常用的内置函数
本节视频教学录像:38分钟
巧妙地使用内置函数,程序员可以减少代码的编写量,轻松实现许多复杂的功能。本节介绍一些常用的内置函数。
5.1.1 数学函数
数学函数就是实现各种数学计算的函数,在Visual Basic中包含有丰富的数学函数供用户使用。常用的数学函数如表所示。
例如,使用Abs函数来计算“3”和“-3”的绝对值。
01 Private Sub Form_Activate() 02 Print"3的绝对值是:"&Abs(3) '输入正数3的绝对值 03 Print"-3的绝对值是:"&Abs(-3) '输出负数3的绝对值 04 End Sub
运行窗体后,结果如图所示。
5.1.2 字符串函数
在程序设计中,将能够对字符串处理的函数称为字符串函数。常用的字符串函数如表所示。
例如,使用Left()函数获取某字符串中最左边的6个字符。
01 Private Sub Form_Activate() 02 Dim str As String '定义字符串变量 03 str="Congratulations" '为字符串变量赋初值 04 Print"字符串最左边的6个字符是:"&Left(str,6) '输出字符串最左边6位 05 End Sub
运行窗体后,结果如图所示。
5.1.3 转换函数
在编程处理数据的时候,有时需要在各种数据类型间进行转换,Visual Basic中提供有很多数据类型转换的函数,特别是各种进制数据的转换以及字符串和数字的转换函数。
1. 进制转换函数
常见数据进制有十进制、二进制、八进制、十六进制等。十进制是我们最为常见和常用的数据进制,二进制是计算机的基础进制,八进制和十六进制因为和二进制有着天然的亲密关系,并且表示比二进制更方便,因此也成为计算机的常用表示方法。
在Visual Basic中进行数据进制转换的函数中,常用的有以下几种。
⑴ Hex()函数
求出参数的十六进制形式。
语法:
Hex(number)
number参数为任何有效的数值表达式或字符串表达式,不同取值情况下的函数返回结果如表所示。
例如输入一个十进制数,将其转换成十六进制,并将转换后的结果输出在窗体上。
01 Private Sub Command1_Click() 02 Print"您输入的十进制数是"&Text1.Text '输出获得的十进制数 03 Print"转成十六进制后为:"&Hex(Val(Text1.Text)) '输出转换后的结果 04 End Sub
输入一个十进制数“15”,单击【转换】按钮,结果如图所示。
⑵ Oct()函数
求出参数的八进制形式。
语法:
Oct(number)
number参数为任何有效的数值表达式或字符串表达式,不同取值情况下的函数返回结果如表所示。
例如输入一个十进制数,将其转换成八进制,并将转换后的结果输出在窗体上。
01 Private Sub Command1_Click() 02 Print"您输入的十进制数是"&Text1.Text '输出获得的十进制数 03 Print"转成八进制后为:"&Oct(Val(Text1.Text)) '输出转换后的结果 04 End Sub
输入一个十进制数“8”,单击【转换】按钮,结果如图所示。
⑶ Cint()函数
用于强制将一个表达式转换成-32768~327 67的整型。
语法:
Cint(number)
number参数为任何有效的数值表达式或返回值为数值的字符串表达式。
例如输入一个带小数的数值,将其强制转换成整型,并将转换后的结果输出在窗体上。
01 Private Sub Command1_Click()
02 Print"您输入数值是"&Text1.Text '输出获得的十进制数 03 Print"强制转换后为:"&Clnt(Val(Text1.Text)) '输出转换后的结果 04 End Sub
输入任意有效的数值表达式或字符串表达式,单击【转换】按钮,结果如图所示。
2. 字符串和数字转换函数
⑴ Str()函数
将数值型数据转换为字符型数值。
语法:
Str(number)
number参数为长整型,其中可包含任何有效的数值表达式。
例如,将一个数字转换成字符串。
01 Private Sub Form_Activate() 02 Print str(156.33) '返回" 156.33" 03 Print str(-156.33)'返回" -156.33" 04 End Sub
提示
当数字转换成字符时,字符串的首位是一个空格或是正负号。
⑵ Val()函数
返回包含于字符串内的数字。
语法:
Val(string)
string参数可以是任何有效的字符串表达式。
例如,返回字符串中包含的数值。
01 Private Sub Form_Activate() 02 Print Val("111.11") '返回"111.11" 03 Print Val("-111.11") '字符中的空格被除去了,返回"-111.11" 04 End Sub
5.1.4 日期时间函数
在编写程序的时候,往往会遇到各种样式的日期和时间,例如在状态栏中显示当前的系统日期等。
下面介绍几个常用的日期时间函数和日期时间转换函数。
1. Date ( )函数
用于返回系统的当前日期。
语法:
Date
例如,在窗体上显示系统的当前日期。
01 Private Sub Form_Activate() 02 Print"今天是:"&Date '返回系统当前日期 03 End Sub
结果如图所示。
2. Day(date)函数
用于表示一个月中的某一日,返回值为1~31之间的整数。
语法:
Day(date)
date参数可以是任何能够表示日期的可变类型数据、数值表达式、字符串表达式或它们的组合。如果date包含Null,则返回Null;如果不为空,则返回当前指定的日期的某一日。
例如,在窗体上显示系统当前是本月的第几天。
01 Private Sub Form_Activate() 02 Print"今天已是本月的第"&Day(Date)&"天!" '返回系统当前是本月第几天 03 End Sub
结果如图所示。
3. Month()函数
用于返回1到12之间的整数,表示一年中的某月。
语法:
Month(date)
date参数可以是任何能够表示日期的可变类型数据、数值表达式、字符串表达式或它们的组合。如果date包含Null,则返回Null;如果不为空,则返回当前指定的日期的某一月。
例如,在窗体上显示系统当前本年的月份。
01 Private Sub Form_Activate() 02 Print"现在已是本年的"&Month(Date)&"月份了!" '返回系统当前月份 03 End Sub
结果如图所示。
4. Time()函数
用于返回当前系统时间(不包含日期)。
语法:
Time
例如,在窗体上显示当前的时间。
01 Private Sub Form_Activate() 02 Print"现在是,北京时间:"&Time '返回系统当前时间 03 End Sub
结果如图所示。
5. Weekday() 函数
返回某个日期是星期几。
语法:
Weekday(date,[firstdayofweek])
Weekday函数语法中参数的含义如表所示。
firstdayofweek参数设置值如表所示。
Weekday函数的返回值如表所示。
例如,返回当前天数是本周的第几个工作日。
01 Private Sub Form_Activate() 02 Print"今天已是本周的第"&Weekday(Date)&"个工作日了" '返回系统工作日 03 End Sub
效果如图所示。
6. Year()函数
用于返回日期中的年份。
语法:
Year(date)
date参数可以是任何能够表示日期的可变类型数据、数值表达式、字符串表达式或它们的组合。如果date包含Null,则返回Null;如果不为空,则返回当前指定的年份。
例如,在窗体上显示系统日期是哪一年。
01 Private Sub Form_Activate() 02 Print"时间已经到了公元"&Year(Date)&"年!" '返回当前年份 03 End Sub
结果如图所示。
5.1.5 随机函数
在编程处理数据的时候,经常会用到随机函数,包括Randomize函数和Rnd函数。
1. Randomize函数
Randomize函数是初始化随机数生成器。
语法:
Randomize[number]
number:可选参数,是Variant类型的值或任何有效的数值表达式。
提示
若想得到重复的随机序列,要在使用具有数值参数的Randomize之前直接调用具有负参数值的Rnd,使用具有同样数值的Randomize是不会得到重复的随机数序列的。
2. Rnd函数
Rnd函数用于返回一个Single类型的随机数值。
语法:
Rnd[(number)]
如果number的值是Rnd生成,则number的值:
小于0:每次都使用number作为随机数种子得到的相同结果。
大于0:序列中的下一个随机数。
等于0:最近生成的数。
默认:序列中的下一个随机数。
注意
Rnd函数返回小于1但大于或等于0的值。number的值决定了Rnd生成随机数的方式。
对最初给定的种子都会生成相同的数列,因为每一次调用Rnd函数都用数列中的前一个数作为下一个数的种子。在调用Rnd之前,先使用无参数的Randomize语句初始化随机数生成器,该生成器具有根据系统计时器得到的种子。
为了生成某个范围内的随机整数,可使用以下公式。
lnt((upperbound - lowerbound + 1) * Rnd + lowerbound)
这里,upperbound是随机数范围的上限,而lowerbound则是随机数范围的下限。
提示
若想得到重复的随机数序列,在使用具有数值参数的Randomize之前直接调用具有负参数值的Rnd。使用具有同样number值的Randomize是不会得到重复的随机数序列的。
5.1.6 判断函数
在进行数据验证的过程中,使用判断函数会为编程工作带来极大的方便,判断函数包括IsNull函数、IsNumeric函数和IsArray函数。
1. IsNull函数
IsNull函数用于返回一个Boolean类型值,指出表达式是否不包含任何有效数据(Null)。
语法:
lsNull(expression)
expression:必要参数,是一个Variant类型的值,其中包含数值表达式或字符串表达式。
2. IsNumeric函数
Isnumeric函数用于返回一个Boolean类型的值,指出表达式的运算结果是否为数值。
语法:
lsNumeric(expression)
expression:必要参数,是一个Variant类型的值,包含数值表达式或字符串表达式。
3. IsArray函数
IsArray函数用于返回一个Boolean类型的值,指出变量是否为一个数组。
语法:
lsArray(varname)
Varname:必要参数,是一个指定变量的标识符。
5.1.7 格式化函数
Visual Basic中的格式化函数也称Format函数。
用于返回Variant(String)类型值,其中含有一个表达式,它是根据格式表达式中的指令来格式化数据的。
语法:
Format(expression[,format[,firstdayofweek[,firstweekofyear]]])
Format函数的语法具有下面几个部分。
1.设置值
firstdayofweek参数有下面的设置。
2.说明
firstweekofyear参数有下面的设置。
如果在格式化数字时没有指定format,Format会提供与Str函数类似的功能,尽管它是国际化的。然而,以Format作用在正数上不会保留正负号空间,而以Str的话则会。
如果要格式化一个没有本地化的数值字符串,应该使用一个用户自定义的数值格式,以保证得到需要的外观。
注意如果Calendar属性设置是Gregorian,并且format指定了日期格式,那么,提供的expression必须是Gregorian。如果Visual BasicCalendar属性设置是Hijri,则提供的expression必须是Hijri。
如果日历是Gregorian,则format表达式的意义没有改变。如果日历是Hijri,则所有的日期格式符号(例如,dddd,mmmm,yyyy)有相同的意义,这些意义只应用于Hijri日历。格式符号保持英文,用于文本显示的符号(例如,AM和PM)显示与该符号有关的字符串(英文或阿拉伯数字)。当日历是Hijri时,一些符号的范围会改变。
5.1.8 Shell函数
除了以上介绍的几个函数外,本小节介绍Shell函数。Shell函数的作用是在Visual Basic应用程序的执行过程中调用执行其他的应用程序,凡是能在DOS下或Windows下运行的可执行程序,均可通过Shell()函数在Visual Basic应用程序中调用。
Shell()函数的语法如下。
Shell(命令字符串[,窗口类型])
命令字符串是要执行的应用程序名,包括路径,它必须是可执行文件(扩展名为.com、.exe或.bat)。
窗口类型是指执行应用程序的窗口大小,可选择0~4或6的整型数值。取1,表示正常窗口状态。默认值为2,表示窗口被最小化成任务栏上的一个图标。
5.2 提升法宝——过程
本节视频教学录像:32分钟
过程就是一个具有相对独立的代码块。在一个大型系统中,会有很多独立的代码块,每个代码块将会完成一定的功能,最后把各个代码块组合起来就实现了大型系统的全部功能。
5.2.1 事件过程
当用户对某个窗体或控件等对象发出了一个动作后,将会产生一个事件。Visual Basic会自动调用与该事件有关的过程,该过程就是一个事件过程。
事件过程的语法是:
Private Sub <对象名>_<事件名>([<形式参数表>]) <代码段> End Sub
不同的对象所对应的事件过程的命名方式有所不同,窗体和控件都有各自的事件过程命名方式。
例如每个窗体都有自己的名称,但是不论窗体的名称是什么,在窗体的事件过程中统一用Form表示。在编写控件的事件过程时,在代码编辑窗口左侧的对象下拉列表中选择控件,在代码编辑窗口右侧的过程下拉列表中选择相应的事件名。
5.2.2 Sub过程(子过程)
Sub过程是指根据特定的实际需要而编写的,用来实现某种功能的代码块。例如,一本《Visual Basic 6.0从入门到精通》的书的出版是一个最终的结果,在这期间,出版社会找优秀的作者去写这本书,然后再找排版人员对这本书进行排版,最后由编辑对书进行审校。一本书的出版,对出版社来说并不需要完全由自己亲自去写书、排版和审校,对于写书和排版来说,只需要调用相应的人员去做即可。
子过程的语法是:
[Private|Public|Static]Sub <过程名>(<形式参数表>) <代码段> End Sub
我们创建一个子过程的时候,不需要在某个特定窗体或者模块内编写,直接在代码窗口中输入子过程的代码即可。下图建立了一个新的子过程:SubTest。
创建一个通用过程的目的就是为了调用它。由于子过程是一个独立的过程,不能通过语句直接返回值,所以要用以下两种形式调用一个子过程。
⑴ 使用Call语句:Call <过程名>([<实参表>])。
⑵ 直接使用过程名:<过程名>([<实参表>])。
“实参表”是可选项,“实参表”中的参数必须与子过程的形式参数表中的参数一一对应,并且相应位置上的参数类型也要相同。实参表中的参数可以为常量、变量或者表达式,而子过程的形式参数表对过程传递参数的描述则包括形参变量的名称和类型。
【范例5-1】 定义一个Sub子过程,主要用于进行阶乘的运算。输入一个数值,通过调用该Sub子过程,计算出该数值的阶乘值。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中。选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在Form1窗体中添加1个命令按钮控件和1个文本框控件,并将命令按钮控件的Caption属性值设置为“计算”,将文本框控件的Text值设置为空。
⑶ 在Form1窗体中双击【计算】按钮,打开代码窗口,输入以下代码(代码5-1-1.txt)。
01 Private Sub Command1_Click() 02 Dim a As lnteger,s As lnteger,total As lnteger,j As lnteger,x As lnteger,str As String 03 x=Val(Text1.Text) '将获取的文本内容转换为数值型 04 s=0 's用于得到计算的最终结果 05 str="" '初始化字符串 06 For j=1 To x '开始计数循环 07 Call fact(j,total) '调用阶乘计算的子过程,并向子过程传递两个参数 08 s=s+total '记录第1次运算的结果 09 str=str&j&"!+" '输入阶乘数 10 Next j '符合条件,进行下一次运算 11 str=str+"=" '得到最终计算结果 12 Print str;s; '输出最终计算结果 13 End Sub
⑷ 在代码窗口中编写fact子过程的代码(代码5-1-2.txt)。
01 Private Sub fact(n As lnteger,t As lnteger) '定义形式参数表 02 Dim i,s As lnteger 03 s=1 '初始化变量,用于计算阶乘的初始值 04 For i=1 To n 05 s=s*i '累积 06 Next i 07 t=s '得到结果 08 End Sub
提示
子过程是一个独立的过程,可以写在其他过程以外的任何地方,但不可以在已有过程的内部编写。为了读取程序方便,通常在只有一个子过程的情况下,可以将其放在代码段的最后面或最前面。
【运行结果】
保存程序,单击【启动】按钮,运行程序。在文本框中输入数值“7”,单击【计算】按钮,结果如图所示。
【拓展训练5-1】
在Visual Basic中不仅可以调用有返回值的函数,同时还可以调用无返回值的函数。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在Form1窗体中添加1个命令按钮控件。
⑶ 在Form1窗体中双击【Command1】按钮,进入代码窗口,输入以下代码。
01 Private Sub Command1_Click() 02 Call XS'调用子函数 03 End Sub
⑷ 在代码窗口中编写XS子过程的代码。
01 Private Sub XS() 02 Print"我是无参的" '输出字符串 03 End Sub
⑸ 保存程序,按【F5】快捷键运行程序,单击【Commad1】按钮查看程序效果。
5.2.3 Function过程(函数过程)
函数过程也是用来完成具有特定功能的代码段,其语法是:
[Private|Public|Static]Function <函数过程名>(<形式参数表>)[As<返回值类型>] <代码段> <函数过程名>=<返回值> End Function
提示
Function过程和Sub子过程有不同的地方,函数过程可以向调用过程明确地返回一个值。所以调用函数过程比调用子过程多了一种形式,共有以下3种形式。
⑴ 使用Call语句:Call <函数名>([<实参表>])。
⑵ 直接使用过程名:<函数名>([<实参表>])。
⑶ 在表达式中调用:<返回值变量>=<函数名>([<实参表>])。
【范例5-2】 定义一个Function过程,输入一个数值,通过调用Function函数,
计算出该数值的阶乘值。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在Form1窗体中添加1个命令按钮控件和1个文本框控件,并将命令按钮控件的Caption属性值设置为“计算”,将文本框控件的Text值设置为空。
⑶ 在Form1窗体中双击【计算】按钮,打开代码窗口,输入以下代码(代码5-2-1.txt)。
01 Private Sub Command1_Click() 02 Dim a As lnteger,s As lnteger,total As lnteger,j As lnteger,x As lnteger,str As String 03 x=Val(Text1.Text) '将获取的文本内容转换为数值型 04 s=0 's用于得到计算的最终结果 05 For j=1 To x '利用计数循环开始计数 06 s=s+fact(j) '调用过程函数 07 str=str&j&"!+" '格式化字符输出形式 08 Next j 09 str=str&"=" '再次格式化字符输出形式 10 Print str;s; '输出最终计算结果 11 End Sub
⑷ 在代码窗口中编写fact子过程的代码(代码5-2-2.txt)。
01 Private Function fact(n As lnteger) '定义形式参数表 02 Dim i,s As lnteger 03 s=1 '用于得到结果 04 For i=1 To n 05 s=s*l '累积 06 Next l '满足条件进行下次循环 07 fact=s '函数fact的返回值 08 End Function
【运行结果】
保存程序,单击【启动】按钮,运行程序。在文本框中输入数值“7”,单击【计算】按钮,结果如图所示。
【拓展训练5-2】
本实例主要讲解如何使用Visual Basic中提供的可视化图形窗口来创建一个过程。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 双击Form1窗体,进入代码窗口。
技巧
如果当前打开的窗口不是代码窗口,则无法进行下面的操作。
⑶ 选择【工具】【添加过程】菜单命令,打开【添加过程】对话框。
⑷ 在【名称】文本框中输入过程名,例如输入“SubTest”。
⑸ 在【类型】选项组中选中【函数】单选按钮。
注意
在【添加过程】对话框中的【类型】选项组中,可以选中【子程序】单选按钮来创建一个子过程(Sub),或者选中【函数】单选按钮来创建一个函数过程(Function)。
⑹ 在【范围】选项组中,可以选中【公有的】单选按钮来创建一个公有过程,或者选中【私有的】单选按钮来创建一个私有过程。在这里选中【私有的】单选按钮,然后单击【确定】按钮。
⑺ 这样就完成了一个函数过程的创建,但该函数过程并不能实现任何功能,而需要向函数过程中添加实现程序功能的代码。
5.2.4 参数的传递
我们使用过程的目的就是将一些数据传递给过程,过程经过计算后将结果传递出来。在调用的过程中,必须考虑调用过程和被调用过程之间的数据调用方式。在Visual Basic中,使用参数来实现主调过程和被调过程间的数据传递。
1. 形参与实参
参数在Visual Basic中根据功能被分为形式参数和实际参数两种。在编写过程的时候,我们并不知道所要计算数据的真实值,因此使用参数代表这些值,当真正的数值作为参数传递进入过程后,再将参数值替换为实际值。在过程中代表真正需要计算的值的参数就是形式参数,之所以称其为形式参数,是因为它仅仅是形式上代表真正需要计算的值。
⑴ 形式参数。形式参数(简称形参)是接收数据的变量。形式参数表中的各个变量之间用逗号分隔。形式参数表中的变量类型可以是合法的简单变量,也可以是数组,但不能是定长字符串。
⑵ 实际参数。实际参数(简称实参)是指在调用子过程或函数过程时,传递给子过程或函数过程的常量、变量或表达式。实际参数表可以由常量、表达式、合法的变量名、数组等组成,实际参数表中的各参数用逗号分隔。
2. 按地址传递和按值传递
知道了形参和实参之间的关系,现在需要知道形参和实参之间是如何传递数据的。实参与形参之间的参数传递方式有两种,即按地址传递和按值传递。
⑴ 按地址传递(By Reference)。所谓按地址传递参数,就是将实参的地址传递给相应的形参,形参与实参使用相同的内存地址单元,这样通过调用被调程序就可以改变实参的值。在进行地址传递时,实参必须是变量,常量或表达式无法进行地址传递。按地址传递是Visual Basic中系统默认的参数传递方式。
⑵ 按值传递(By Value)。所谓按值传递,就是当实参是常量时,直接将常量值传递给形参变量;当实参是变量时,仅仅将实参变量的值传递给形参变量。然后执行被调过程,在被调过程中,即使对形参发生改变也不会影响实参值的变化。我们可以把按值传递给形参的变量看做实参的一个“副本”或者“镜像”,就像镜子中的我们一样,虽然镜子中的样子和真人一模一样,但是镜子中的影像消失了并不会导致真人消失。
【范例5-3】 对整型变量进行初始化,然后调用按地址传递和按值传递的函数,再将变量传递后的结果输出,比较按地址传递和按值传递的区别。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在Form1窗体中添加两个命令按钮控件,将Command1命令按钮的Caption属性设置为“按地址传递”,将Command2命令按钮的Caption属性设置为“按值传递”。
⑶ 在Form1窗体中双击【按地址传递】按钮,打开代码窗口,输入以下代码(代码5-3-1.txt)。
01 Private Sub Command1_Click() 02 Dim a As lnteger,b As lnteger 03 a=20 '为变量a赋初值 04 b=30 '为变量b赋初值 05 Print"按地址传递(初始):a=";a,"b=";b '输出变量a和b的初始值 06 Call dizhisub(a,b) '调用名称为dizhisub的子过程 07 Print"调用子过程结束以后:a=";a,"b=";b '输出调用函数后的结果 08 Print"" '输出空行 09 End Sub
⑷ 在Form1窗体中双击【按值传递】按钮,打开代码窗口,输入以下代码(代码5-3-2.txt)。
01 Private Sub Command2_Click() 02 Dim a As lnteger,b As lnteger 03 a=20 '为变量a赋初值 04 b=30 '为变量b赋初值 05 Print"按值传递(初始):a=";a,"b=";b '输出变量a和b的初始值 06 Call zhisub(a,b)'调用名称为zhisub的子过程 07 Print"调用子过程结束以后:a=";a,"b=";b '输出调用函数后的结果 08 Print"" '输出空行 09 End Sub
⑸ 在代码窗口中编写dizhisub的子过程的代码。
01 Private Sub dizhisub(m As lnteger,n As lnteger) 02 Print"调用按地址传递的子程序(初始):m=";m,"n=";n '输出形参m和形参n的初始值 03 m=50 '为形参m重新赋值 04 n=100'为形参n重新赋值 05 Print"调用按地址传递的子程序(子程序赋值以后):m=";m,"n=";n '输出形参的新值 06 End Sub
⑹ 在代码窗口中编写zhisub的子过程的代码。
01 Private Sub zhisub(ByVal m,ByVal n) 02 Print"调用按值传递的子程序(初始):m=";m,"n=";n'输出形参m和形参n的初始值 03 m=50 '为形参m重新赋值 04 n=100'为形参n重新赋值 05 Print"调用按值传递的子程序(子程序赋值以后):m=";m,"n=";n '输出形参的新值 06 End Sub
【运行结果】
保存程序,按【F5】快捷键,运行程序。分别单击【按地址传递】按钮和【按值传递】按钮,可以看到按地址传递和按值传递后数值的变化。
5.2.5 过程的嵌套与递归
在Visual Basic中,在一个过程中调用另外一个或其他若干个过程的方法称为过程的嵌套调用,在过程中直接或间接地调用过程自身的方法则称为过程的递归调用。
1. 过程的嵌套调用
在Visual Basic中,过程的定义都是相互平行独立的,一个过程内不能包含另一个过程,在程序代码中每一个过程之间都用一条分割线隔开。
虽然不能嵌套定义过程,但在Visual Basic中提供有嵌套调用过程的方法,也就是主程序可以调用子过程,在子过程中还可以调用另外的子过程,这种程序结构称为过程的嵌套。
2. 过程的递归调用
递归调用的方法有两种:直接递归和间接递归。
⑴ 直接递归。直接递归的实例代码是:
Private Sub Sub1() '定义过程Sub1 … Call Sub1 '调用自身
… End Sub
⑵ 间接递归。间接递归的实例代码是:
Private Sub SubA() '定义过程SubA … Call SubB '调用SubB … End Sub Private Sub SubB() '定义过程SubB … Call SubA '调用SubA … End Sub
【范例5-4】 定义一个计算平方根的子过程,并在子过程中调用自己,以实现对某个数进行平方根的运算。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在窗体中添加两个命令按钮控件、两个标签控件和两个文本框控件,将两个文本框的Text属性值设置为空,将两个命令按钮控件和两个标签控件的Caption属性值按下表进行设置。
⑶ 将Form1窗体上的控件排列整齐,如图所示。
⑷ 在Form1窗体中双击【计算】按钮,打开代码窗口,输入以下代码(代码5-4-1.txt)。
01 Private Sub Command1_Click() 02 Dim x,x1,x2 As Single
03 x1=1 '为变量x1赋初值 04 x2=Val(Text1.Text) '为变量x2赋初值,并将其转换成数值型 05 x=x2 '将变量x2的值赋给变量x 06 Call sqrt(x1,x2,x) '调用计算平方根的子过程 07 Text2.Text=x '将结果显示在Text2中 08 End Sub
⑸ 在Form1窗体中双击【清除】按钮,打开代码窗口,输入以下代码。
01 Private Sub Command2_Click() 02 Text1.Text="" '清空文本框1中的内容 03 Text2.Text="" '清空文本框2中的内容 04 End Sub
⑹ 在代码窗口中编写sqrt的子过程(代码5-4-2.txt)。
01 Private Sub sqrt(y1,y2,y) 02 Dim n As lnteger '定义变量n,用于记录计算的次数 03 Dim y3 As Single '定义变量y3,用于接收计算后的值 04 Do While Abs(y1-y2)>0.000001 '判断是否大于0.000001,小于则退出循环体 05 y3=(y1+y2)/2 '将传递后的y1与y2相加并对2求模 06 lf(y3*y3-y)<=0 Then '判断平方根值是否小于等于零 07 y1=y3 '小于等于0则将平方根的值赋予y1 08 Else 09 y2=y3 '大于则将平方根的值赋予y2 10 End lf 11 n=n+1 '计算的次数加1 12 Loop 13 y=y1 '得到结果,赋值给形参 14 Print"经过"&n&"次计算,得到"&Text1.Text&"的平方根"'输出最终结果 15 End Sub
【运行结果】
保存程序,按【F5】快捷键,运行程序。在【请输入一个大于1的数】文本框中输入数值“3”,单击【计算】按钮,结果如图所示。
【拓展训练5-3】
阶乘运算的方法很多,在这里使用递归的方法进行一次阶乘的运算。
⑴ 启动Visual Basic 6.0,在弹出的【新建工程】对话框中选择【标准EXE】图标,然后单击【打开】按钮。
⑵ 在Form1窗体上添加一个命令按钮控件。
⑶ 双击From1窗体上名称为Commad1的命令按钮控件,打开代码窗口,输入以下代码(拓展代码5-3-1.txt)。
01 Private Sub Command1_Click() 02 Dim s As Long '定义长整型变量,用于接收7的阶乘值 03 Dim i As lnteger '定义整型变量,用于计数循环 04 s=0 '为变量s赋初值 05 For i=1 To 7 Step 1 '进行阶乘运算循环 06 s=s+Factorial(i) '调用Factorial函数过程 07 Next i 08 Print"用递归方法求得1!+2!+…+7!的和为:";s '输出最终的结果 09 End Sub
⑷ 在代码窗口中编写Factorial函数过程(拓展代码5-3-2.txt)。
01 Public Function Factorial(ByVal n As lnteger)As Long 02 lf n=1 Then '如果接收到的数为1 03 Factorial=1 '返回1的阶乘值 04 Else '否则递归调用函数过程 05 Factorial=Factorial(n-1)*n '返回值不为1的其他阶乘值 06 End lf 07 End Function
⑸ 保存程序,按【F5】快捷键运行程序,单击【Command1】命令按钮,结果如图所示。
5.3 高手点拨
本节视频教学录像:3分钟
本章中有两个问题,不但是本章难点,也是一些考试中常出现的问题,需要我们格外注意。
1. 确定自定义的过程是子过程还是函数过程
一般来说,函数过程名有值,子过程名无值。有一个返回值,则使用函数过程;有多个返回值或无返回值,一般使用子过程。
2. 实参与形参结合时对应问题
在使用实参与形成那对照时,要注意个数、类型、位置、次序的一一对应。
形参是按值传递,对应实参可以是表达式、常量、数组元素。
形参是按址传递,对应实参只能是简单变量。
数组、记录类型、对象只能是按地址传递。
5.4 实战练习
一、思考题
1. 简述调用Sub子过程与Function函数过程的区别是什么。
2. 参数传递有哪几种,它们的区别是什么?
二、操作题
使用Function函数实现两数平均值的计算。