VB第六章-PPT.ppt
第六章第六章 过过 程程6.1 函数过程的定义与调用函数过程的定义与调用6.2 子过程的定义与调用子过程的定义与调用6.3 参数传递参数传递6.4 递归递归6.5 变量、过程的作用域变量、过程的作用域6.6 综合应用综合应用 6.7 重点和难点重点和难点16.1 函数过程的定义函数过程的定义6.1.1 引引例例已已知知多多边边形形的的各各条条边边的的长长度度,计计算算多边形的面积。多边形的面积。计计算算多多边边形形面面积积,可可将将多多边边形形分分解解成成若若干干个个三角形。三角形。计算三角形面积的公式如下:计算三角形面积的公式如下:xyz定义函数过程定义函数过程area:Public Function area(x!,y!,z!)As Single Dim c!c=1/2*(x+y+z)area=Sqr(c*(c-x)*(c-y)*(c-z)End Function调用函数过程:调用函数过程:Sub command1_click()输入若干个三角形边长输入若干个三角形边长 S=area(a,b,c)+area(c,d,e)+area(e,f,g)Print SEnd Sub26.1.2 函数过程的定义函数过程的定义 1.自定义函数过程有两种方法自定义函数过程有两种方法 (1)利用利用“工具工具”菜单下的菜单下的“添加过程添加过程”命令定义,生成一个命令定义,生成一个函数的框架。函数的框架。(2)利用代码窗口直接定义。利用代码窗口直接定义。2.函数过程形式函数过程形式Private|Public Static Function 函数过程名函数过程名(参数列表参数列表)As 类型类型 局部变量或常数定义局部变量或常数定义 语句块语句块1 函数名函数名=返回值返回值 Exit Function 语句块语句块2 函数名函数名=返回值返回值End Function函数过程体函数过程体3 3.说明说明(1)Static、Private、Public:意义与过程的作用域有关。:意义与过程的作用域有关。(2)函数过程名:命名规则同变量名。)函数过程名:命名规则同变量名。(3)参数列表形式)参数列表形式:ByVal|ByRef形参名形参名()As 类型类型 称称为为形形参参或或哑哑元元,只只能能是是变变量量或或数数组组名名,不不能能是是常常量量、数数组组元元素素或或表表达达式式。形形参参仅仅表表示示参参数数的的个个数数、类类型型,无无值值。ByVal表表示示当当过过程程被被调调用用时时,参参数数按按值值传传递递,缺缺省省或或ByRef表表示示当当过过程程被被调调用用时时,参参数数按按地地址址传传递递。无无参参数数时时函函数数过过程程名名后后的的括括号不能省略,这是函数过程的标志。号不能省略,这是函数过程的标志。(4)AS 类型:函数返回值的类型。若省略,则返回变体类型。类型:函数返回值的类型。若省略,则返回变体类型。(5)函函数数名名=返返回回值值:在在函函数数体体内内,函函数数名名可可以以当当变变量量使使用用,函函数数的的返返回回值值就就是是对对函函数数名名的的赋赋值值语语句句实实现现的的,在在函函数数体体内内至至少对函数名赋值一次。少对函数名赋值一次。(6)Exit Function 或或End Function:表示退出函数过程。:表示退出函数过程。总之,函数过程名有值,有类型,在过程体内至少被赋值一次。总之,函数过程名有值,有类型,在过程体内至少被赋值一次。例例6.2 编一求最大公约数的函数过程。编一求最大公约数的函数过程。46.1.3函数过程的调用函数过程的调用 1.调用形式:函数过程名调用形式:函数过程名(参数列表参数列表)参数列表参数列表(称为实参或实元称为实参或实元):传递给过程的变量或表达式。:传递给过程的变量或表达式。Sub Form_Click Dim x%,y%,z%x=124:y=24 z=gcd(x,y)MsgBox(最大公约数是最大公约数是&z)End Sub 2.2.程序运程序运行流程行流程 Function gcd(m%,n%)As Integer r=m Mod n Do While(r 0)m=n:n=r:r=m Mod n Loop gcd=nEnd Function53.函数过程调用时应注意的问题函数过程调用时应注意的问题(1)参参数数列列表表称称为为实实参参,它它必必须须与与形形参参保保持持个个数数相相同同,位位置置与与类类型型一一一一对对应应(也也允允许许形形参参与与实实参参个个数数不不同同),实实参参可以是同类型的常量、变量、数组元素或表达式。可以是同类型的常量、变量、数组元素或表达式。(2)因因为为函函数数名名要要返返回回一一个个值值,所所以以函函数数调调用用不不是是一一条条独独立立的语句,不能独立存在。的语句,不能独立存在。(3)调调用用时时把把实实参参的的值值传传递递给给形形参参称称为为参参数数传传递递。值值传传递递时时实实参参的的值值不不随随形形参参的的变变化化而而变变化化,而而地地址址传传递递时时实实参参随随形参的值一起改变。形参的值一起改变。(4)当当参参数数是是数数组组时时,形形参参与与实实参参声声明明时时应应省省略略其其维维数数和和大大小,但括号不能省略。小,但括号不能省略。6例例6.3编一函数,统计字符串中汉字的个数。编一函数,统计字符串中汉字的个数。分析:在分析:在VB中,字符以中,字符以Unicode码存放,每个汉字和码存放,每个汉字和英文是一个字符、占有两个字节,区别是汉字的机内英文是一个字符、占有两个字节,区别是汉字的机内码最高位为码最高位为1,若利用,若利用Asc函数求其码值为小于函数求其码值为小于0(以补(以补码表示),而西文字符的最高位为码表示),而西文字符的最高位为0,Asc函数求其码函数求其码值为大于值为大于0。7大家应该也有点累了,稍作休息大家有疑问的,可以询问和交流大家有疑问的,可以询问和交流大家有疑问的,可以询问和交流大家有疑问的,可以询问和交流86.2 子过程的定义与调用子过程的定义与调用 6.2.1 引例引例以下情况使用函数过程存在不足:以下情况使用函数过程存在不足:v不是为了获得某个函数值,而是为了某种功能的处不是为了获得某个函数值,而是为了某种功能的处理。理。v要获得多个结果。要获得多个结果。VB中提供了使用更灵活的子过程。中提供了使用更灵活的子过程。例例6.4编一过程,对编一过程,对Label1控件进行移动,通过参数控件进行移动,通过参数Tag的值(的值(1或或-1)决定移动方向。)决定移动方向。该过程不是为了计算获得某个结果,而是进行对控件该过程不是为了计算获得某个结果,而是进行对控件移动的处理。移动的处理。96.2.2 子过程定义子过程定义 Private|Public Static Sub 子过程名子过程名(参数列表参数列表)局部变量或常数定义局部变量或常数定义 语句块语句块1 Exit Sub 语句块语句块2 End Sub 说明:(说明:(1)子过程名、形参同函数过程中对应项的规定。)子过程名、形参同函数过程中对应项的规定。(2)子过程名无值、无类型,子过程中不能给过程名赋值。)子过程名无值、无类型,子过程中不能给过程名赋值。6.2.3 子过程的调用子过程的调用 子过程名子过程名 参数列表参数列表 或或 Call 子过程名子过程名(参数列表参数列表)说明:说明:(1)若使用)若使用Call则实参列表要用括号括起来,若无则实参列表要用括号括起来,若无Call则括号可有可则括号可有可无。无。(2)若实参要获得子过程的返回值,则实参只能是变量,不能是常量)若实参要获得子过程的返回值,则实参只能是变量,不能是常量或表达式,也不能是控件名。或表达式,也不能是控件名。(3)过程调用是一条独立的语句。)过程调用是一条独立的语句。106.2.4子过程与函数过程区别子过程与函数过程区别(1)函数过程名有值,有类型,在函数体内至少赋值一次;函数过程名有值,有类型,在函数体内至少赋值一次;子过程名无值,无类型,在子过程体内不能对子过程名赋值。子过程名无值,无类型,在子过程体内不能对子过程名赋值。(2)调用时,子过程调用是一句独立的语句;调用时,子过程调用是一句独立的语句;函数过程不能作为单独的语句加以调用,必须参与表达式运算。函数过程不能作为单独的语句加以调用,必须参与表达式运算。(3)一一般般当当过过程程有有一一个个返返回回值值,使使用用函函数数过过程程较较直直观观;反反之之若若过过程程无无返返回回值值,或或有有多多个个返返回回值值,使使用用子子过过程程较较直直观观。把把某某功功能能定定义义成成函函数数或或是是过过程程,没没有有严严格格的的规规定定。但但只只要要能能用用函函数数定定义义的的,就就肯肯定定能能用用过过程程定定义义,反反之之不一定。不一定。6.2.5形参个数的确定形参个数的确定(1)形形参参是是过过程程与与主主程程序序交交互互的的接接口口,从从主主程程序序获获得得初初值值,或或将将计计算算结结果果返返回回给给主主调调程程序序。不不要要将将过过程程中中所所有有使使用用过过的的变变量量均均作作为为形形参参。若若只只在在过过程内部使用,则声明为局部变量。程内部使用,则声明为局部变量。(2)形形参参没没有有具具体体的的值值,只只代代表表了了参参数数的的个个数数、位位置置、类类型型;只只能能是是简简单单变变量、数组名,不能是常量、数组元素、表达式。量、数组名,不能是常量、数组元素、表达式。11例例6.5 分分别别编编一一统统计计字字符符串串S中中定定冠冠词词the出出现现个个数数的的子子过过程程和和函数过程,并分别调用。函数过程,并分别调用。处理方法:利用处理方法:利用InStr函数反复在字符串函数反复在字符串S找找the子串。子串。Function FuncThe%(ByVal s$)Dim Count%,i%Count=0 s=Trim(s)i=InStr(s,“the)Do While i 0 Count=Count+1 s=Mid(s,i+3)i=InStr(s,“the)Loop FuncThe=CountEnd FunctionSub ProcThe(ByVal s$,ByRef Count%)Dim i%Count=0 s=Trim(s)i=InStr(s,“the)Do While i 0 Count=Count+1 s=Mid(s,i+3)i=InStr(s,“the)Loop End Sub函数的调用:函数的调用:Label3=FuncThe(Text1)过程的调用:过程的调用:Dim n%Call ProcThe(Text1,n)Label4=n 可以看出:对同一问题定义两种过程时,只要抓住函数过程和子过程的区别,即可以看出:对同一问题定义两种过程时,只要抓住函数过程和子过程的区别,即函数名有一个值、子过程名无值的特点。当定义好函数过程后,要改为子过程,只要函数名有一个值、子过程名无值的特点。当定义好函数过程后,要改为子过程,只要将函数过程的返回结果作为子过程的形参,即在子过程中增加一个参数;反之也然。将函数过程的返回结果作为子过程的形参,即在子过程中增加一个参数;反之也然。126.3 参数传递参数传递 6.3.1 形参与实参形参与实参 在参数传递中,一般是按位置传送,也可以按名传送。在参数传递中,一般是按位置传送,也可以按名传送。按位置传送是最常用的参数传递方法,按实参的位置、按位置传送是最常用的参数传递方法,按实参的位置、次序、类型与形参的位置、次序、类型一一对应传送,与参次序、类型与形参的位置、次序、类型一一对应传送,与参数名没有关系。数名没有关系。如在调用标准函数时,用户根本不知道形参名,只要关如在调用标准函数时,用户根本不知道形参名,只要关心形参的个数、类型、位置,例如心形参的个数、类型、位置,例如Mid函数形式:函数形式:Mid(字符串字符串$,起始位,起始位%,取几位,取几位%)调用语句:调用语句:s=Mid(This is VB,9,2)则则s中的结果为中的结果为“VB”。136.3.2 传址与传值传址与传值 实参与形参的结合有传址实参与形参的结合有传址(ByRef)和传值和传值(ByVal)两种两种方法。方法。1.传址方式参数结合过程传址方式参数结合过程 当调用一个过程时,它将实参的地址传递给形参。当调用一个过程时,它将实参的地址传递给形参。因此在被调过程体中对形参的任何操作都变成了对因此在被调过程体中对形参的任何操作都变成了对相应实参的操作,实参的值就会随过程体内对形参相应实参的操作,实参的值就会随过程体内对形参的改变而的改变而改变改变。2.传值方式参数结合过程传值方式参数结合过程 当调用一个过程时,系统将实参的值复制给形参,当调用一个过程时,系统将实参的值复制给形参,实参与形参断开了联系。在过程体内对形参的任何实参与形参断开了联系。在过程体内对形参的任何操作不会影响到实参。操作不会影响到实参。14Sub Swap2(x%,y%)Dim t%t=x:x=y:y=tEnd Sub例例6.6 两个变量的交换。Sub Swap1(ByVal x%,ByVal y%)Dim t%t=x:x=y:y=tEnd SubPrivate Sub Command1_Click()Dim a%,b%a=10:b=20 Swap1 a,b Print A1=;a,B1=;b a=10:b=20 Swap2 a,b Print A2=;a,B2=;bEnd Sub153.传址与传值的选择传址与传值的选择选用传值还是传地址一般进行如下考虑:选用传值还是传地址一般进行如下考虑:(1 1)要要将将被被调调过过程程中中的的结结果果返返回回给给主主调调程程序序,则则形形参参必必须须是是传传址址方方式式。这这时时实实参参必必须须是是同同类类型型的的变变量量名名(包包括括简简单单变变量量、数数组组名名、结结构构类类型型等等),不能是常量、数组元素、表达式。,不能是常量、数组元素、表达式。(2 2)不不希希望望过过程程修修改改实实参参的的值值,则则应应选选用用传传值值方方式式,减减少少各各过过程程间间的的关关联联。因因为为在在过过程程体体内内对对形形参参的改变不会影响实参。的改变不会影响实参。(3 3)形参是数组及自定义类型时都是地址传递。)形参是数组及自定义类型时都是地址传递。16例例6.76.7如下如下sumsum子过程求数组子过程求数组a a各元素和、并改变数组各元素值:各元素和、并改变数组各元素值:Function sum%(x()As Integer)Function sum%(x()As Integer)Dim i%Dim i%sum=0 sum=0 For i=0 To UBound(x)For i=0 To UBound(x)sum=sum+x(i)sum=sum+x(i)x(i)=2*x(i)x(i)=2*x(i)Next i Next iEnd FunctionEnd Function6.3.3 数组参数的传递数组参数的传递 当参数是数组时,通过传址方式进行传递。注意:当参数是数组时,通过传址方式进行传递。注意:(1)在实参和形参中写数组名,忽略维数的定义,但圆括号不能省。)在实参和形参中写数组名,忽略维数的定义,但圆括号不能省。(2)被调过程可通过)被调过程可通过Lbound和和Ubound函数确定实参数组的下、上界。函数确定实参数组的下、上界。Private Sub Command1_Click()Dim b(),s%b=Array(1,3,5,7,9)s=sum(b()Print 数组数组b的各元素和为:的各元素和为:;s Print 数组数组b的各元素值为:的各元素值为:For i=0 To UBound(b)Print b(i);Next End Sub17Sub f1(x)x=f2(xx)*3End SubSub Command1_Click()Call f1(y)End SubFunction f2(x)f2=f3(x)+3End FunctionFunction f3(x)f3=x*xEnd FunctionSub f1(x)Call f1(y)End Sub6.4.1 过程的嵌套调用过程的嵌套调用Sub Command1_Click()Call f1(y)End Sub6.4.2 过程的递归调用过程的递归调用6.4 6.4 过程的嵌套与递归调用过程的嵌套与递归调用18 1.1.递归的概念递归的概念 用自身的结构来描述自身就称为“递归”。例对阶乘的定义:2.递归过程递归过程 过程在自身定义的内部调用自己。例例6.8 编fac(n)=n!的递归函数 Sub Command1_Click()Print“fac(4)=”;fac(4)End Sub结果:fac(4)=24Function fac(n As Integer)As Integer If n=1 Then fac=1 Elsefac=n*fac(n-1)End If End Function19递推回归在递归处理中,用栈来实现。栈中存放形参、局部变量、返回地址。在递归处理中,用栈来实现。栈中存放形参、局部变量、返回地址。递推过程:每调用自身,当前参数压栈,直到达到递归结束条件。递推过程:每调用自身,当前参数压栈,直到达到递归结束条件。回归过程:不断从栈中弹出当前的参数,直到栈空。回归过程:不断从栈中弹出当前的参数,直到栈空。递归算法设计简单,但消耗的机时和占据的内存空间比非递归大。递归算法设计简单,但消耗的机时和占据的内存空间比非递归大。思考:思考:若上述若上述fac函数中函数中少了少了:If n=1 Then fac=1 即仅有语句:即仅有语句:fac=n*fac(n-1)或或 n 1)Then 当没有到底层,递归调用当没有到底层,递归调用 u1=(x1+x2)/2 三条边的中点三条边的中点 u2=(x2+x3)/2 v1=(y1+y2)/2 Call triangle(u1,x2,u2,v1,y2,k-1)递归调用递归调用 Call triangle(x1,u1,x2,y1,v1,k-1)Call triangle(x2,u2,x3,y1,v1,k-1)Else picture1.Line(x1,y1)-(x3,y1)到达递归底层画三角形到达递归底层画三角形 picture1.Line(x1,y1)-(x2,y2)picture1.Line(x2,y2)-(x3,y1)End IfEnd Sub236.5 6.5 过程与变量的作用域过程与变量的作用域 作用域:作用域:过程、变量随所处的位置不同,可被访问的范过程、变量随所处的位置不同,可被访问的范围称为过程或变量的作用域。围称为过程或变量的作用域。VBVB工程的组成:工程的组成:应用程序(应用程序(.vbp文件)文件)至少一个或若干个窗体模至少一个或若干个窗体模块文件(块文件(.frm)可有一个或若干个标准可有一个或若干个标准模块文件(模块文件(.bas)事件过程(事件过程(Sub)自定义过程(自定义过程(Sub)自定义函数(自定义函数(Function)自定义过程(自定义过程(Sub)自定义函数(自定义函数(Function)类模块类模块(.cls)246.5.1过程的作用域过程的作用域 窗体窗体/模块级:加模块级:加Private关键字的过程,只能被定义的窗体或模块关键字的过程,只能被定义的窗体或模块中的过程调用。中的过程调用。全局级:加全局级:加Public关键字(缺省)的过程,可供该应用程序的所有关键字(缺省)的过程,可供该应用程序的所有窗体和所有标准模块中的过程调用。窗体和所有标准模块中的过程调用。256.5.2 6.5.2 变量的作用域变量的作用域 局部变量:在一个过程内用局部变量:在一个过程内用Dim或或Static语句声明的变量,只能在本过程中使用。语句声明的变量,只能在本过程中使用。模块级变量:在窗体或模块的通用声明段用模块级变量:在窗体或模块的通用声明段用Dim、Private语句声明的变量,可被语句声明的变量,可被本模块的任何过程访问。本模块的任何过程访问。全局变量:在模块级用全局变量:在模块级用Public语句声明的变量,可被应用程序的任何过程或函数访语句声明的变量,可被应用程序的任何过程或函数访问。问。26例例6.11 在下面一个标准模块文件中不同级的变量声明:在下面一个标准模块文件中不同级的变量声明:标准模块内:标准模块内:Public pa As integerPrivate mb As string*10Sub F1()Dim fa As integerEnd SubSub F2()Dim fb As SingleEnd Sub窗体内:窗体内:Public fa as integer Dim fb as integer Private Sub Form_Load()Dim i as integer End Sub Private Sub Command1_Click()Dim i as integer End Sub 请说明哪些是全局级、请说明哪些是全局级、模块级、局部变量?如模块级、局部变量?如何使用?何使用?27 注意:若在不同级声明相同的变量名注意:若在不同级声明相同的变量名,系统按局部、窗体系统按局部、窗体/模模块、全局次序访问。例如块、全局次序访问。例如:Public Temp As integer 全局变量全局变量 Sub Form_LoadSub Form_Load()()Dim Temp As IntegerDim Temp As Integer 局部变量局部变量 Temp=10 访问局部变量访问局部变量 Form1.Temp=20 访问全局变量必须加窗体名访问全局变量必须加窗体名 Print Form1.Temp,Temp 显示显示 20 10 End Sub 一一般般来来说说,在在同同一一模模块块中中定定义义了了不不同同级级而而名名字字相相同同的的变变量量时时,系系统统优优先先访访问问作作用用域域小小的的变变量量名名。若若想想访访问问全全局局变变量量,则则必必须须在在全全局局变变量量名名前前加加模模块块名名。为为了了避避免免混混淆淆,不不要要定定义义不同级别但名字相同的变量。不同级别但名字相同的变量。286.5.3 6.5.3 静态变量静态变量 在局部变量声明时:在局部变量声明时:Dim 声明,随过程的调用而分配存贮单元,每次调用都对变量声明,随过程的调用而分配存贮单元,每次调用都对变量初始化;过程体结束,变量的内容自动消失,存储单元释放。初始化;过程体结束,变量的内容自动消失,存储单元释放。Static 声明,每次调用过程,变量保持原来的值。声明,每次调用过程,变量保持原来的值。声明形式:声明形式:Static 变量名变量名 AS 类型类型 Static Function 函数过程名函数过程名(参数列表参数列表)As 类型类型 Static Sub 子过程名子过程名(参数列表参数列表)过程名前加过程名前加Static,表示该过程内的局部变量都是静态变量。,表示该过程内的局部变量都是静态变量。例例6.12 编一程序,利用局部变量编一程序,利用局部变量count统计单击窗体的次数。统计单击窗体的次数。Private Sub Form_Click()Dim count%count=count+1 Print count;“次次”End SubStatic29 1.1.数制转换数制转换 例例6.13 将一个十进制整数将一个十进制整数m转换成转换成 r(216)进制字符串,并对进制字符串,并对八、十六进制数调用内部函数加以验证。八、十六进制数调用内部函数加以验证。方法:将方法:将m不断除不断除 r 取余数,直到商为零,以反序得到结果。取余数,直到商为零,以反序得到结果。6.6 6.6 综合应用综合应用30Function TD(ByVal m%,ByVal r%)TD=Do While m 0 c=m Mod r If c 9 Then 超过超过9转换成对应的转换成对应的AZ十六进制表示形式十六进制表示形式 TD=Chr(c-10+65)&TD Else TD=c&TD End If m=m r LoopEnd Function31Private Sub Command1_Click()Dim m0%,r0%m0=Val(Text1)输入十进制正整数输入十进制正整数 r0=Val(Text2)输入输入r进制进制 If r0 16 Then MsgBox(数制超出范围数制超出范围):End Text3=TD(m0,r0)调用转换函数,显示转换结果调用转换函数,显示转换结果End SubPrivate Sub Command2_Click()Text4=Oct(Val(Text1)调用调用Oct函数转换成八进制数函数转换成八进制数End SubPrivate Sub Command3_Click()Text5=Hex(Val(Text1)调用调用Hex函数转换成十六进制数函数转换成十六进制数End Sub32R进制转换为十进制:进制转换为十进制:Function ct(s$,r%)As Long Dim i%,c As String*1,p&p=0 For i=1 To Len(s)c=Mid(s,i,1)Select Case UCase(c)Case 0 To 9 p=p*r+Val(c)Case A To“F p=p*r+Asc(c)-Asc(A)+10 End Select Next i ct=pEnd Function332.2.加密和解密加密和解密 简单加密的思想是:将每个字母简单加密的思想是:将每个字母C加一序数加一序数K,式子,式子 c=chr(Asc(c)+k),例如序数例如序数k为为5,这时,这时 “A”“F”,“a”“f”,“B”“G”当加序数后的字母超过当加序数后的字母超过“Z”或或“z”则则 c=chr(Asc(c)+k-26)。解密为加密的逆过程。解密为加密的逆过程。例例6.14 编一加密和解密的程序。编一加密和解密的程序。34Function Code$(ByVal s$,ByVal Key%)Dim c As String*1,iAsc%Code=For i=1 To Len(s)c=Mid$(s,i,1)取第取第i个字符个字符 Select Case c Case A To Z 大写字母加序数大写字母加序数Key加密加密 iAsc=Asc(c)+Key If iAsc Asc(Z)Then iAsc=iAsc-26 加密后字母超过加密后字母超过Z Code=Code+Chr(iAsc)Case a To z iAsc=Asc(c)+Key 小写字母加序数小写字母加序数Key加密加密 If iAsc Asc(z)Then iAsc=iAsc-26 Code=Code+Chr(iAsc)Case Else 当第当第i个字符不加密时个字符不加密时,与加密字符串的前与加密字符串的前i-1个字符连接个字符连接 Code=Code+c End Select Next iEnd FunctionPrivate Sub Command1_Click()加密事件加密事件 Text2=Code(Text1,2)调用调用End Sub35Function ReCode(ByVal s$,ByVal Key%)Dim c As String*1,iAsc%ReCode=For i=1 To Len(s)c=Mid$(s,i,1)取第取第i个字符个字符 Select Case c Case A To Z 大写字母加序数大写字母加序数Key加密加密 iAsc=Asc(c)-Key If iAsc Asc(A)Then iAsc=iAsc+26 加密后字母超过加密后字母超过Z ReCode=ReCode+Chr(iAsc)Case a To z iAsc=Asc(c)-Key 小写字母加序数小写字母加序数Key加密加密 If iAsc Asc(a)Then iAsc=iAsc+26 ReCode=ReCode+Chr(iAsc)Case Else 当第当第i个字符不加密时个字符不加密时,与前与前i-1个字符连接个字符连接 ReCode=ReCode+c End Select Next iEnd Function363.3.查找查找(1)顺序查找顺序查找 例例6.15。顺序查找根据查找的关键值与数组中的元素逐顺序查找根据查找的关键值与数组中的元素逐一比较一比较(数组可无序数组可无序)Public Sub Search(a()As Variant,ByVal key,index%)Dim i%For i=LBound(a)To UBound(a)If key=a(i)Then 找到,元素的下标在找到,元素的下标在index中,结束查找中,结束查找 index=i Exit Sub End If Next i index=-1 End SubPrivate Sub Form_Click()Dim b()As Variant b=Array(1,3,5,7,9,2,4)k=Val(InputBox(指定数据指定数据1-5,7,9)Call Search(b,k,n%)If n=-1 Then Print 没找到!没找到!Else Print nEnd Sub37Keya(mid)则则low=mid+1 查找区域缩小一半查找区域缩小一半,继续继续直到找到或查找区直到找到或查找区域中无元素域中无元素。本例可以用递归实现,也可以用循环实现。本例可以用递归实现,也可以用循环实现。Sub birsearch(a(),low%,high%,key ,index%)(2)二分法查找二分法查找要查找的数组必须有序。要查找的数组必须有序。思想:要查找的关键值思想:要查找的关键值Key同数组的中间同数组的中间mid项元素比较项元素比较:12345678111222333444555666777888Lowhighmid444Key38递归过程:递归过程:Sub birsearch(a(),ByVal low%,ByVal high%,ByVal key,index%)Dim mid As Integer mid=(low+high)2 取查找区间的中点取查找区间的中点 If a(mid)=key Then index=mid 查找到,返回查找到的下标查找到,返回查找到的下标 Exit Sub ElseIf low high Then 二分法查找区间无元素,查找不到二分法查找区间无元素,查找不到 index=-1 Exit Sub End If If key a(mid)Then 查找区间在上半部查找区间在上半部 high=mid-1 Else low=mid+1 查找区间在下半部查找区间在下半部 End If Call birsearch(a,low,high,key,index)递归调用查找函数递归调用查找函数End Sub39非递归过程:非递归过程:Sub search(a(),ByVal low%,ByVal high%,ByVal key,index%)Dim mid As Integer index=-1 Do While low high mid=(low+high)2 取查找区间的中点取查找区间的中点 If a(mid)=key Then index=mid 查找到,返回查找到的下标查找到,返回查找到的下标 Exit Sub ElseIf key a(mid)Then high=mid 1 Else low=mid+1 End if LoopEnd SubPrivate Sub Command1_Click()Dim b()As Variant b=Array(5,13,19,21,37,56,64,75,80,88,92)Call birsearch(b,LBound(b),UBound(b),21,n%)Print nEnd Sub404.4.例例6.16 6.16 高次方程求根高次方程求根 有有牛顿迭代法、二分法、弦截法等牛顿迭代法、二分法、弦截法等(1)牛顿迭代法)牛顿迭代法迭代公式:迭代公式:思想:思想:对方程给定一个初值对方程给定一个初值x0作为方程的作为方程的 近似根,利用迭代公式,求得近似根,利用迭代公式,求得x1,当当 x1为求得的近似根,否则为求得的近似根,否则x1作为作为x0再迭代。再迭代。41Public Sub newton(ByVal x0#,x#,ByVal eps#)Dim fx#,f1x#Do fx=3*x0*x0*x0-4*x0*x0-5*x0+13 f1x=9*x0*x0-8*x0-5 x=x0-fx/f1x if Abs(x-x0)0.00001 c=(a+b)/2 If f(c)=0 Then Exit Do ElseIf f(a)*f(c)0 Then a=c Else b=c End If Loop halfRoot=cEnd Function435.5.字符串处理字符串处理例例6.17 编写一个英文打字训练的程序编写一个英文打字训练的程序.要求如下:要求如下:(1)在文本框内随机产生在文本框内随机产生30个字母的范文;个字母的范文;(2)当焦点进入文本框时开始计时,并显示当时时间;当焦点进入文本框时开始计时,并显示当时时间;(3)在键入文本框按产生的范文输入相应的字母;在键入文本框按产生的范文输入相应的字母;(4)当键入满了当键入满了30个字母后结束计时,禁止向文本框输入内容个字母后结束计时,禁止向文本框输入内容,与范文逐一比,与范文逐一比较,显示打字的速度和正确率。较,显示打字的速度和正确率。44Dim t As Date,per%Private Sub Command1_Click()产生产生30个字母的范文个字母的范文 Randomize For i=1 To 30 a=Chr$(Int(Rnd*26)+65)随机产生大写字母随机产生大写字母 Text1=text1+a 产生的字母连入范文框产生的字母连入范文框 Next i Text2.Locked=False End SubPrivate Sub Command2_Click()EndEnd SubPrivate Sub Text2_GotFocus()t=Time 键入文本框获得焦点键入文本框获得焦点,开始计时开始计时 Text3=TimeEnd SubPrivate Sub Command3_Click()Text1=“:Text2=“:Text3=“:Text4=ProgressBar1.Value=0 per=0End Sub45Private Sub Text2_KeyPress(KeyAscii As Integer)per=per+1 If per=30 Then ProgressBar1.Value=Int(per/30*100)If Len(Text2)=30 Then 键入满键入满30个字符个字符 t2=DateDiff(“s”,t,Time)计算时间计算时间 Text3=30 t2&字字/秒秒 显示速度显示速度 Text2.Locked=True 不允许再修改不允许再修改 y=0:n=0 For i=1 To 30 比较正确率比较正确率 If Mid(Text1,i,1)=Mid(Text2,i,1)Then y=y+1 Else n=n+1 End If Next i y=y/(y+n)*100 Text4=Format(y,0.00)&%显示正确率显示正确率 End If End Sub466.7 重点和难点 1.确定自定义的过程是子过程还是函数过程确定自定义的过程是子过程还是函数过程 函数过程名有值,子过程名无值。函数过程名有值,子过