(共50张PPT)
专题17 自定义函数、递归算法和
VB连接数据库
一、过程与自定义函数
1.依据结构化程序设计的思想,当需要解决的问题规模较大、复杂时,可以按功能细分成一个个小的功能______,这样的小程序段,在VB中被称为______; 过程是一段能完成一个或多个特定功能的独立的程序段,并可以被其他过程调用。程序中多处重复出现处理相同功能的程序段可以通过过程简化。
2.在VB中,过程有两种,一种是____子过程,一种是_________函数。两者的区别在于:Sub子过程只执行程序而____返回值,而Function函数执行程序后会________。
模块
过程
Sub
Function
不
返回值
3.事件处理过程基本结构
Sub事件处理过程名(参数表)
语句块
End Sub
其中,事件处理过程名必须符合下面的规则:对象名_事件的标准名。
VB的一些常用对象上的常见事件的标准名有:__________和Command1_Click
Form_Load
4.自定义函数基本结构
Function函数名(参数表)As 类型名
语句块(至少有一个语句是:________=表达式)
End Function
函数:函数是类似于过程的另一个程序模块,不同之处是函数执行完成后,
函数的计算结果被送到函数的调用点上,供程序的后继部分继续进行处理。
参数分为形式参数和实际参数。在定义函数时,函数名后面括号中的变量名称叫做__________,或者称为形参。在调用函数时,函数名后面括号中的变量名称叫做__________,或者称为实参。
函数名
形式参数
实际参数
二、递归算法
绝大多数编程语言支持函数的自调用,在这些语言中函数可以通过调用自身来进行递归。计算理论可以证明递归的作用可以完全取代循环,因此在很多函数编程语言中习惯用递归来实现循环。
递归就是一个函数在它的函数体内调用______。执行递归函数将根据递推关系反复调用其自身,每调用一次就进入新的一层,直至遇到结束条件。递归要有两个要素,______条件与______关系,其中结束条件又叫递归出口,它确保了递归不会无限执行。
自身
结束
递推
三、VB访问Access数据库
1.通过ADO对象中的____________对象连接数据库,步骤如下(右边是对应的代码):
Connection
2.通过ADO对象中的___________对象读取数据库表中记录,步骤如下(右边是对应的代码):
Recordset
考点一 自定义函数
从标准函数如Abs类比自定义函数,明确自定义函数的参数、调用过程和函数的返回值。自定义函数有函数名、函数的参数和函数的返回值三个要素,其中在函数的参数中要说明每个参数的类型,在函数的返回值中也要说明值的类型。函数的调用过程分为三步:一是把实际参数的值赋给形式参数,二是在自定义内部进行运算,三是通过函数名把计算结果返回给函数值。
【例1】 有如下程序:
Private Sub Command1_Click()
Dim i As Integer,s As Integer
s=0
For i=1 To 5
s=s+myfun(i)
Next i
Label1.Caption=Str(s)
End Sub
Function myfun(x As Integer) As Integer
Dim t As Integer
t=x ^ 2-1
myfun=Int(Sqr(t))
End Function
执行这部分程序,单击按钮Command1,则在标签Label1上显示的是( )
A.5 B.10 C.12 D.15
解析 本题考核的是自定义函数的定义和调用。在自定义函数中,整型变量x是参数,他的值从主程序中来,在自定义函数内部,经过计算得到myfun的值,该变量就是函数名返回函数的值。在函数调用时,计算myfun(i)的值,先把i的值赋给自定义函数中的x,计算得到结果后,再进行累加。myfun(i)的值依次是0、1、2、3、4,累加的和为10。
B
【变式1】 有如下程序段:
Private Sub Command1_Click()
Dim a As Integer,b As Integer,c As Integer
a=Val(Text1.Text): b=Val(Text2.Text): c=Val(Text3.Text)
Label2.Caption=Str(fx(a,b,c))
End Sub
Function fx(x As Integer,y As Integer,z As Integer) As Integer
If xIf x>y Then fx=y Else fx=x
End Function
A
若在文本框Text1、Text2、Text3中分别输入2,5,6,运行程序,标签Label2中显示的是( )
A.2 B.5 C.6 D.0
解析 自定义函数fx (x,y,z)功能是计算x和y中的最小值,有两条IF语句,若满足第一条语句条件,还是要执行第二条IF语句,因此第一条语句不起作用,即当x【例2】 落球游戏。小球从上方随机垂直掉落在孔(“.”)、平板(“_”)、左右滑坡(“/”“\”)、隔板(“|”)后,运动情况如下:
小球落在孔上,入孔;
垂直落在平板上,停下;
落在左滑坡向左滚动,右滑坡向右滚动。若遇平板继续滚动,遇孔则入孔;遇隔板或滑坡则停下;或超出边界;
落在隔板上,可能向左或向右滑落,概率分别为50%。滑落后运动规律与左右滑坡相同。
假设两个隔板不相邻且左右滑坡总是以“/\”出现。小球入孔或超出边界则消失,记消失的概率为100%;小球若停下,记消失的概率为0。
如图a所示,小球随机落下,最终消失的平均概率计算过程如下:
(100%+100%+100%+0.5*(100%+0)+0+0+100%+100%+0.5*(100%+100%)+100%)/10=75%
编写VB程序求解小球消失的概率,程序运行界面如图b所示,代码如下。
Dim s As String
Dim prob As Single
Private Sub Command1_Click()
Dim i As Integer,c As String
s=Text1.Text
prob=0
For i=1 To Len(s)
c=Mid(s,i,1)
If c=”.” Then
prob=prob+100
ElseIf c=”/” Then
prob=prob+slope(i,True)
ElseIf c=”\” Then
prob=prob+slope(i,False)
ElseIf c=” \” Then
prob=prob+________
End If
Next i
Text2.Text=Str(prob/Len(s))
End Sub
Function slope(k As Integer,flag As Boolean) As Single
Dim c As String
If flag Then
c=Mid(s,j,1)
If c=”.” Then slope=100: Exit For
If c=”|” Or c=”\” Then slope=0: Exit For
Next j
If j<1 Then slope=100
Else
For j=k+1 To Len(s)
c=Mid(s,j,1)
If c=”.” Then slope=100: Exit For
If c=”|” Or c=”/” Then slope=0: Exit For
Next j
If j>Len(s) Then slope=100
End If
End Function
请回答下列问题:
(1)在文本框中输入:“/\—|.”则小球消失的概率为________。
(2)加框代码有误,请改正。
(3)请在划线处填入合适代码。
(4)若删除虚线框处的代码,运行程序,则________。(单选,填字母)
A.输出的概率值变大 B.输出的概率值变小
C.程序调试错误 D.输出的概率值不变
答案 (1)50% (2)k-1 to 1 Step -1 (3)(slope(i,True)+slope(i,False))*0.5 或其他等价答案 (4)D
解析 本题考核自定义函数的应用。解决该题目的关键是要充分利用图中所给数据,理解程序功能。题中给出10个小球落下的情况,第1个小球向左滑坡,出边界;第2个小球向右滑坡,滚入孔;第3个小球直接入孔,第4个小球掉隔板上,可能向左或向右滑落,概率分别为50%。若向左,入孔,向右滚过横板,遇左滑坡,停止;第5个小球掉横板,停止;第6个小球,左滑坡,向左滚过横板,碰到隔板,停止。依此类推。在文本框中输入:“/\—|.”则小球消失的概率分别为(100%+0+0+0.5*(0+100%)+100%)/5=50%。自定义函数中有两个参数,当flag=False时,j从k+1向后遍历,可见是向右滑坡的算法,那么flag=True时,应该是向左滑坡,从k的前一个位置开始,向左遍历。当遇隔板时,向左向右各有50%机率,因此两次调用函数。
【变式2】 某日期加密授权码生成方法描述如下:
(1)授权码由10位字符组成,前8位为日期的密文,后2位为验证码;
(2)取日期的第1位字符,若该字符第一次出现,则直接取其对应加密字符,否则取下一个不重复的加密字符。按此操作,依次取出该日期余下各位对应的加密字符;
(3)求出所有日期字符数值的和,将和除16取余得到一位验证码字符;若和不小于16,则将和除16取整加1得到另一位验证码字符,否则另一位验证码字符为“X”。取出验证码重复时,处理规则与(2)相同。加密(验证码)字符对应表如下:
值(十进制) 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
加密(验证码)字符 K n G j L t W b 0 a P H Z q Y c
小明设计了一个生成8位日期(YYYYMMDD格式)授权码的VB程序。程序功能如下:在文本框Text1中输入一个8位有效日期,单击“生成授权码”按钮Command1,在标签Label2中显示出该日期的授权码。运行效果如图所示。
(1)若输入的日期是“20181213”,则该授权码的验证码字符是_____________。
(2)请在划线处填入合适代码。
Dim f(0 To 15) As Integer
Const Code=”KnGjLtWb0aPHZqYc”
Private Sub Command1_Click()
Dim rq As String,sq As String,c As Integer,i As Integer,d As Integer
For i=0 To 15
f(i)=0
Next i
rq=Text1.Text
sq=””: d=0
If Len(rq) <>8 Then
Labe12.Caption=”请输入8位日期!”
Else
For i=1 To 8
c=Val(Mid(rq,i,1))
d=d+c
sq=____①____
Next i
If d>=16 Then
yz=GetChar(d Mod 16)+GetChar(d\16+1)
Else
yz=____②____
End If
Label2.Caption=sq+yz
End If
End Sub
Function GetChar(x As Integer) As String ′获取不重复的加密字符
Dim flag As Boolean
flag=False
Do While flag=False
f(x)=f(x)+1
If f(x)=1 Then
____③____
f(x)=f(x)+1
flag=True
Else
x=(x+1) Mod 10
End If
Loop
End Function
答案 (1)GKn0jLtWba (2)①sq+GetChar(c) ②GetChar(d Mod 16)+”X”
③GetChar=Mid(Code,x+1,1)
解析 若输入的日期是“20181213”,前4位互不重复,分别取出各自位置上的字符,后4位与前3位重复,对应的第4、5、6、7上的字符。自定义函数GetChar是获取数x在Code中获取不重复的加密字符,数组f是表示数字0-15出现的次数,初始值为0,下标为x的数组先加1再判断是否等于1,若等于1,表示该数字没有出现过,找到对应的加密字符。变量sp表示对日期的加密,每一位上的数字取出不重复的加密字符,并进行正向连接。当和d小于16时,有d Mod 16取出加密字符和“X”两位验证码。
考点二 递归算法
列出每步迭代的表达式,找出自定义函数的“出口”,即函数等于某个值时,返回的具体的值,而不是迭代表达式,最后把值依次代入。
【例3】 有如下VB程序:
Private Sub Command1_Click()
Dim n As Integer,x As String
n=Val(Text1.Text)
x=f(n)
Label1.Caption=x
End Sub
Function f(n As Integer) As String
Dim r As Integer
If n <>0 Then
r=n Mod 2
n=n\2
If r=0 Then
f=f(n)+”0”
Else
f=f(n)+”1”
End If
Else
f=”0”
End If
End Function
程序运行后,在Text1文本框中输入35,则在Label1上显示的内容是( )
A.0100111 B.0100011 C.1100010 D.1110010
解析 本题考核的是递归算法。自定义函数的功能是将整数n转换成二进制数,当n=0时不再重复计算,因此第1个字符是0。当n不为0时,把n Mod 2的值放在字符的右边。以输入35为例。f(35)=f(17)+”1”,f(17)=f(8)+”1”,f(8)=f(4)+”0”,f(4)=f(2)+”0”,f(2)=f(1)+”0”,f(1)=f(0)+”1”,f(0)=”0”,再逆向代入,得到答案。
B
【变式3】 以下VB程序段:
Private Sub Command1_Click()
Dim n As Integer,f As Integer
n=Val(Text1.Text)
f=fac(n)
Label2.Caption=Str(f)
End Sub
Function fac(n As Integer) As Integer
If n=1 Then fac=1 Else fac=n*fac(n-1)
End Function
A
程序运行时,若在文本框Text1中输入8,下列说法正确的是( )
A.程序运行出错 B.控件Label2中显示1
C.控件Label2中显示8 D.控件Label2中显示40320
解析 本题考核的知识点是递归的算法思想。在文本框Text1中输入8,将返回8*f(7),f(7)=7*f(6),f(6)=6*f(5),f(5)=5*f(4),f(4)=4*f(3),f(3)=3*f(2),f(2)=2*1,将f(2)的结果代回,f(8)=8!=40320,但函数返回值为整数,超出了整数的范围,将出现溢出的报错。
【变式4】 通过递归函数来实现“十进制整数转换为二进制数”的算法,程序代码如下,请将空白处填写完整。
Private Sub Command3_Click()
Text2.Text=db_dg(Val(Text1.Text))
End Sub
Private Function db_dg(n As Integer) As String
Dim p As Integer
If n=0 Then ′递归出口
db_dg=””
Else
p=n Mod 2
db_dg=________ ′递推关系
End If
End Function
答案 db_dg(n\2) & p
解析 假设一个测试数据来理解递归函数db_dg的运行过程。假设Val(Text1.Text)=6,则程序运行过程如下图所示:
根据图示程序运行过程,向下逐层递归调用函数时实际参数n值以及转换后的二进制数值。
考点三 VB连接数据库
考核的知识点有:一是连接数据库的步骤,先定义连接的语句表达,再用ADODB对象的open方法连接数据库。二是在数据表中查询数据。先定义查询语句(含查询的数据表,查询条件和显示字段)并打开查询,接着用循环结构从第1条记录开始,依次把相应的字段值读入到数组中去。注意数据表中第1个字段的编号为0,读取一条记录后,必须用MoveNext方法移动指针。
【例4】 有如下VB程序段:
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
conn.ConnectionString=”Provider=Microsoft.ACE.OLEDB.12.0;Data Source=” & App.Path & ”\词库.accdb”
conn.Open
Set rs.ActiveConnection=conn
rs.Open ”SELECT*FROM words”
n=0
Do While Not rs.EOF
n=n+1
en(n)=rs.Fields(1)
ch(n)=rs.Fields(2)
rs.MoveNext
Loop
rs.Close:conn.Close
C
下列说法中正确的是( )
①连接的数据库文件名是“\词库.accdb” ②程序运行后,变量n 的值表示该数据表中记录的总数 ③数组en(n)所存储的是数据表第 2 个字段的字段值 ④“ConnectionString”是conn对象的属性值 ⑤查询的数据表名称是“words” ⑥省略语句“rs.MoveNext”,程序也可以正常运行
A.①④⑤ B.③④⑥ C.②③⑤ D.②③④
解析 数据库文件名中不包含”\”,每读取一条记录,n的值增加1,因此n表示记录的总数。rs记录集中的字段序号从0开始,en(n)=rs.Fields(1),因此是数据表中第2个字段。“ConnectionString”是 conn 对象的属性名。从语句rs.Open ”SELECT*FROM words”可得查询的数据表名称。若省略了语句“rs.MoveNext”,指针停留在第1条记录上,因此不会满足条件Not rs.EOF,从而进入死循环。
【变式5】 (2020·6月温州适应性考试)某VB程序实现数据库管理应用,其相关数据库的部分界面如图所示,程序段如下。
Dim cn As New ADODB.Connection:Dim rs As New ADODB.Recordset
cn.ConnectionString=”Provider-Microsoft.ACE.OLEDB.12.0;Data Source=”+App.Path+”\stu.accdb”
cn.Open
Set rs.ActiveConnection=cn
rs.Open ”select*from xf”
rs.MoveFirst
num=0
Do While Not rs.EOF
num=num+1
a(num)=rs.Fields(”序号”)
c(num)=rs.Fields(”学分”)
d(num)=rs.Fields(”姓名”)
rs.MoveNext
Loop
rs.Close:cn.Close
C
下列说法错误的是( )
A.语句“rs.MoveFirst”的作用是将指针移到记录集对象rs的第1条记录
B.该程序所连接的数据库名称是“stu.accdb”,所查询的数据表名称是“xf”
C.加框处代码的功能等同于语句“b(num)=rs.Fields(2)”
D.对数据表中“序号”字段元素进行对分查找,所需的最多查找次数为8次
解析 本题考查VB连接数据库的基本知识。A选项MoveFirst指针移到第1条记录。B选项从cn.ConnectionString语句和rs.Open语句可以得知查询的数据库名称和数据表名称。C选项rs记录集中的字段序号从0开始,因此档案号应为rs.Fields(1)。D选项从图中可知,共有记录数144条,因此根据公式以2为底144的对数取整加1的值为8。
1.在VB中,设已定义函数过程f,它有三个实型传值参数。设a,b,c为实型变量,则下列能调用该函数的正确语句是( )
A.f B.f(a+b,b+c)
C.f(a+b,b+c,c+a) D.fa+b,b+c,c+a
解析 函数的格式为f(参数),已知有3个参数,因此B选项不正确。
C
2.在VB中,设已定义函数过程Function f(a As Integer,b As Integer) As String,下列说法不正确是( )
A.该函数的返回值一定是字符串型
B.语句f(3.5,2)不能正确调用函数
C.语句f(3) 不能正确调用函数
D.若a和b的值分别为1和2,则语句f(a,a+b)也可以正确调用函数
解析 B选项中,先把3.5转换成整型3,再去调用函数,因此B不正确。
B
3.小明在VB中定义了以下函数,功能是求a和b的最大公约数。
Function gcd( a As Integer,b As Integer)As Integer
Do While b>0
c=a Mod b
a=b
b=c
Loop
End Function
调试中发现计算结果一直是0。经过仔细观察与分析,发现错误的原因是( )
A.函数名有错 B.变量C没有定义
C.函数没有返回值 D.b>0应该改为b>=0
解析 必须通过函数名来返回函数的值。
C
4.(2020·9月嘉兴)有如下VB程序段:
Private Sub Command1_Click()
Const s1=”tea”
s2=”老师 Happy Teacher’s Day!”: s3=””
For i=1 To Len(s2)
If bijiao(s1,Mid(s2,i,1)) Then s3=s3+Str(i)+”,”
Next i
Text1.Text=s3
End Sub
Function bijiao(x As String,y As String) As Boolean
bijiao=False
For i=1 To Len(x)
If y=Mid(x,i,1) Then
bijiao=True: Exit Function
End If
Next i
End Function
执行上述程序段后,文本框Text1中显示的内容是( )
A.6,11,12,13,16,22, B.6,12,13,16,22,
C.4,9,10,11,14,20, D.4,10,11,14,20,
解析 自定义函数bijiao实现的功能是判断y在x中能否找到。将s2中每个字符分离开来,并且在s1中查找,如果能找到,把位置连接起来。
D
5.有如下VB程序段:
Function fx(i As Integer) As Integer
If i=1 Then
fx=5
Else
fx=5*2 ^ (i-1)+fx(i-1)
End If
End Function
Private Sub Command1_Click()
Dim n As Integer,sum As Integer,i As Integer
n=Val(Text1.Text): sum=0
For i=1 To n
sum=sum+fx(i)
Next i
Label1.Caption=Str(sum)
End Sub
若在Text1中输入4,单击Command1,则Label1中显示的内容为( )
A.55 B.75 C.80 D.130
解析 本题考查对递归算法的掌握。递归即调用自身函数,在函数中,每次循环调用5*2^(i-1)+f(i-1),当i为1时,直接返回5,作为递归边界。i等于4,则第一次计算f函数得到f(4)=40+f(3),计算f(3)得到f(3)=20+f(2),再次计算f(2)得到f(2)=15,因此f(1)=5,f(2)=15,f(3)=35,f(4)=75,四个数累加为130。
D
6.通过ADO的Recordset Recordset对象实例rs打开的记录,如下图所示。
序号 书名 书号 作者 售价
1 解忧杂货店 ISBN9787544270878 东野圭吾 39.5
2 摆渡人 ISBN9787550013247 克莱儿·麦克福尔 36
3 白夜行 ISBN9787544258609 东野圭吾 39.5
4 追风筝的人 ISBN9787208061644 卡勒德·胡赛尼 29
5 这就是二十四节气 ISBN9787511026118 高春香,邵敏 100
当前是第4条记录,要用 Fields集合返回第2个字段的值,以下代码正确的是( )
A.a(4)=rs.Fields(2) B.a(4)=rs.Fields(1)
C.a(4)=rs.Fields(书名) D.a(4)=rs.Fields(”书号”)
解析 第1个字段的下标为0,第2个字段的下标就为1,选项C,对书名要加引号。
B
7.某个VB应用程序中使用如下代码读取数据库中的信息:
Dim conn As New ADODB.Connection
Dim rs As New ADODB.Recordset
Dim n As Integer
Private Sub Form_Load()
conn.ConnectionString=”Provider=Microsoft.Ace.OLEDB.12.0;data source=”+App.Path+”\Data\data.accdb”
conn.Open
sql=”select*from student”
Set rs.ActiveConnection=conn
rs.Open sql
n=0
Do While Not rs.EOF
List1.AddItem rs(”name”)
n=n+1
rs.MoveNext
Loop
End Sub
运行上述程序,以下说法不正确的是( )
A.当前读取的数据库文件是Data文件夹中的data.accdb文件
B.数据库中存在一个名为student的数据表
C.List1列表框中将显示指定的数据表中所有记录name字段的值
D.窗体加载完成后,读取的数据表中总记录数为n-1
解析 从conn对象的ConnectionString属于值来看,连接的数据库名称是data.accdb,查询的数据表名称为student。列表框中只显示name字段的值。n表示记录的数量,初值为0,每读取一条,记录增加一条,因此总数为n。
D