590 likes | 754 Views
第 5 章 过 程. 5.1 过程的定义与调用 5.2 变量的作用域. 5.1 过程的定义与调用. 在 VB 中是用过程来实现程序模块的。将一个程序分成若干个相对独立的过程,每个过程可实现单一的功能。由于各个模块的层次分明,因此也便于程序的阅读。 VB 除了可以使用前面已介绍的事件过程外,还可以使用 Sub 过程(子程序) 和 Function 过程(函数) 。. 5.1.1 Sub 过程的定义与调用. 【 例 5.1】 在窗体上添加两个命令按钮。. 单击时, 显示 10 个*. 单击时,根据输入框中输入的整数,显示 n 个*.
E N D
第5章 过程 5.1 过程的定义与调用 5.2 变量的作用域
5.1 过程的定义与调用 在VB中是用过程来实现程序模块的。将一个程序分成若干个相对独立的过程,每个过程可实现单一的功能。由于各个模块的层次分明,因此也便于程序的阅读。VB除了可以使用前面已介绍的事件过程外,还可以使用Sub过程(子程序)和 Function过程(函数)。
【例5.1】在窗体上添加两个命令按钮。 单击时, 显示10个* 单击时,根据输入框中输入的整数,显示n个*
Private Sub Command1_Click() Call prt(10) End Sub Private Sub Command2_Click() n% = Val(InputBox(“请输入整数:”)) If n% <> 0 Then Call prt(n%) Else Exit Sub End If Print "$ $ $ $ $" End Sub 调用名为prt的Sub过程 退出本命令按钮的单击事件过程
输出n个* 定义名为prt的Sub过程 Private Sub prt(n As Integer) For i = 1 To n Print "* "; Next i Print End Sub 换行
说明: • 程序中的第3个模块编写了两个单击事件都需要使用的一段代码,该模块叫做子程序(Sub)过程。子程序过程不与任何特定的事件相联系,而是被其他的过程来调用。调用子程序过程相当于执行该过程的程序代码(执行后返回到主调过程,并继续执行调用处下面的语句)。
子程序体 子程序过程的一般定义格式为: [Private|Public][Static]Sub 子程序名 ([形参列表]) 语句组1 [Exit Sub] [语句组2] End Sub 强制退出子程序
格式说明: • 关键字Private和Public中最多只能选其一。使用Private,表示该过程是私有的局部过程,只能被该过程所在的窗体或标准模块中的其他过程所调用。使用Public,表示该过程是公共的全局过程,可被应用程序中的任何窗体或任何标准模块中的过程所调用。VB默认所有标准模块中的子程序是Public。关键字Static的作用在5.2节中介绍。
调用子程序过程的一般形式: 第一种形式:Call 子程序名[(实参列表)] 第二种形式:子程序名[实参列表] 若带有实参,则实参必须用括号括起 实参可直接加在子程序名后面
【例5.2】按值和按地址传递参数示例。根据下图所示的窗体设计界面。【例5.2】按值和按地址传递参数示例。根据下图所示的窗体设计界面。 单击时,观察运行结果
程序代码: Private Sub Command1_Click() a$ = Text1.Text b$ = Text2.Text Call swap((a$), b$) Text1.Text = a$ Text2.Text = b$ End Sub Private Sub swap(a As String,b As String) t$ = a a = b b = t$ End Sub 调用swap子程序 实参形式不同 定义名为swap的Sub过程
说明: • 调用语句中的实参(a$)和b$形式不同,表示的意义也是不同的。 • (a$):在被调过程中对形参的任何改变,都不会影响实参变量本身 • b$:在被调过程中对形参的任何操作,都意味着对实参的操作
VB除了用加括弧的方式区分按值或按址传递参数外,还可以在定义过程时,在相应的形参前加关键字ByVal或ByRef表示。按址传递是默认方式VB除了用加括弧的方式区分按值或按址传递参数外,还可以在定义过程时,在相应的形参前加关键字ByVal或ByRef表示。按址传递是默认方式
【例5.3】在窗体上添加两个文本框和两个命令按钮。【例5.3】在窗体上添加两个文本框和两个命令按钮。 切换到第2个窗体 回到第1个窗体 单击时,显示3个文本框中的最大值 单击时,交换两个文本框中的内容
在标准模块中定义的全局过程的程序代码: PublicSub swap(x As String,y As String) t$ = x x = y y = t$ End Sub 定义名为swap的全局级子程序
窗体1程序代码: Private Sub Command1_Click() a$ = Text1.Text b$ = Text2.Text Call swap(a$, b$) Text1.Text = a$ Text2.Text = b$ End Sub Private Sub Command2_Click() Form2.Show Form1.Hide End Sub 调用名为swap的子程序
窗体2程序代码: Private Sub Command1_Click() a$ = Text1.Text b$ = Text2.Text c$ = Text3.Text d$ = a$ If Val(d$) < Val(b$) Then Call swap(d$, b$) If Val(d$) < Val(c$) Then Call swap(d$, c$) Text4.Text = d$ End Sub Private Sub Command2_Click() Form1.Show Form2.Hide End Sub d$、b$按址传给swap中的形参x,y
说明: • 在标准模块的声明段中用关键字Public定义的子程序为全局级子程序,这种子程序可被应用程序中的任何模块所调用。本例中Form1和Form2窗体就分别调用了全局级子程序swap,完成相同的交换功能;
【例5.4】函数过程的示例。在窗体上添加两个标签、两个文本框和两个命令按钮。【例5.4】函数过程的示例。在窗体上添加两个标签、两个文本框和两个命令按钮。 单击时,计算1~n之间所有数之和 单击时,计算1~n之间所有数的平均值
程序代码: Private Sub Command1_Click() Text2.Text = sum(Val(Text1.Text)) Label2.Caption = “总和是” End Sub Private Sub Command2_Click() n% = Val(Text1.Text) Text2.Text = sum(n%) / n% Label2.Caption = “平均值是” End Sub 调用sum函数过程
定义名为sum的函数过程 PrivateFunction sum(n As Integer) For i = 1 To n s = s + I Next I sum = s End Function 为函数名sum 赋值
说明: • 本例用到过程的另一种形式:函数过程。在解决实际问题时,如果没有现成的函数可用时,我们可以自定义函数过程。函数过程同Sub过程一样也是由一段独立的代码组成,可以被某个过程多次调用
函数体 定义函数过程的一般格式为: [Private|Public][Static] Function 函数名 [(形参列表)][As 类型] 语句组1 [函数名=函数返回结果 Exit Function] 语句组2 函数名=函数返回结果 End Function 在函数体内至少 对函数名赋值一次
函数过程的调用 函数过程的调用同标准函数调用,其形式为: 函数过程名([实参列表]) 注意: 实参数列表中的个数必须与形参个数相同,位置与类型一一对应。可以是同类型的常量、变量、表达式。
【例5.5】计算1!+2!+3!+……+20!的值。在窗体上添加一个标签、一个文本框和两个命令按钮。【例5.5】计算1!+2!+3!+……+20!的值。在窗体上添加一个标签、一个文本框和两个命令按钮。 单击时,显示出1~20之间各阶乘的和 单击时,退出程序
Private Function jch(n As Integer) As Single Dim i As Integer, fac As Single fac = 1 For i = 1 To n fac = fac * i Next i jch = fac End Function Private Sub Command1_Click() Dim m As Integer, jsum As Single For m = 1 To 20 jsum = jsum + jch(m) Next m Text1.Text=”1!+ 2!+ 3!+ … + 20!=” & jsum End Sub 将n!的结果赋值给函数名jch 调用函数jch
说明: • 变量jsum的作用是存放1!、2!、…、20!的累加和。 • 在循环体中,每次调用函数jch时,将循环控制变量m作为实参发送到函数过程的形参中,作为当前要计算的n! • 在函数过程中,将计算n!的结果fac赋值给函数名jch,返回给主调程序的调用处
【例5.6】从键盘上输入一个正整数,判断该数是否为素数。在窗体上添加一个标签、一个文本框和两个命令按钮。【例5.6】从键盘上输入一个正整数,判断该数是否为素数。在窗体上添加一个标签、一个文本框和两个命令按钮。 判断输入的数是否为素数 显示3 至输入的数之间所有素数
程序代码: 判断是否为素数的函数过程 Private Function isprime(a) As String k% = Int(Sqr(a)) For i% = 2 To k% If a Mod i% = 0 Then Exit For Next i% If i% >= k% + 1 Then isprime = 1 Else isprime = 0 End If End Function 若找到一个能整除a的数,就能断定a不是素数,此时应提前退出循环 若a是素数,返回1;否则返回0
Private Sub Command1_Click() Text1.SetFocus n = Val(Text1.Text) If isprime(n) = 1 Then m = n & “是素数” Else m = n & “不是素数” End If MsgBox m, , “判断素数” End Sub 将函数isprime的返回值作为条件进行逻辑判断
Private Sub Command2_Click() x = Val(Text1.Text) For j = 3 To x If isprime(j) = 1 Then y$ = y$ & " " & j End If Next j MsgBox y$, , “显示素数” End Sub 显示3至输入的数之间所有素数
说明: • 函数过程isprime判断输入的数是否为素数,若是,则函数返回结果为1,否则返回0; • 在Command1_Click事件中,根据函数返回结果,显示该数是否为素数; • 在Command2_Click事件中,根据所输入的x,调用函数isprime依次判断3、4、……、x是否为素数,然后将其中的素数连接起来送到变量y$中,最后再显示该变量中的字符串。
5.2 变量的作用域 一个VB应用程序可以包含若干个过程,这些过程可以出现在窗体或标准模块中,而且在过程中必不可少的要使用变量。变量在程序中所处的位置不同,其使用的范围也不同,我们将变量的有效范围称为变量的作用域。变量按其作用域分为局部变量、窗体/模块级变量、全局变量。
5.2.1 局部变量的作用域 在过程内部声明的变量称为局部变量。它是用Dim语句声明(若该变量是静态的,则用Static语句,参见5.2.4节)或不声明而直接使用。局部变量只能在声明它的过程中有效。
【例5.7】在窗体上添加一个文本框和两个命令按钮。【例5.7】在窗体上添加一个文本框和两个命令按钮。 单击时,观察运行结果 单击时,观察运行结果
程序代码: Private Sub cmdTest1_Click() Dim a As Integer a = a + 1 Text1.Text = a End Sub Private Sub cmdTest2_Click() Dim a As Integer Text1.Text = a End Sub 声明局部变量 在一个过程中用Dim语句声明的局部变量,只有当程序执行该过程时才存在。当该过程执行结束时,系统立即释放变量所占用的内存单元
说明: • 本例分别在两个事件过程中,声明了两个同名变量a,但它们彼此互不影响,各自在自己所在的过程中起作用。
5.2.2 窗体/模块级变量的作用域 在一个窗体/模块的任何过程之外声明的变量称为窗体/模块级变量。它是在“通用”段中用Dim语句或Private语句声明的,可以在声明它的窗体/模块的任何过程中使用,但在其他窗体/模块中是无效的。
【例5.8】在窗体1上添加一个文本框和3个命令按钮,而在窗体2上添加一个文本框和2个命令按钮。【例5.8】在窗体1上添加一个文本框和3个命令按钮,而在窗体2上添加一个文本框和2个命令按钮。 切换到第2个窗体 单击10次 观察结果 单击时,观察运行结果 单击时,切换到窗体1
窗体1的代码: 声明窗体/模块级变量 Dim a As Integer Private Sub cmdTest_Click() a = a + 1 End Sub Private Sub cmdShow_Click() Text1.Text = a End Sub Private Sub cmdSwitch_Click() frmEx5_8_1.Hide frmEx5_8_2.Show End Sub 在两个事件过程中使用的a是同一个变量(窗体级变量)
窗体2的代码: 直接使用局部变量a Private Sub cmdDisplay_Click() Text1.Text = a If a = ” ” Then MsgBox “a中存放空串!”, , “显示” End Sub Private Sub cmdExit_Click() frmEx5_8_1.Show frmEx5_8_2.Hide End Sub
说明: • 如果需要在一个窗体或模块的不同过程中均使用同一个变量,就需要将它定义为一个窗体或模块级变量。
在第一个窗体中声明窗体级变量a后,在该窗体的任何过程中都可使用这个变量,但在其他窗体中不能使用。当关闭一个窗体时,该窗体级的变量全部被释放;在第一个窗体中声明窗体级变量a后,在该窗体的任何过程中都可使用这个变量,但在其他窗体中不能使用。当关闭一个窗体时,该窗体级的变量全部被释放; • 在第二个窗体中直接使用了一个同名的变量a,没有声明直接使用的变量是局部变量,该变量只能在包含它的过程中使用,与第一个窗体中声明的变量a互不干涉。
5.2.3 全局变量的作用域 全局变量可以在整个应用程序中使用,其值始终不会消失和重新初始化,只有当应用程序执行结束时,全局变量才消失并释放所占用的内存空间。
切换到第2个窗体 【例5.9】在窗体1上添加一个文本框和3个命令按钮。在窗体2上添加一个文本框和2个命令按钮。 单击时,观察运行结果 单击时,切换到窗体1 单击10次 观察结果
窗体1的代码: 声明全局变量 Public a As Integer Private Sub cmdTest_Click() a = a + 1 End Sub Private Sub cmdShow_Click() Text1.Text = a End Sub Private Sub cmdSwitch_Click() frmEx5_9_1.Hide frmEx5_9_2.Show End Sub
窗体2的代码: Private Sub cmdDisplay_Click() Text1.Text = frmEx5_9_1.a End Sub Private Sub cmdExit_Click() frmEx5_9_1.Show frmEx5_9_2.Hide End Sub 显示全局变量的值 要在当前声明全局变量的窗体之外使用该变量时,应在变量名前加窗体名
说明: • 如果需要在整个应用程序中的任一窗体或标准模块中使用同一个变量,就需要将它定义为全局变量。如本例在Form1的“通用”段中声明Public a As Integer后,变量a就可在整个应用程序中被使用。
【例5.10】在例5.9基础上改写应用程序:添加一个标准模块Module1,并将程序代码按如下改写:【例5.10】在例5.9基础上改写应用程序:添加一个标准模块Module1,并将程序代码按如下改写: • 将窗体1代码中的变量声明语句Public a As Integer移到标准模块Module1中; • 将窗体2代码中cmdDisplay_Click事件的语句Text1.Text = frmEx5_9_1.a改写为Text1.Text = a,其他语句不变; • 窗体界面不变。观察单击10次“测试”按钮后,再单击“查看”按钮时的运行结果和单击“显示”按钮时的运行结果。