内容正文:
内蒙古自治区(计算机类)对口招生
《Visual Basic程序设计》复习讲义
模块 8 过程
考点 16 过程
【考纲要求】
1. 掌握事件过程;
2. 掌握子过程;
3. 掌握过程间参数的传递;
4. 了解过程的嵌套与递归;
5. 掌握常用算法实例。
【知识网络】
【知识和技能要点】
一、事件过程
1. 事件过程的特点与命名
事件过程是系统提供的过程:当用户对某个对象发出一个动作时便产生一个事件,程序随即自动调用与该事件相关联的过程,它也是构成应用程序的主体。事件过程依附于窗体和控件,一般由 Visual Basic 自动创建,用户不能自行增加或删除。命名有固定要求:控件事件的过程名由控件名称、下画线和事件名称三部分依次组成,窗体事件的过程名由窗体名称、下画线和事件名称组成。
二、子过程
1. Function 过程的定义与格式
Function 过程用来完成某项运算并把结果返回给调用者。定义时以关键字 Function 开头,后面写函数名与一对圆括号,括号中是形参列表,可以用 As 子句指明返回值的数据类型;过程体写在下面,最后以 End Function 结束。关键字前面还可以加 Private 或 Public 表示过程的作用范围,其中 Private 表示所定义的是模块级过程,只能被本模块内的过程调用,Public用于表示所定义的Function过程是公有的,可以被应用程序内的任意过程调用。
2. Function 过程的返回值
Function 过程要返回结果,靠的是在过程体中给函数名赋值,写法是把表达式写在等号右边、函数名写在等号左边。返回值的类型由过程定义时 As 子句指明,如果省略不写,默认是变体型。假如过程执行完毕也没有给函数名赋过值,那么调用者得到的便是该类型的默认值,数值型函数返回 0,字符型函数返回空串。此外,在过程体中还可以用 Exit Function 语句提前结束过程。
3. Sub 过程的定义与格式
Sub 过程是一组能够完成特定操作、相对独立的程序段,当别处需要执行这项操作时就可以调用它。定义时以关键字 Sub 开头,后面写过程名与形参列表,过程体写在下面,最后以 End Sub 结束。如果在 Static 之后定义,则过程中的局部变量成为静态变量,过程调用结束后仍能保留其值。需要注意,过程的定义不能嵌套,一个过程里面不能再写另一个过程。
4. Sub 过程的调用与两者的区别
调用 Sub 过程要把过程名连同实参写成一条独立的语句,前面可以加上关键字 Call。Sub 过程没有返回值,不能出现在表达式中。Function 过程则不同,它有返回值,既可以作为一条语句来调用,也可以写在表达式里直接参与计算。需要把结果交给调用者使用时就定义为 Function 过程,只完成某种操作、不需要结果时定义为 Sub 过程。
三、过程间参数的传递
1. 形参与实参
定义过程时写在过程名后面括号中的参数称为形参,它只说明参数的名称与类型以及在过程中的作用,本身并不占用实际的数据。调用过程时写在调用语句中的参数称为实参,它可以是常量、表达式、变量,也可以是数组。调用时,实参按照先后位置逐个传递给形参;两者的名称可以不同,但个数、数据类型、位置顺序必须对应一致,否则就会出错。
2. 按值传递
在形参前加上关键字 ByVal,就表示这个参数按值传递。系统会为形参另外分配一个临时的内存单元,把实参的值复制到这个单元中去,形参与实参从此各占一处、互不相干,因此这种传递是单向的:在被调用的过程中无论怎样改变形参的值,调用者那里的实参都不会受到影响。另外,如果调用语句中给出的实参是常量或者表达式,那么实际进行的也是按值传递。
3. 按地址传递
在形参前加上关键字 ByRef,或者什么也不写,系统默认采用的就是按地址传递。这时传递过去的是实参所在内存单元的地址,形参与实参指向同一个存储单元,因此被调用的过程中只要改变了形参的值,调用者的实参也会跟着改变。如果本意是只把数值传给过程、不希望实参被改动,可以在调用语句中把实参用一对圆括号括起来,强制它按值传递。
4. 数组参数的传递
当参数是数组时,只能采用按地址传递的方式,不能按值传递。书写时,形参中要写出数组名并在后面带一对空括号,其类型应当与实参数组一致;实参同样只写数组名、后面带一对空括号,不必写出下标。由于传递的是地址,过程中对该数组元素的任何修改都会直接反映到原来的数组上,因此交换、排序一类需要改变原数组的过程都采用这种写法。
5. 变量与过程的作用域
按作用范围的大小,变量可分为三类。在过程内部用 Dim 声明的是过程级变量,作用范围仅限于声明它的那个过程,不同过程中的局部变量可以取相同的名字而互不影响;在窗体的声明部分用 Dim 或 Private 声明的是模块级变量,本模块内的所有过程都可以使用;在标准模块中用 Public 声明的是全局变量,整个应用程序中都能访问,不同模块中的全局变量可以同名,引用时要在变量名前加上模块名。
四、过程的嵌套与递归
1. 过程的嵌套调用与递归调用
一个过程中调用了另一个过程,被调用的过程中又调用了第三个过程,这样一层套一层的调用方式称为过程的嵌套调用。需要注意区分的是,过程的调用可以嵌套,但过程的定义不能嵌套——不能把一个 Sub 过程写在另一个过程里面。如果一个过程直接或间接地调用了它自身,就称为递归调用,求阶乘、求最大公约数一类问题常用它来解决,编写时必须设置终止条件。
五、常用算法实例
1. 过程在常用算法中的应用
把反复使用的算法写成通用过程,程序的结构会更清楚,改动起来也方便。常见的做法是:把求阶乘、求数列之和、由三边长求三角形面积一类需要返回结果的计算写成 Function 过程;把交换两个变量的值、交换数组中的元素、在窗体上输出一行文字一类只完成操作的过程写成 Sub 过程。参数传递方式的选择是关键——需要从过程里把结果带回来时用按地址传递,只需要把数值送进去计算时用按值传递。
【真题】
2022年真题|单选题第19题 在标准模块过程中用 Public 语句声明的变量的作用域是( )
A. 整个应用程序
B. 某窗体中的所有程序
C. 仅限于标准模块中的某个程序
D. 仅限于标准模块中
【答案】A
【解析】在标准模块中用 Public 语句声明的变量是全局变量,它的作用域是整个应用程序,工程中任何窗体、任何模块里的过程都可以访问它。若作用域只限于本模块,那是在窗体或标准模块的声明部分用 Dim 或 Private 声明的模块级变量;仅限某个过程的则是在过程内部声明的局部变量。
2022年真题|单选题第20题 以下说法错误的是( )
A. 在同一模块不同过程中的变量可以同名
B. 不同模块中定义的全局变量不可以同名
C. 引用另一个模块中的全局变量时,必须在变量名前加模块名
D. 同一模块中不同级的变量可以同名
【答案】B
【解析】不同模块中定义的全局变量是可以同名的,只要在引用时通过模块名加以区分即可,因此 B 项的说法错误。A 项正确:同一模块的不同过程各自声明的局部变量互不相干,可以重名;C 项正确:跨模块引用全局变量时必须加上模块名;D 项正确:同一模块中模块级变量与过程级变量可以同名,此时过程内优先使用局部变量。
2023年真题|第16题 下列叙述中正确的是( )
A. 在窗体的 Form_Load 事件过程中定义的变量是全局变量
B. 局部变量的作用域可以超出所定义的过程
C. 在某个 Sub 过程中定义的局部变量可以与其他事件过程中定义的局部变量同名,但作用域只限于该过程
D. 在调用过程时,所有局部变量被系统初始化为 0 或空字符串
【答案】C
【解析】在过程内部声明的变量是局部变量,作用范围仅限于该过程,不同过程中可以取相同的名字而互不影响,因此 C 项正确,A、B 两项都错。D 项之所以不正确,是因为它说的是"所有"局部变量:用 Static 声明的静态局部变量在过程调用结束后仍保留其值,并不会被重新初始化,只有用 Dim 声明的动态局部变量才会在每次调用时重新初始化。
2024年真题|填空第129题 对于下面程序,单击窗体三次后,变量 a 的值等于________。
Private Sub Form_Click()
Dim a As Integer
a = a + 1
End Sub
【答案】1
【解析】a 是在事件过程内部用 Dim 声明的过程级变量。每次单击窗体触发事件时,系统都会重新为它分配存储单元并初始化为 0,随后执行 a = a + 1,结果始终是 1。因此无论单击多少次,输出或观察到的 a 都等于 1;若把 Dim 改成 Static,局部变量就成为静态变量,其值可以累加,那时单击三次后 a 才会等于 3。
2026年真题|第127题 在窗体上有一个命令按钮 Command1,单击 Command1,程序执行,将整数 1 到 10 存入数组 a() 中并在窗体上打印出来。然后调用通用过程 swap,调换数组 a() 中存放的值,即 a(1) 与 a(10) 的值互换、a(2) 与 a(9) 的值互换……a(5) 与 a(6) 的值互换,最后在窗体上打印交换后的数组元素的值。程序如下,请补充完善程序。
Option Base [1]________
Private Sub Command1_Click()
Dim a(10) As Integer
For i = 1 To [2]________
a(i) = i
Print [3]________;
Next i
Print
[4]________ swap(a())
For i = 1 To 10
Print a(i);
Next i
End Sub
Sub swap(b() As Integer)
n = [5]________
For i = 1 To n / 2
t = b(i)
[6]________ = b(n - i + 1)
b(n - i + 1) = [7]________
Next i
End Sub
【答案】[1] 1;[2] 10;[3] a(i);[4] Call;[5] UBound(b)(填 10 亦可);[6] b(i);[7] t
【解析】数组 a(10) 要存放下标 1 到 10 的元素,应当用 Option Base 1 把下标的下界设为 1,故 [1] 处填 1。循环要给 10 个元素赋值,终值为 10,故 [2] 处填 10;打印当前元素用 a(i),故 [3] 处填 a(i)。调用通用过程 swap 时可以加上关键字 Call,故 [4] 处填 Call。过程中要把数组的长度算出来,数组 b 的最大下标就是元素个数,用 UBound 函数提取,故 [5] 处填 UBound(b);填 10 也能得到同样结果。交换三步走:先暂存 b(i),再把后一个元素上移,故 [6] 处填 b(i);最后把暂存值写回后一个位置,故 [7] 处填 t。
2026年真题|第129题 单击窗体上的命令按钮 Command1,程序运行计算 3! + 5! + 7! + 9!。程序代码如下,请补充完善程序代码。
Private Function jc(ByVal i) As Long
Dim j As Integer, k As Long
k = [12]________
For j = 1 To [13]________
k = [14]________ * j
Next j
[15]________ = k
End Function
Private Sub Command1_Click()
Dim x As Long
[16]________ = jc(3) + jc(5) + jc(7) + jc(9)
Print "3!+5!+7!+9!="; x
End Sub
【答案】[12] 1;[13] i;[14] k;[15] jc;[16] x
【解析】jc 是求阶乘的 Function 过程,形参 i 是要求阶乘的数。累乘变量 k 的初值应当设为 1,故 [12] 处填 1。求 i 的阶乘要从 1 乘到 i,故 [13] 处填 i。循环中把 k 与当前的 j 相乘后仍存回 k,故 [14] 处填 k。Function 过程要把结果返回给调用者,必须给函数名赋值,故 [15] 处填 jc。主过程中把四个阶乘之和赋给变量 x,故 [16] 处填 x;Function 过程有返回值,因此可以直接写在表达式中参与运算。
【练习题】
一、填空题
1. 事件过程的过程名由________、下画线和________组成。
【答案】控件名称(窗体名称);事件名称
【解析】事件过程依附于窗体和控件,命名有固定要求:控件事件的过程名由控件名称、下画线和事件名称三部分依次组成,窗体事件的过程名把控件名称换成窗体名称即可。正因为命名规则统一,系统才能在事件发生时自动找到并调用相应的事件过程。
2. Function 过程通过________的方式给函数赋值;若要提前退出 Function 过程,可以使用________语句。
【答案】函数名 = 表达式;Exit Function
【解析】Function 过程只有给函数名赋了值,才能把结果返回给调用者,写法是把表达式写在等号右边、函数名写在等号左边。若过程执行到中途就已经得出结果,可以用 Exit Function 语句提前结束过程,避免继续做无用的运算。
3. Sub 过程不能嵌套________,也不能嵌套________。
【答案】Sub 过程;Function 过程
【解析】过程的调用可以一层套一层,但过程的定义不能嵌套:不能把一个 Sub 过程或 Function 过程写在另一个 Sub 过程的内部。若要重复使用某段代码,应当把它单独定义成一个过程,再由其他过程去调用它。
4. 在形参前加关键字________表示按值传递,加关键字________表示按地址传递。
【答案】ByVal;ByRef
【解析】在形参表中通过关键字指定传递方式:加 ByVal 表示按值传递,系统为形参另分配一个临时单元,改形参不影响实参;加 ByRef 表示按地址传递,形参与实参共用同一个存储单元。若什么也不写,系统默认按地址传递。
5. 在过程内部用 Dim 声明的变量称为________变量,用 Static 声明的变量称为________变量。
【答案】过程级(局部);静态
【解析】在过程内部用 Dim 声明的变量是过程级变量,也叫局部变量,每次调用过程时都会被重新初始化;用 Static 声明的变量是静态变量,它在过程调用结束后仍保留其值,下次再调用时接着上次的结果继续使用,求累加和时常用它。
二、单项选择题
1. 关于事件过程,下列说法正确的是( )
A. 用户可以自行增加或删除事件过程
B. 事件过程由用户编写,与控件无关
C. 事件过程一般由 Visual Basic 创建,依附于窗体和控件
D. 事件过程不响应任何动作
【答案】C
【解析】事件过程是系统提供的过程,当用户对某个对象发出动作时自动调用,它依附于窗体和控件,一般由 Visual Basic 自动创建,用户不能自行增加或删除。事件过程与控件密切相关,正是为了响应某个动作才被调用。
2. Function 过程与 Sub 过程的主要区别之一是( )
A. Function 过程有返回值,可以写在表达式中
B. Function 过程没有返回值
C. Sub 过程必须写在表达式中
D. 两者完全一样
【答案】A
【解析】Function 过程有返回值,既可以像 Sub 那样作为一条语句调用,也可以写在表达式中把返回值直接用于计算;Sub 过程没有返回值,只能作为独立的语句调用。是否需要把一个结果交给调用者使用,正是选择两者的依据。
3. 定义一个 Function 过程时,若省略 [As 类型] 部分,则返回值的数据类型默认为( )
A. Integer
B. String
C. Single
D. Variant
【答案】D
【解析】过程定义中的 [As 类型] 用来指明返回值的数据类型,如果省略不写,默认是变体型。此时函数同样可以正常返回结果,只不过返回值的类型要等到运行时依据赋值给函数名的表达式的类型来确定。
4. 在 Sub 过程的形参表中,若形参前省略传递方式关键字,则默认的传递方式是( )
A. 按值传递
B. 按地址传递
C. 双向传递
D. 不能传递
【答案】B
【解析】形参前加 ByVal 表示按值传递,加 ByRef 表示按地址传递;如果什么也不写,系统默认采用按地址传递。因此在过程中修改形参时要注意,实参可能会随之改变;若确实不希望实参被改动,就应显式加上 ByVal。
5. 采用按值传递参数时,实参向形参的传递是( )
A. 单向的,形参的改变不会影响实参
B. 双向的,两者互相影响
C. 形参改变后实参随之改变
D. 数组不能按值传递
【答案】A
【解析】按值传递时系统为形参另外分配一个临时的内存单元,把实参的值复制过去,形参与实参各占一处、互不相干,因此这种传递是单向的:过程中无论怎样改变形参,实参都不受影响。数组不能按值传递,只能按地址传递。
6. 若调用语句中的实参是常量或表达式,则参数传递的方式是( )
A. 按地址传递
B. 只能按地址传递
C. 按值传递
D. 不传递
【答案】C
【解析】常量与表达式都没有可供传递的内存地址,系统只能把它们的结果值复制给形参,因此实际进行的是按值传递。这也解释了为什么用表达式作实参时,过程中对形参的修改无法带回来。
7. 数组作为实参传递给过程时,采用的传递方式是( )
A. 按值传递
B. 按地址传递
C. 两者都不是
D. 由形参的类型决定
【答案】B
【解析】数组作为参数时只能按地址传递,不能按值传递。形参中写数组名并带一对空括号,实参同样只写数组名带一对空括号。正因为传的是地址,过程中对数组元素的修改会直接反映到原数组上。
8. 在窗体的声明部分用 Dim 声明的变量,其作用域是( )
A. 整个应用程序
B. 仅限于声明它的那个过程
C. 其他模块中的过程
D. 本模块内的所有过程
【答案】D
【解析】在窗体或标准模块的声明部分用 Dim 或 Private 声明的变量是模块级变量,作用范围是本模块内的所有过程,其他模块中的过程不能直接使用。作用域能覆盖整个应用程序的,只有在标准模块中用 Public 声明的全局变量。
9. 在过程内部用 Dim 声明的变量,其作用域是( )
A. 整个应用程序
B. 本模块内的所有过程
C. 仅限于声明它的那个过程
D. 其他模块中的所有过程
【答案】C
【解析】过程内部用 Dim 声明的变量是过程级变量,作用范围仅限于声明它的那个过程,过程执行结束后它所占用的存储单元即被释放。不同过程中可以取相同的变量名而互不影响,这也是大型程序便于分工编写的原因之一。
10. 在过程内用 Static 声明的变量,其特点是( )
A. 每次调用过程都重新初始化
B. 过程调用结束后仍保留其值
C. 作用域扩大到整个模块
D. 只能用于 Function 过程
【答案】B
【解析】用 Static 声明的静态变量在过程调用结束后仍保留其值,下次再调用同一过程时可以接着上次的结果继续使用,常用来累计调用次数或累加和。它的作用范围仍限于该过程,只是生存期与整个程序一样长。
11. 若过程 A 调用过程 B,过程 B 又调用过程 C,这种调用方式称为( )
A. 过程的嵌套调用
B. 过程的递归调用
C. 过程的并行调用
D. 过程的重复调用
【答案】A
【解析】一个过程中调用另一个过程、被调用的过程中又调用第三个过程,这样一层套一层的调用方式称为过程的嵌套调用。要注意区分的是:过程的调用可以嵌套,但过程的定义不能嵌套。
12. 一个过程直接或间接地调用自身,这种调用方式称为( )
A. 嵌套调用
B. 并行调用
C. 顺序调用
D. 递归调用
【答案】D
【解析】过程直接或间接地调用自身称为递归调用,求阶乘、求最大公约数一类具备递推性质的问题常用它来解决。编写递归过程时必须设置终止条件,使过程在满足该条件时不再调用自身,否则会无休止地调用下去。
三、程序填空题
1. 下列程序用 Function 过程求两个数中的较大者。请补充完整下列程序代码。
Private Function Max(a As Single, b As Single) As Single
If a > b Then
Max = [1]________
Else
Max = [2]________
End If
End Function
Private Sub Command1_Click()
Dim x As Single
x = [3]________
Print "较大者是"; x
End Sub
【答案】[1] a;[2] b;[3] Max(12, 18)
【解析】Function 过程通过给函数名赋值来返回结果。条件 a > b 成立时较大者是 a,故 [1] 处填 a;否则较大者是 b,故 [2] 处填 b。Function 过程有返回值,可以直接写在表达式中参与运算,故 [3] 处调用 Max 并把结果赋给 x,任取两个数作实参即可,填 Max(12, 18) 一类写法都符合要求。
2. 下列程序用 Function 过程求 1 + 2 + … + n 的和。请补充完整下列程序代码。
Private Function Sum(n As Integer) As Integer
Dim i As Integer, s As Integer
s = 0
For i = 1 To n
s = s + i
Next i
[1]________ = s
End Function
Private Sub Command1_Click()
Dim x As Integer
x = [2]________
Print "1+2+…+100="; x
End Sub
【答案】[1] Sum;[2] Sum(100)
【解析】循环累加结束后,总和存放在变量 s 中,Function 过程必须把这个值赋给函数名才能返回,故 [1] 处填 Sum。主过程中要得到 1 到 100 的和,应调用该过程并把实参 100 传进去,故 [2] 处填 Sum(100);过程有返回值,因此可以直接写在赋值语句的右边。
原创精品资源学科网独家享有版权,侵权必究
学科网(北京)股份有限公司
$