资源描述
第6章 补充资料
习题解答
1、简述子过程与函数过程得共同点与不同之处、
解答:子过程与函数过程得共同点:函数过程与子过程都就是功能相对独立得一种子程序结构,
它们有各自得过程头、变量声明与过程体。在程序中使用它们不但可以避免书写重复得程序
语句,缩短代码,而且可以使程序条理清晰,容易阅读。
子过程与函数过程得不同点:
(1)过程声明得关键字不同,子过程用得就是Sub,函数过程用得就是Function。
(2)子过程名无值就无类型声明,函数过程名有值就有类型声明。
(3)函数过程名兼作结果变量,因此在函数过程体内至少对函数过程名赋值;而子过程名在
过程体内不能赋值。
(4)调用方式不同,子过程就是一条独立得语句,可用Call子过程名或省略Call直接以子过程
名调用;函数过程不就是一条独立得语句,就是一个函数值,必须参与表达式得运算。
(5)一般来说,一个函数过程可以被一个子过程代替,代替时只要改变函数过程定义得形式,
并在子过程得形参表中增加一个地址传递得形参来传递结果。
2.什么就是形参,什么就是实参?什么就是值引用?什么就是地址引用?地址引用时,对应得实参
有什么限制?
解答:形参就是在定义过程时得一种形式虚设得参数,只代表了该过程参数得个数、类型、位
置、形参得名字并不重要,也没有任何值,只表示在过程体内进行某种运算或处理。
实参就是调用子过程时提供给过程形参得初始值或通过过程体处理后获得得结果。
调用时用实参代替形参,实参与形参在个数、类型、位置一一对应,实参与形参名相同与否
无关。
实参与形参得结合有两种方法,即传地址(ByRef)与传值(ByVal),或称地址引用与值引
用,缺省为地址引用。
值引用时,系统将实参得值传递给对应得形参,实参与形参断开了联系。如果在过程体中改
变形参得值,不会影响到实参。
地址引用时,实参与形参变量共用同一个存储单元,如果在过程中改变了形参得值,对应得
实参也将发生改变。
地址引用时,实参只能就是变量,不能就是常量或表达式。
3、指出下面过程语句说明中得错误:
(1)Sub f1(n%)As Integer
(2)Function f1 % (f1%)
(3)Sub f1(ByVal n%())
(4)Sub f1(x(i)as Integer)
解答:
(1)错误为Sub子过程名无返回值,也就没有类型。
(2)函数名与形参名相同。
(3)形参n为数组,不允许声明为ByVal值传递。
(4)形参x(i)不允许为数组元素。
4、已知有如下求两个平方数与得fsum子过程:
Public Sub fsum(sum%,ByVal m%,ByVal n%)
sum = a * a + b * b
End Sub
在事件过程中若有如下变量声明:
Private Sub mand1_Click()
Dim a%,b%,c!
a = 10:b = 20
则指出如下过程调用语句得错误所在:
(1)fsum 3,4,5
(2)fsum c,a,b
(3)fusm a + b,a,b
(4)Call fsum(Sqr(c),Sqr(a),Sqr(b))
(5)Call fsum c,a,b
解答:
(1)fsum子过程得第一个形参就是地址传递,因此对应得实参3不应该就是常量。
(2)fsum子过程得第一个形参就是整形而且就是地址传递,对应得实参c就是单精度,类型不
匹配。
(3)fsum子过程得第一个形参就是地址传递,因此对应得实参a+b不应该就是表达式。
(4)fsum子过程得第一个形参就是地址传递,因此对应得实参Sqr(c)不应该就是表达式。
(5)用Call语句调用fsum子过程,必须加圆括号括起实参。
5、利用迭代法求方程 x^2 - a = 0得近似根,要求精度为10^-5,迭代公式为Xi+1 =
1/2(Xi + a/Xi)。编制三个过程:迭代函数过程、迭代子过程与递归法函数过程。
解答:假定a为10,三种过程得执行效果如图6、6所示,程序代码如下:
Private Sub mand1_Click()
Print"函数过程";f1(10)
Call s1(x!,10)
Print"子过程";x!
Print"递柜调用";dgf(x,10)
End Sub
Public Function f1!(a!) '函数过程
Dim X!,X1!
x1 = a
Do
x = (x + a/x)/2
If Abs(x - x1) < 0、00001 Then Exit Do
x1 = x
Loop
End Sub
Public Function dgf!(x,a!) '递归调用
x1 = (x + a/x)/2
If Abs(x - x1)< 0、00001 Then
dgf = x
Else
dgf = dgf(x1,a)
End If
End Function
6、要使变量在某事件过程中保留值,有哪几种变量声明得方法?
解答:声明变量为全局(Public)、通用声明段或标准模块声明得模块级变量、局部过程声明得
静态变量(Static)。
7、为了使某变量在所有得窗体中都能使用,应在何处声明该变量?
解答:在标准模块声明为全局变量。
8、在同一模块、不同过程中声明得相同变量名,两者就是否表示同一个变量?两者间有没有联系?
解答:表示不同得变量,没有任何关系。
常见错误与难点分析
1、程序设计算法得问题
该章程序编写难度较大,主要就是算法得构思有困难,这也就是程序设计中最难学习得阶段。但
就是对每一位程序设计得初学者,没有捷径可走,一定要多瞧、多练、知难而进。上机前一定要先编
写好程序,仔细分析、检查,才能提高上机调试得效率。
2、确定自定义得过程就是子过程还就是函数过程
实际上过程就是一个具有某种功能得独立程序单位,可供多次调用。子过程与函数过程得区
别就是前者子过程名无值;后者函数过程名有值。若过程有一个返回值,则习惯使用函数过程;若
过程无返回值,则使用子过程;若过程返回多个值,一般使用子过程,通过实参与形参得结合返回
结果,当然也可通过函数过程名返回一个,其余结果通过实参与形参得结合返回。
3、过程中确定形参得个数与传递方式
对初学者,在定义过程时较难确定形参得个数与传递方式。
过程中参数得作用就是实现过程与调用者得数据传递。一方面,调用者为子过程或函数过程
提供初值,这就是通过实参传递给形参实现得;另一方面,子过程或函数过程将结果传递给调用者,
这就是通过地址传递方式实现得。因此,决定形参得个数就就是由上述两方面决定得。
对初学者,往往喜欢把过程体中用到得所有变量全作为形参,这样就增加了调拥者得负担与
出错概率;也有得初学者全部省略了形参,因此无法实现数据得传递,既不能从调用者得到初值,
也无法将计算结果传递给调用者。
VB中形参与实参得结合有传值与传地址两种方式。区别如下:
(1)在定义形式上前者在形参前加ByVal关键字,后者在形参前加ByRef关键字或缺省。
(2)在作用上值传递只能从外界向过程传入初值,但不能将结果传出;而地址传递既可传入
又可传出。
(3)如果实参就是数组、自定义类型、对象变量等,形参只能就是地址传递。
4、实参与形参类型对应得问题
在地址传递方式时,调用过程实参与形参类型要一致。例如:
函数过程定义如下:
Public Function f!(x!)
f = x + x
End Function
主调程序如下:
Private Sub mand1_Click()
Dim y%
y = 3
Print f(y)
End Sub
上例形参x就是单精度型、实参y就是整形,程序运行时会显示"ByRef参数类型不符"得编译提
示信息。
在值传递时,若就是数值型,则实参按形参得类型将值传递给形参,例如:
函数过程定义如下:
Public Function f!(x!)
f = x + x
End Function
主调程序如下:
Private Sub mand1_Click()
Dim y%
y = 3、4
Print f(y)
End Sub
程序运行后显示得结果就是6。
5、变量得作用域问题
局部变量,在对该过程调用时,分配该变量得存储空间,当过程调用结束时,回收分配得存储
空间,也就就是调用一次,初始化一次,变量值不保留;窗体级变量,当窗体装入时,分配该变量得存
储空间,直到该窗体从内存卸掉,才回收该变量分配得存储空间。
例如,要通过文本框输入若干个值,每输入一个按Enter键,直到输入得值为9999,输入结束,
求输入数得平均值。
Private Sub Text1_KeyPress(KeyAscii As Integer)
Dim sum!,n%
If KeyAscii = 13 Then
If Val(Text1) = 9999 Then
sum = sum / n
Print sum
Else
sum = sum + Val(Text1)
n = n + 1
Text1 = ""
End If
End If
End Sub
该过程没有语法错,运行程序可输入若干个数,但当输入9999时,程序显示“溢出”得错误。
因为sum与n就是局部变量,每按一个键,局部变量初始化为0,所以会有上述错误产生。
改进方法:将要保值得局部变量声明为Static静态变量,也可将要保值得变量在通用声明段
进行声明为窗体级变量。
6、递归调用出现“栈溢出”
如下求阶乘得递归函数过程:
Public Function fac(n As Integer)As Integer]
If n = 1 Then
fac = 1
Else
fac = n * fac(n - 1)
End If
End Function
Private Sub mand1_Click() '调用递归函数,显示出fac(5)=120
Print "fac(5)=";fac(5)
End Sub
当主调程序调用时,n得值为5时,显示结果为120;当n得值为-5时,显示“溢出堆栈空
间”得提示信息。
实际上每递归调用一次,系统将当前状态信息(形参、局部变量、调用结束时得返回地址)压
栈,直到到达递归结束条件。上例中当 n = 5 时,每递归调用一次,参数n - 1,直到n = 1 时递归
调用结束,然后不断从栈中弹出当前参数,直到栈空。而当 n = -5 时,参数 n - 1 为-6,压栈,
再递归调用 n - 1 永远到不了 n = 1 得终止条件,直到栈满,产生栈溢出得提示信息。
所以设计递归过程时,一定要考虑过程中有终止得条件与终止时得值或某种操作,而且每递
归调用一次,其中得参数就要向终止方向收敛,否则就会产生栈溢出。
测试题
一、选择题
1、设有如下程序段:
Public Sub F1(n%)
、、、
n = 3 * n + 4
、、、
End Sub
Private Sub mand1_Click()
Dim n% , m%
n = 3
m = 4
、、、
'调用F1语句
、、、
End Sub
则在mand1_Click事件中有效得调用语句就是______。
(A)Call F1(n + m) (B)Call F1(m) (C)Call F1(5) (D)Call F1(m + 5)
2、下面子过程语句说明合法得就是______。
(A)Sub f1(ByVal n%()) (B)Sub f1(n%)As Integer
(C)Function f1%(f1%) (D)Funtion f1(ByVal n%)
3、要想从子过程调用后返回两个结果,下面子过程语句说明合法得就是______。
(A)Sub f2(ByVal n%,ByVal m%)
(B)Sub f1(n%,ByVal m%)
(C)Sub f1(n%,m%)
(D)Sub f1(ByVal n%,m%)
4、在过程中定义得变量,若希望在离开该过程后,还能保存过程中局部变量得值,则应使用
______关键字在过程中定义局部变量。
(A)Dim (B)Private (C)Public (D)Static
5、下面过程运行后显示得结果就是______。
Public Sub F1(n%,ByVal m%) Private Sub mand1_Click()
n = n Mod 10 Dim x%,y%
m = m \ 10 x = 12:y = 34
End Sub Call F1(x,y)
Print x,y
End Sub
(A)2 34 (B)12 34 (C)2 3 (D)12 3
6、如下程序,运行得结果就是______。
Dim a%,b%,c%
Public Sub p1(x%,y%)
Dim c%
x = 2 * x:y = y + 2:c = x + y
End Sub
Public Sub p2(x%,ByVal y%)
Dim c%
x = 2 * x:y = y + 2:c = x + y
End Sub
Private Sub mand1_Click()
a = 2:b = 4:c = 6
Call p1(a,b)
Print "a=";a;"b=";b;"c=";c
Call p2(a,b)
Print "a=";a;"b=";b;"c=";c
End Sub
(A)a=2 b=4 c=6 (B)a=4 b=6 c=10
a=4 b=6 c=10 a=8 b=8 c=6
(C)a=4 b=6 c=6 (D)a=4 b=6 c=14
a=8 b=6 c=6 a=8 b=8 c=6
7、如下程序得运行结果就是______。
Public Sub Proc(a%())
Static i%
Do
a(i)=a(i)+a(i + 1)
i=i + 1
Loop While i<2
End Sub
Private Sub mand1_Click()
Dim m%,i%,x%(10)
For i = 0 To 4:x(i) = i + 1:Next i
For i = 1 To 2:Call Proc(x):Next i
For i = 0 To 4:Print x(i);:Next i
End Sub
(A)3 4 7 5 6 (B)3 5 7 4 5 (C)2 3 4 4 5 (D)4 5 6 7 8
二、填空题
1、传地址方式就是当过程被调用时,形参与实参共享_(1)__。
2、按照如下要求书写函数过程定义得首语句,即Function__(2)___定义语句,要求为:形参
有两个a为整形,b为一维整形数组,函数过程名为MyF,函数返回值为逻辑型。
3、当形参就是数组时,在过程体内对该数组操作时,为了确定数组得下界与上界,应分别用
___(3)_与__(4)___函数。
4、VB中得变量按其作用域分为全局变量、模块变量与_(5)____变量。
5、窗体中得模块级变量应在__(6)___段声明,它作用与该窗体__(7)___。
6、如下程序,运行得结果就是_(8)____,函数过程得功能就是__(9)___。
Public Function f(m%,n%)
Do While m〈〉n
Do While m > n:m = m - n:Loop
Do While n > m:n = n - m:Loop
Loop
f = m
End Function
Private Sub mand1_Click()
Print f(24,18)
End Sub
7、将100~150之间得偶数,拆分成两个素数之与(只要一对即可),最后输出格式如图6、7
所示。其中,prime函数判断参数x就是否为质数。
Private Function prime(ByVal x As Integer)As Boolean
prime = __(10)____
For i = 2 To Sqr(x)
If __(11)____ Then
prime = False
Exit Function
End If
Next i
End Function
Private Sub Form_Click()
i = 1
For n = __(12)____
For k = 3 To n/2
If prime(k) _(13)_____ Then
Print i;":";n;"=";k;"+";n - k
Exit For
End If
Next k
__(14)____
Next n
End Sub
8、子过程MoveStr()就是把字符数组移动m个位置,当Tag为True时左移,则前m个字符
移到字符数组尾,例如,"abcdefghij"左移3个位置后,结果为"defghijabc";当Tag为False
时右移,则后m个字符移到字符数组前,如"abcdefghij"右移3个位置后,结果为"hi-
jabcdefg"。
子过程如下:
Public Sub MoveStr(a $(),m%,Tag As Boolean)
Dim i%,j%,t$
If__(15)____Then '左移
For i = 1 To m
__(16)_____
For j = 0 To __(17)____
a(j) = a(j + 1)
Next j
__(18)____
Next i
Else
For i = 1 To m '右移
_(19)_____
For j = Ubound(A)__(20)____
a(j) = a(j - 1)
Next j
__(21)____
Next i
End If
End Sub
9、子过程CountN用来统计字符串中各数字字符("0"~"9")出现得个数;主调程序对在
TextBox1框输入得文本,每次单击"统计"按钮,调用该子过程,在Label1框显示结果,如
图6、8所示。
Private Sub mand1_Click()
Dim n(9) As Integer,i%
Call CountN(n(),Text1、Text)
List1、Clear
For i = 0 To 9
If n(i) Then_(22)_____"字符"&i&"出现得次数为"&n(i)
Next
End Sub
Sub CountN(_(23)_____)
Dim c As String * 1,i%,m%,j%
For i = 0 To 9
num(i) = 0
Next i
m = Len(s)
For i = 1 To m
c = __(24)____
If c >="0"And c <="9"Then
j = Val(c)
num(j) = _(25)_____
End If
Next i
End Sub
10、子过程F(n,m,t)对一个四位数n整数判断:已知该整数n,逆向排列获得另一个4位
数m就是它自身得倍数(2倍以上),则t为True表示满足上述条件。主调程序用该函
数,显示1000~9999中所有满足该条件得数,如图6、9所示。
提示:根据一个数n,逐一分离得到它得反序数m,然后判断m就是否就是n得倍数。
Private Sub mand1_Click()
Dim t As Boolean,i%,k%
Text1 = ""
Text2 = ""
For i = 1000 To 9999
Call f(_(26)_____)
If t Then
Text1 = Text1 & i & vbCrLf
Text2 = Text2 & k & "="& i & "*" & k \ i & vbCrLf
End If
Next
End Sub
Sub f(ByVal n%,ByRef m%,ByRef tag As Boolean)
Dim i%
tag = False
m = 0
i = n
Do While i > 0
m = _(27)_____ '求得n得逆序
i = __(28)____
Loop
If m MOd n = 0 And m \ n > 1 Then '就是否就是倍数
tag = ______
End If
End Sub
11、下列程序中得子过程MySplit(s,sAarray(),n)用于实现Split函数得功能(字符分离到
数组),即将数字字符串s按分隔符“,”分离到sArray数组中,分离得个数为n。主调程
序将文本框中输入得数字字符串按回车键后进行分离,结果在List1控件显示,如图6、10
所示。
Private Sub Text1_KeyPress(KeyAscii As Integer)
Dim str1 As String,num(100) As Integer,n%,i%
If_(30)_____Then
str1 = Trim(Text1、Text)
Call MySplit(__(31)____)
List1、Text = ""
For i = 0 To n
List1、AddItem num(i)
Next
End If
End Sub
Sub MySplit(ByVal str1 As String,ByRef sn() As Integer,ByRef n As Integer)
Dim i%,j%,ch$
i = 0
j = InStr(str1,",")
Do While j > 0
sn(i) = Val(__(32)____)
str1 = Mid(str1,j + 1)
i = i + 1
j = __(33)____
Loop
sn(i) = Val(str10
n = __(34)_____
End Sub
12、以下过程将一个有序数组中重复出现得数进行压缩,删除后只剩一个、主调程序运行
后结果如图6、11所示。
Sub p(a())
Dim n%,m%,k%
n = UBound(a)
m = n
Do While (_(35)_____) '从右往左比较、压缩
If a(m) = a(m - 1) Then
For k = __(36)____
a(k - 1) = a(k)
Next k
__(37)____
End If
___(38)___
Loop
ReDim Preserve a(n)
End Sub
Private Sub mand1_Click() '主调程序调用P压缩过程
Dim b(),i%
b = Array(23,45,45,60,70,70,70,90)
Call p(_(39)_____)
For i = 0 To UBound(b)
Print b(i);
Next i
End Sub
13、在主教材中介绍得选择法、冒泡法排序都就是在欲排序得数组元素全输入后,再进行排
序。而插入排序就是每输入一个数,马上插入到
数组中,数组在输入过程中总就是有序得,界面
如图6、12所示。在插入排序中,涉及查找、数
组内数得移动与元素插入等算法。
[提示]
此例关键在于编一个插入排序过程,插入排序
法得思路就是:
对数组中已有n个有序数,当输入某数x时:
(1)找x应在数组中得位置j。
(2)从n - j个数依次往后移,使位置为j得数让出。
(3)将数x放入数组中应有得位置j,一个数插入完成。
对于若干个数输入,只要调用插入排序过程即可。
Dim n As Integer
Private Sub Text1_keypress(keyascii As Integer)
Static bb! (1 To 20)
Dim i%
If n = 20 Then
MsgBox"数据太多!",1,"警告"
End
End If
If keyascii = 13 Then
n = n + 2
insert_(40)_____
Picture2、Print Text1 '打印刚输入得数
For i = 1 To n '打印插入后得有序数
Picture1、Print bb(i)
Next i
Picture1、Print
Text1 = ""
End If
End Sub
Sub insert(a() As Single,ByVal x!)
Dim i%,j%
j = 1
Do While__(41)____ '查找x应插入得位置j
j = j + 1
Loop
For i = n - 1 To j Step - 1 'n - j个元素往右移
__(42)____
Next i
a(j) = x 'x插入数组中得第j个位置
End Sub
参考答案
一、选择题
1、B F1子过程中得形参n就是地址传递,可以从实参中获得初值,也可以把结果返回给主
调程序,此时要求实参就是变量,才能获得效果。而A、C、D调用时实参就是表达式或常
量,在VB中语法没有错(有得程序设计语言不允许),但得不到子过程中操作得
结果。
2、D A形参就是数组,不允许为值传递;B子过程名无值也无类型,F1不能声明为整形;C函
数名与形参名同名。
注意:在VB中允许子过程名与形参名同名,例如,C改为:
Sub f1(f1%)
认为就是正确得,因为子过程名无值,不会产生二义性,但尽量不要这样写,因为在有得
程序设计语言中不允许。
3、C 原因同第1题。
4、D Static具有保值得特点;不能在过程体内声明Public、Private变量。
5、A 原因同第1题。
6、C P1子过程得形参都就是地址传递,P2子过程x就是地址传递,y就是值传递。
7、B 形参就是数组,就是地址传递,实参可得到过程中操作得结果。
二、填空题
(1)存储单元
(2)MyF(a%,b%())As Boolean
(3)LBound()
(4)UBound()
(5)局部变量
(6)通用声明
(7)所有过程
(8)6
(9)用辗转相减法求m、n得最大公约数
求最大公约数通常就是用辗转相除法。
(10)True 初值假定为素数。
(11)m Mod i = 0 '只要被i整除,x就不就是质数。
(12)100 To 150
(13)And prime(n - k) '拆分成两个素数。
(14)i = i + 1 '统计满足得个数。
(15)Tag 'Tag为True左移。
(16)c = a(0) '将最左边得元素移出。
(17)Ubound(a) - 1 '数组上界减一个,循环完成,所有元素左
移一次,最右边空出位置,留给最左边得
刚移出元素a(0)
(18)a(Ubound(a))=c '最左边得刚移出元素移到最右边
(19)c = a(Ubound(a)) '将最右边得元素移出
(20)To 1 Step-1 '意义同11,仅就是右移。右移从右边开始逐
一往右移,最左空出位置,留给最右边得
展开阅读全文