第6章过程6.1函数过程的定义和调用引例6.1已知多边形各条边的长度,计算多边形的面积。计算多边形面积,可将多边形分解成若干个三角形。计算三角S2形面积的公式如下:S3farea= /c(c-x)(c-y)(c-z)(x+y+2)a6.1.1引例定义函数过程areaFunction area(x!, yl, z!)As SingleDim c!c=1/2*(x+y+z)area=Sqrt(c *(c -x)* (c-y)* (c-z)End FunctionSubcommand1_click().输入若干个三角形边长S=area(a,b,c)+area(c,d,e)+area(e,f,g)msgbox(“面积=”&S)End Sub6.1.2函数过程的定义在窗体、模块等的代码窗口把插入点放在所有现有过程之外,直接输入函数过程。定义函数过程的形式如下:[Public|Private]Function函数过程(形参)[As类型]变量声明语句块Return表达式或函数名=表达式EndFunction函数过程的定义+Public全局函数过程,可被程序任何模块调用Private仅供本模块中的其它过程调用心形参(或称哑元)只能是变量或数组名()仅表示参数的个数、类型,无值。例6.2编一求最大公约数的函数过程Functiongcd(m%,n%)AsIntegerIf m<n Then t = m: m = n: n = tDowhilen>0r=mModn:m=n:n=rLoopgcd=mEnd Function6.1.3函数过程的调用调用形式:函数过程名([参数列表])参数列表(称为实参或实元):必须与形参个数相同,位置与类型一一对应。可以是同类型的常量、变量、表达式
a b e d f g S1 c S2 S3 ( ) 2 1 area = c(c − x)(c − y)(c − z) c = x + y + z 第 6 章 过 程 6.1 函数过程的定义和调用 引例 6.1 已知多边形各条边的长度,计算多边形的面积。 计算多边形面积,可将多边形分解成若干个三角形。计算三角 形面积的公式如下: 6.1.1 引例 定义函数过程 area Function area(x!, y!, z!) As Single Dim c! c = 1 / 2 * (x + y + z) area = Sqrt(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) msgbox(“面积=” & S) End Sub 6.1.2 函数过程的定义 在窗体、模块等的代码窗口把插入点放在所有现有过程之外,直接输入函数过程。定义 函数过程的形式如下: [Public |Private] Function 函数过程(形参)[As 类型] 变量声明 语句块 Return 表达式 或 函数名=表达式 End Function 函数过程的定义 ❖ Public 全局函数过程,可被程序任何模块调用 ❖ Private 仅供本模块中的其它过程调用 ❖ 形参(或称哑元) 只能是变量或数组名( ),仅表示参数的个数、类型,无值。 例 6.2 编一求最大公约数的函数过程 Function gcd( m%, n%) As Integer If m < n Then t = m: m = n: n = t Do while n<>0 r = m Mod n : m = n: n = r Loop gcd = m End Function 6.1.3 函数过程的调用 调用形式:函数过程名([参数列表]) 参数列表(称为实参或实元):必须与形参个数相同,位置与类型一一对应。可以是同类 型的常量、变量、表达式
SubForm ClickDim x%, y%, z%X= 124: y= 24z= gcd(x, y)MsgBox("最大公约数是"&z)End SubFunctiongcd(m%,n%)AsIntegerIf m<n Then t = m: m =n: n =tDowhilen>0r=mModn:m=n:n=rLoopgcd=mEnd Function函数过程的调用例6.3编一函数,统计字符串中汉字的个数。分析:在VB中,字符以Unicode码存放,每个汉字和英文是一个字符、占有两个字节区别是汉字的机内码最高位为1,若利用Asc函数求其码值为小于0(以补码表示),而西文字符的最高位为0,Asc函数求其码值为大于0。Forn2口回区输入字符串显示统计的结果C/C++程序设计有4个汉字数windowsXP开发技术Unix操作系统有4个汉字数5VB.NET程设计有4个汶学数大学计算机基础者7个没字数有4个汶字【统计没学个”windowsXP开发技术6.2子过程的定义与调用6.2.1引例以下情况使用函数过程存在不足:不是为了获得某个函数值,而是为了某种功能的处理。*要获得多个结果。VB中提供了使用更灵活的子过程。例6.4编一过程,对Label1控件进行移动,通过参数Tag的值(1或-1)决定移动方向。该过程不是为了计算获得某个结果,而是进行对控件移动的处理。6.2.2子过程的定义子过程定义的方法同函数过程,形式如下:Sub子过程名[(参数列表)]局部变量或常数定义语句[Exit Sub]语句End Sub子过程名、形参同函数过程中对应项的规定,当无形参时不要括号
Sub Form_Click Dim x%, y%, z% x = 124: y = 24 z = gcd(x, y) MsgBox("最大公约数是" & z) End Sub Function gcd( m%, n%) As Integer If m < n Then t = m: m = n: n = t Do while n<>0 r = m Mod n : m = n: n = r Loop gcd = m End Function 函数过程的调用 例 6.3 编一函数,统计字符串中汉字的个数。 分析:在 VB 中,字符以 Unicode 码存放,每个汉字和英文是一个字符、占有两个字节, 区别是汉字的机内码最高位为 1,若利用 Asc 函数求其码值为小于 0(以补码表示),而西 文字符的最高位为 0,Asc 函数求其码值为大于 0 。 6.2 子过程的定义与调用 6.2.1 引例 以下情况使用函数过程存在不足: ❖ 不是为了获得某个函数值,而是为了某种功能的处理。 ❖ 要获得多个结果。 VB 中提供了使用更灵活的子过程。 例 6.4 编一过程,对 Label1 控件进行移动,通过参数 Tag 的值(1 或-1)决定移动方向。 该过程不是为了计算获得某个结果,而是进行对控件移动的处理。 6.2.2 子过程的定义 子过程定义的方法同函数过程,形式如下: Sub 子过程名[(参数列表)] 局部变量或常数定义 语句 [Exit Sub] 语句 End Sub 子过程名、形参同函数过程中对应项的规定,当无形参时不要括号
子过程与函数过程的区别◆把某功能定义为函数过程还是子过程,没有严格的规定。一般若程序有一个返回值时,函数过程直观:当有多个返回值时,习惯用子过程。→函数过程必须有返回值,函数名有类型。子过程名没有值,过程名没有类型,不能在子过程体内对子过程名赋值。参数问题→形参是过程与主调程序交互的接口,从主调程序获得初值,或将计算结果返回给主调程序。不要将过程中所有使用过的变量均作为形参。→形参没有具体的值,只代表了参数的个数、位置、类型;只能是简单变量、数组名,不能是常量、数组元素、表达式。6.2.3子过程调用子过程的调用是一句独立的调用语句,有两种形式:Call子过程名[(实参列表)]子过程名([实参列表})用Call关键字时,若有实参,则实参必须用圆括号括起,无实参圆括号省略注意:若实参要获得子过程的返回值,则实参只能是变量(与形参同类型的简单变量、数组名、结构类型),不能是常量、表达式,也不能是控件名。6.2.3子过程调用例6.5分别编一统计字符串S中定冠词The出现个数的子过程和函数过程,并分别调用。处理方法:利用InStr函数反复在字符串S找The子串。对同一问题定义两种过程时,只要抓住函数过程和子过程的区别,即函数名有一个值、子过程名无值的特点。当定义好函数过程后,要改为子过程,只要将函数过程的返回结果作为子过程的形参,即在子过程中增加一个参数:反之也然。6.3参数传递6.3.1形参与实参在参数传递中,一般是按位置传送,按实参的位置次序与形参的位置次序对应传送,与参数名没有关系。按位置传送是最常用的参数传递方法,如在调用标准函数时,用户根本不知道形参名,只要关心形参的个数、类型、位置,例如Mid函数形式:Mid(字符串S,起始位%,取几位%)调用语句:s=Mid("ThisisVB",9,2)则s中的结果为"VB"。6.3.2传址与传值实参与形参的结合有传址(ByRef)和传值(ByVal)两种方法。*传址方式参数结合过程当调用一个过程时,它将实参的地址传递给形参。因此在被调过程体中对形参的任何操作都变成了对相应实参的操作,实参的值就会随过程体内对形参的改变而改变。传值方式参数结合过程当调用一个过程时,系统将实参的值复制给形参,实参与形参断开了联系。在过程体内对形参的任何操作不会影响到实参。ByVal传值传地址例6.6传址与传值10实参10:XX形参10a的地址
子过程与函数过程的区别 ◆ 把某功能定义为函数过程还是子过程,没有严格的规定。一般若程序有一 个返回值时,函数过程直观;当有多个返回值时,习惯用子过程。 ◆ 函数过程必须有返回值,函数名有类型。子过程名没有值,过程名没有类 型,不能在子过程体内对子过程名赋值。 参数问题 ◆ 形参是过程与主调程序交互的接口,从主调 程序获得初值,或将计算结 果返回给主调程序。不要将过程中所有使用过的变量均作为形参。 ◆ 形参没有具体的值,只代表了参数的个数、位置、类型;只能是简单变量、 数组名,不能是常量、数组元素、表达式。 6.2.3 子过程调用 子过程的调用是一句独立的调用语句,有两种形式: Call 子过程名[(实参列表)] 子过程名 ([实参列表]) 用 Call 关键字时,若有实参,则实参必须用圆括号括起,无实参圆括号省略 注意:若实参要获得子过程的返回值,则实参只能是变量(与形参同类型的简单变量、 数组名、结构类型),不能是常量、表达式,也不能是控件名。 6.2.3 子过程调用 例 6.5 分别编一统计字符串 S 中定冠词 The 出现个数的子过程和函数过程,并分别调 用。 处理方法:利用 InStr 函数反复在字符串 S 找 The 子串。 对同一问题定义两种过程时,只要抓住函数过程和子过程的区别,即函数名有一个值、 子过程名无值的特点。当定义好函数过程后,要改为子过程,只要将函数过程的返回结果作 为子过程的形参,即在子过程中增加一个参数;反之也然。 6.3 参数传递 6.3.1 形参与实参 在参数传递中,一般是按位置传送,按实参的位置次序与形参的位置次序对应传送,与 参数名没有关系。 按位置传送是最常用的参数传递方法,如在调用标准函数时,用户根本不知道形参名, 只要关心形参的个数、类型、位置,例如 Mid 函数形式: Mid(字符串$,起始位%,取几位%) 调用语句:s=Mid("This is VB" ,9,2) 则 s 中的结果为“VB”。 6.3.2 传址与传值 实参与形参的结合有传址(ByRef)和传值(ByVal)两种方法。 ❖ 传址方式参数结合过程 当调用一个过程时,它将实参的地址传递给形 参。因此在被调过程体中对形参的任何操作都变成了对相应实参的操作,实参的值 就会随过程体内对形参的改变而改变。 ❖ 传值方式参数结合过程 当调用一个过程时,系统将实参的值复制给形 参,实参与形参断开了联系。在过程体内对形参的任何操作不会影响到实参。 例 6.6 传址与传值 10 a 的地址 10 10 a a x x 形参 实参 ByVal 传值 传地址
传址与传值选用传值还是传地址一般进行如下考虑:口要将被调过程中的结果返回给主调程序,则形参必须是传址方式。这时实参必须是同类型的变量名(包括简单变量、数组名、结构类型等),不能是常量、表达式。口不希望过程修改实参的值,则应选用传值方式,减少各过程间的关联。因为在过程体内对形参的改变不会影响实参。口形参是数组都是地址传递(可表示值传递或地址传递)。6.3.3数组参数的传递例6.7如下sum子过程求数组a各元素和、并改变数组各元素值:Function sum%(By Val x() As Integer)Dim i%sum = 0For i=O To UBound(x)sum += x(i): x(i) =2 * x(i)NextiEnd Function数组参数的传递心形参是数组:要以数组名加圆括号表示,不要给出维数上界:多维数组,每维以逗号分隔。在过程中通过Ubound函数确定每维的上界。*实参是数组:要给出数组名(不需要圆括号)。当数组作为参数传递时,系统将实参数组的起始地址传给过程,使形参数组也具有与实参数组相同的起始地址。6.3.4变量的作用域块变量:在控制结构块中声明的变量,只能在本块内有效。心过程级变量:在一个过程内用Dim或Static语句声明的变量,只能在本过程中使用。4模块级变量:在模块内、任何过程外用Dim、Private语句声明的变量,可被本模块的任何过程访问。全局变量在模块级用Public语句声明的变量,可被应用程序的任何过程或函数访问。变量的作用域例如在下面一个标准模块文件中不同级的变量声明:·全局变量Public PaAs integerPrivateMbAs string *10·窗体/模块级变量Sub F1()DimFa。过程级变量aAsintegerEnd SubSubF2()Dim FbAsSingle“过程级变量For i=1 to 10Dim k%“块变量
传址与传值 选用传值还是传地址一般进行如下考虑: ❑ 要将被调过程中的结果返回给主调程序,则形参必须是传址方式。这时 实参必须是同类型的变量名(包括简单变量、数组名、结构类型等),不能是常量、 表达式。 ❑ 不希望过程修改实参的值,则应选用传值方式,减少各过程间的关联。 因为在过程体内对形参的改变不会影响实参。 ❑ 形参是数组都是地址传递(可表示值传递或地址传递)。 6.3.3 数组参数的传递 例 6.7 如下 sum 子过程求数组 a 各元素和、并改变数组各元素值: Function sum%(ByVal x() As Integer) Dim i% sum = 0 For i = 0 To UBound(x) sum += x(i):x(i) = 2 * x(i) Next i End Function 数组参数的传递 ❖ 形参是数组:要以数组名加圆括号表示,不要给出维数上界;多维数组, 每维以逗号分隔。在过程中通过 Ubound 函数确定每维的上界。 ❖ 实参是数组:要给出数组名(不需要圆括号)。 ❖ 当数组作为参数传递时,系统将实参数组的起始地址传给过程,使形参数 组也具有与实参数组相同的起始地址。 6.3.4 变量的作用域 ❖ 块变量:在控制结构块中声明的变量,只能在本块内有效。 ❖ 过程级变量:在一个过程内用 Dim 或 Static 语句声明的变量,只能在本 过程中使用。 ❖ 模块级变量:在模块内、任何过程外用 Dim、Private 语句声明的变量, 可被本模块的任何过程访问。 ❖ 全局变量 在模块级用 Public 语句声明的变量,可被应用程序的任何过 程或函数访问。 变量的作用域 例如在下面一个标准模块文件中不同级的变量声明: Public Pa As integer ' 全局变量 Private Mb As string *10 ' 窗体/模块级变量 Sub F1( ) Dim Fa As integer ‘ 过程级变量 . End Sub Sub F2( ) Dim Fb As Single ‘过程级变量 For i=1 to 10 Dim k% ‘ 块变量
NextiEnd Sub6.3.5静态变量静态变量:程序运行过程中可保留变量的值声明形式:Static变量名[AS类型]用Dim声明的变量,每次调用过程时重新初始化。例6.10比较Dim和Static两者的区别。SubButtonl_Click(......)HandlesButtonl.ClickDimi%,isum%Fori=1 To5isum = sum(i)Textl.Text&="isum="&isum&vbCrLfNextiEnd SubFunctionsum(ByVal nAssInteger)StaticjAsIntegerj=j+nsum=jEnd Function6.4递归用自身的结构来描述自身就称为递归。递归过程在自身定义的内部调用自己。例6.12编fac(n)=n!的递归函数Function fac(n As Integer)As IntegerIfn=1 Thenfac = 1Elsefac =n * fac(n - 1)End IfEndFunction最典型的例子是阶乘运算,作如下的定义:递归结构递推过程:每调用自身,当前参数压栈,直到达到递归结束条件。回归过程:不断从栈中弹出当前的参数,直到栈空。递归算法设计简单,但消耗的机时和占据的内存空间比非递归大由此可见构成递归的结构如下:1)递归结束条件及结束时的值;2)能用递归形式表示,并且递归向终止条件发展。6.5综合应用6.5.1数制转换不同进制数之间的转换,可通过编程来实现:也可通过VB提供的内部函数:十进制转换为八进制函数(Oct)、转换为十六进制函数(Hex)来实现。例6.13编一函数,实现一个十进制整数转换成二至十六任意进制的字符。一个十进制正整数m转换成r进制数的思路:将m不断除r取余数(若余数超过9,还要进行相应的转换例如10变成A,11变成B等),直到商为零,以反序得到结果,即最后得到的余数在最高
Next i End Sub 6.3.5 静态变量 静态变量:程序运行过程中可保留变量的值 声明形式:Static 变量名 [AS 类型] 用 Dim 声明的变量,每次调用过程时重新初始化。 例 6.10 比较 Dim 和 Static 两者的区别。 Sub Button1_Click(.) Handles Button1.Click Dim i% ,isum% For i = 1 To 5 isum = sum(i) Text1.Text &= "isum=" & isum & vbCrLf Next i End Sub Function sum(ByVal n As Integer) Static j As Integer j = j + n sum = j End Function 6.4 递归 用自身的结构来描述自身就称为递归。递归过程在自身定义的内部调用自己。 例 6.12 编 fac(n)=n! 的递归函数 Function fac(n As Integer) As Integer If n = 1 Then fac = 1 Else fac = n * fac(n - 1) End If End Function 最典型的例子是阶乘运算,作如下的定义: 递归结构 递推过程:每调用自身,当前参数压栈,直到达到递归结束条件。 回归过程:不断从栈中弹出当前的参数,直到栈空。 递归算法设计简单,但消耗的机时和占据的内存空间比非递归大 由此可见构成递归的结构如下: 1)递归结束条件及结束时的值; 2)能用递归形式表示,并且递归向终止条件发展。 6.5 综合应用 6.5.1 数制转换 不同进制数之间的转换,可通过编程来实现;也可通过 VB 提供的内部函数:十进制转 换为八进制函数(Oct)、转换为十六进制函数(Hex)来实现。 例 6.13 编一函数,实现一个十进制整数转换成二至十六任意进制的字符。一个十进制 正整数 m 转换成 r 进制数的思路:将 m 不断除 r 取余数(若余数超过 9,还要进行相应的转换, 例如 10 变成 A,11 变成 B 等),直到商为零,以反序得到结果,即最后得到的余数在最高