过程 第 8章
? Sub过程
? Function过程的定义
? 过程调用
? 参数的传递
? 再谈形实结合
? 递归过程
? 变量的作用域
? 程序示例
? 多窗体程序设计
? 小结
1.VB中的模块 (文件 )概念
2.过程的概念
3.过程的种类,
.Sub:过程 (无返回值 )
.Function:函数
.Property:属性过程
Sub过程
在 Visual Basic中有两种 Sub过程,
即事件过程和通用过程。
? 事件过程
? 通用过程
8.1
事件过程 8.1.1
事件就是能被对象 (窗体和控件 )所识别的动
作。把这些对发生的事件进行处理的代码放在过
程中,这样的过程称为事件过程。
事件过程是窗体和控件的附属物。事件过程
分为 窗体事件 过程和 控件事件 过程两种。
1.定义事件过程
2.定义控件事件过程
3.建立事件过程
1.定义 窗体 事件过程
Private Sub Form_事件名 (〔 参数列表 〕 )
〔 局部变量和常数声明 〕
语句块
Eud Sub
说明
1) 窗体事件过程名由词, Form”或, MDIForm”,
下划线和事件名结合而成 。
2),Private”的前缀, 表示使用范围是模块级的
在该窗体之外是不可见的;
3) 事件过程 有无 参数,
完全由具体事件本身所决定 。
例如:
Private Sub Form_Load ()
Call Move ((Screen.Width- Width)/2),_
(Screen.Heigh- Heigh)/2)
End Sub
说明
窗体的若干事件
? Initialize(初始化)事件是在窗体被 加载之
前,窗体被配置的时候触发
? Load(加载)事件,VB把窗体从磁盘或从
磁盘缓冲区读入内存 时 发生
? Activate(激活)事件是在窗体已经被装入
内存,变成 被激活 的窗体时触发 (多次 )
? GotFocus事件在窗体成为当前焦点时触发
? 窗体各事件的发生次序
窗体各事件的发生次序
建立窗体 装入内存 窗体被激活
Load
语句
Initialize Load Activate
P158:窗体事件触发的过程
及其微妙的变化
New关键
字或 VB
自动建立
3.定义 控件 事件过程
Private Sub 控件名 __事件名 ([参数列表 ])
〔 局部变量和常数声明 〕
语句块
End Sub
说明
说明
1)控件事件过程名由控件名, 下划线和事件
名组成 。
2)控件事件过程也是私有过程, 属于包含它
的窗体模块 。
例如:
Private Sub Cmdend_Click()
End
End Sub
建立事件过程
(1) 双击窗体或控件
(2) 单击工程管理窗口中的代码编辑窗口
……
回顾三个正确
回目录
通用过程 8.1.2
SUB的种类,事件 过程与 通用 过程
? 除了事件过程以外的过程而称之。
? 具有一定功能的独立程序段,这个程序段
被称为通用过程。被其他过程调用,
? 通用过程是一个必须从另一个过程 (事件过
程或其它通用过程 )显式调用的程序段。
1.通用 Sub过程的定义
2.建立通用 Sub过程
通用 Sub过程的定义
? 通用 Sub 过程的一般形式是:
[Private | Public] [Static] Sub 过程名 ([形 参数列表 ])
[局部变量和常量声明 ]
End Sub
? Sub过程不能嵌套定义
头部与尾部
局部声明
过程体
语句块
[Exit Sub]
语句块
Sub关键字,过程名
? Sub 过程以 Sub语句开头,
? 结束于 End Sub语句。
? 过程名必须唯一。
? 过程名不能与模块级变量同名。
Private /Public /Static选项
? Private:Sub过程是模块级的 (私有的 )过程,
只能被本模块内的过程调用。
? Public:Sub过程是应用程序级的 (公有 的或
全局 的 )过程。
例如,call form1.xyz(12)
? 系统 默认 值为 Public。
? Static:过程中的局部变量全部是“静态”变
量
参数列表
?参数的 作用, …,
?定义过程头部中的参数称为 形式参数 。若有
多个参数时,各参数之间用逗号分隔。
?Visual Basic的过程可以没有参数,但括号
不可以省略。
形式参数的 格式为,( P161)
[Optional][ByVal][ByRef] __
变量名 [( )] [As 数据类型 ]
有要求 (P161)
2.如何建立通用过程
创建通用过程的方法有两种 。
第一种方法是:
打开代码编辑器窗口 …,
第二种方法是:
在代码窗口中的对象列表框中选, 通
用, …,
演示,..,返回子目录
Function过程的定义
Function过程的形式是:
…,,Function函数名 ([参数列表 ]) [AS数据类型 ]
[局部变量和常数声明 ]
[语句块 ]
[Exit Function]
[语句块 ]
[函数名 = 表达式 ]
End Function
8.2
函数体
函数的种类:系统函数与自定义函数
函数要返回值
函数要返回值
例 8--1
举例
Private Function Fact(ByVal N As Integer) As Long
Dim K As Integer
Fact = 1
If N = 0 Or N = 1 Then
Exit Function
Else
For K = 1 To N
Fact = Fact * K
Next K
End If
End Function
返回主目录
过程调用
? 事件过程的调用
? Sub过程调用
? 调用 Function过程
? 调用其它模块中的过程
8.3
事件 过程的调用 8.3.1
事件过程由一个发生的事件来 自动 调用
同一模块中的其它过程 显式 调用。
例如:( P163)
Private Sub cmdend_Click()
Dim Flg As Integer,L As Boolean
Call Form_Unload(Flg)
If Flg = 1 Then
MsgBox "不退出, 继续运行程序 "
End If
End Sub
以前的概念
新的概念
Sub过程 调用 8.3.2
?Sub过程和 Function过程,
必须在事件过程或其它过程中 显式 调用
?调用与返回的过程图:
调用过程的执行流程
主调程序
调用过程 A
End Sub
过程 A
End Sub
每当程序调用一个 Sub
过程或 Function过程时,
Visual Basic就将程序的
返回地址(断点)、参
数、以及局部变量等压
入栈内。被调用的过程
运行完后,Visual Basic
将回收存放变量和参数
的栈空间。然后返回断
点继续程序的运行。
1.用 Call语句调用 Sub过程
? 调用 Sub过程的形式是:
Call <过程名 > (实在参数表 )
? <过程名 >是被调用的过程名字。
控制转向此过程;
? 实在 参数与 形式 参数的 个数、类型和顺序
相 匹配 。有多个参数时各实在参数之间用
逗号 分隔。如果被调用过程是一个 无参 过
程,则括号可省略。
[8-2]
Private Sub Command1_Click()
Dim Inta As Integer,St As String
Inta = Text1.Text
Call Factor(Inta,St)
Text2.Text = St
End Sub
Private Sub Factor(ByVal N As Integer,S As String)
Dim I As Integer
For I = 1 To N- 1
If N Mod I = 0 Then S = S & Str(I)
Next I
End Sub
区分:过程的类型?
调用时,原始数据?结果在?
调用
2.用 过程名 作为一个调用语句
调用过程的形式是:
过程名 [实参 1[,实参 2,…… ]]
与第一种方式相比, 它有两点不同:
1) 不需要 关键字 Call;
2),实在参数表, 不需要 加括号 。
例如,Factor Inta,St
等价与,call factor (inta,st)
调用 Function过程
调用 Function过程的形式是,(一般 在表达式中 )
函数名 ([实在参数表 ]) 同 sin(0.5)
必须给参数加上括号。
VB也允许象调用 Sub过程那样调用 Function过程
例如,Call Exam (Inx)
Exam Inx
用这两种方法调用函数时 VB放弃 函数的返回值
[8-3] 求二个正整数的最大公约数的程序
8.3.3
Private Sub Form_Click()
Dim N As Integer,M As Integer,G As Integer
N = InputBox("输入 N "),M = InputBox("输入 M ")
G = Gcd(N,M)
Print N; " 和 "; M; " 的最大公约数是,"; G
End Sub
Private Function Gcd(ByVal A As Integer,ByVal BAs Integer)
Dim R As Integer
R = A Mod B
Do While R <> 0
A = B, B = R, R = A Mod B
Loop
Gcd = B ‘结果返回到函数名上
End Function
N-----A M-----B
返回子目录
调用其它模块中的过程 8.3.4
1,调用其他窗体模块中的公有过程
Call Form1.ExamSub([ 实参表 ] )
2,调用标准模块中的公有过程
?标准模块中也必须用 public定义
例,call module1.xyz(12)
?解决 同名 问题
?解决 内 部与 外 部的 同名 问题
举例,“sub#例”
参数的传递
什么是“形实结合”?
实现调用程序和被调用的过程之间的
数据传递。
8.4
?形参与实参
?按值传递参数
?按地址传递参数
?数组参数
?对象参数
形参与实参 8.4.1
1,形参
在 定义 过程 的 形参表 中,说明自变量的
类型 和 形态, 及在过程中所, 扮演, 的角
色 。 形参可以是:
1) 除定长字符串 变量之外的合法变量名;
2)数组名:后面跟 ( ) 。
2,实参
实参是在 过程调用 的实参表中 。
3.“形实结合, 是按对应, 位置, 结合 ;举
例,
Private Sub Examsub(X AS integen,Y AS single)
……
End Sub
Private Sub Form_Click()
Dim X AS single,Y AS Integes
……
Call Examsub(Y,X)
……
End Sub
问, 1.是什么过程?
2.形参?
3.实参?
4.形实结合?
“形实结合”时的对应关系
形 参 实 参
变量 变量, 常数, 表达式, 数组元素, 对象
数组 数组
举例
示例
Private Sub Test (A AS single,Loc AS Boulean,_
Array1() AS Integez,Chr1 AS String)
……
End Sub
Private Sub Form_Click ( )
Dim X AS Single St AS sting*5
Dim A (5) AS Integez
Call Test (X^2,True,A,St)
End Sub
按 值 传递参数
? 程序设计 技巧,形实结合的两种方式
? 定义形参时用 Byval:表示按 值 传递的形参。
传递的只是实参变量的副本。
? 当采用 值 传递时,过程对参数的任何改变
实际上都是对临时单元中值的改变,仅在
过程内部有效,而 不会影响实参 变量本身。
? 示例程序
8.4.2
Private Sub Command1_Click()
Dim M As Integer,N As Integer
M = 15,N = 20
Call V-Change(M,N)
Print "m="; M,"n="; N
End Sub
Private Sub V-Change(ByVal X As Integer,_
ByVal Y As Integer)
X = X + 20
Y = X + Y
Print "X="; X,"Y="; Y
End Sub
RUN
图 8-5,8-6
15
20
15
20
返回地址内存
栈
Call Value(M,N)
X
Y
M
N
15
20
35
55
返回地址内存
栈
X
Y
M
N
BACK
X修改为 35,
但 M仍为 15
过
程
中
形
参
X
调
用
过
程
实
参
M
按 地址 传递参数
? 定义形参用 Byref或缺省,表示形参为按地
址传递。
? 原理:形参和实参 共用 内存的,同一,地
址,即 共享 同一个存储单元,形参 值在过
程中的一旦 被改变,相应的 实参 值 也 跟随
着 被改变 了。
? 示例程序
? 关于按地址传递的副作用
8.4.3
Private Sub Command1_Click()
Dim M As Integer,N As Integer
M = 15,N = 20
Call Value_Change(M,N)
Print "m="; M,"n="; N
End Sub
Private Sub Value_Change(X As Integer,_
ByVal Y As Integer)
X = X + 20 ?改变 X的值,实际就是改变 M的值
Y = X + Y
Print "X="; X,"Y="; Y
End Sub
缺省,为 Byref,
按地址传递
原理图
按 地址 传递的原理图
15
20
1000
20
返回地址
内存 栈Call Value(M,N)
X
Y
M
N
1000
1002
值 地址
35
20
1000
55
返回地址
内存 栈
X
Y
M
N
1000
1002
值 地址
M的地址
N的值M的值
改变了
N的值
没有改变
X = X + 20
Y = X + Y
编写程序计算 5!+4!+3!+2!+1!的值 。
Private Sub Form_click()
Dim Sum As Integer,I As Integer
For I = 5 To 1 Step8-1
Sum = Sum + Fact(I)
Next I
Print "SUM = "; Sum
End Sub
Private Function Fact(N As Integer) As Integer
Fact = 1
Do While N > 0
Fact = Fact * N
N = N- 1 ’ 改变了 N的值, I改变吗?
Loop
End Function
按值?按址?
返回后,I=?
先 RUN
怎么办? P172
数组参数 8.4.4
定义 过程时, VB允 许把数组作为 形式参数,
形参数组名 ( ) [As 数据类型 ] 注:形参只能是 ( )
1.形参数组只能是按 地址传递 的参数 。
2.对应实参必须也是数组且数据 类型相一致 。
3.实参表中只写数组名, 后面不跟圆括号 。
4.若 实参 用 固定 数组, 则在过程中 不 可以用 Dim语句
5.若 实参 用 动态 数组, 则在过程中 可用 ReDim语句重新
设置大小 。
注意,形实结合,严格要求!!!
举例
Private Sub Form_Click()
Dim Arraya() As Integer,I As Integer
ReDim Arraya(5)
Print "调用前数组维上界是,"; UBound(Arraya)
Call Changedim(Arraya) ?实形参的类型一致 。 但数组可固定, 可动态
Print "调用后数组维上界是,"; UBound(Arraya)
Print "数组各元素值是,";
For I = 1 To UBound(Arraya)
Print Arraya(I);
Next I
Print
End Sub
Private Sub Changedim(A( ) As Integer)
Dim I As Integer
ReDim Preserve A(7)
For I = 1 To 7
A(I) = I
Next I
End SubBACK
形参只允许 A( )
对象参数
在 Visual Basic中也可以把 对象 作为 参数
向过程 传递 。
在形参表中,把形参变量的类型声明为
,Control”就可以向过程传递 控件 。
在形参表中,把形参变量的类型声明为
,Form”则可向过程传递 窗体 。
对象的传递只能是 按地址 传递。
8.4.5
举例
对象 名称 (Name) 标题 (Caption)
窗体 1 Frmfirst 对象参数的传递
标签 1 Lab1 欢迎使用 VB5.0
命令按钮 1 Cmd1 控件参数传递
命令按钮 2 Cmd2 窗件参数传递
窗体 2 Frmsecond Frmsecond
命令按钮 3 Cmd3 返回
Private Sub Cmd1_Click()
Call Objarg(Lab1)
End Sub
Private Sub Cmd2_Click()
Call Frmarg(frmsecond)
End Sub
Private Sub Form_Load()
frmfirst.Left = 2000
frmfirst.Top = 1500
Lab1.Caption = "学习使用 VB6.0"
End Sub
1.谁先被执行?
2.实参是控件 lab1
3,实参是窗体 frmsecond
Private Sub Objarg(Lad As Control)
Lad.BackColor = &HFF0000
Lad.ForeColor = &HFFFF&
Lad.Font = 14
Lad.FontItalic = True
Lad.Caption = " 对象参数的传递 "
End Sub
Private Sub Frmarg(F As Form)
F.Left = (Screen.Width8- F.Width) / 2
F.Top = (Screen.Height8- F.Height) / 2
frmfirst.Hide
F.Show
End Sub
传递控件 Lad
传递窗体 F
RUN回子目录
Call Objarg(Lab1)
Call Frmarg(frmsecond)
再谈形实结合 (1)P172
Private Sub Command1_Click()
Dim V1 As Integer,V2 As Integer,V3 As Integer
V1 = 2,V2 = 3,V3 = 4
Debug.Print V1 + V2 + V3 * Fun_Add(V1,V2,V3)
End Sub
Private Function Fun_Add(a As Integer,_
b As Integer,c As Integer)
a = a + 10
b = b + 10
c = c + 10
Fun_Add = a + b + c
End Function
函数的优先级高,
先调用函数,
改变了 V1等值
本想输出值 161,
但结果输出的是 571
再谈形实结合 (2)P172
下面是一个参数数据 类型转换 的程序示例 。
Private Sub Form_Click()
Dim S As Single
S = 125.5
Call Convert((S),"12" + ".5")
End Sub
Private Sub Convert(Inx As Integer,_
Sing As Single)
Inx = Inx * 2
Sing = Sing + 23
Print "Inx="; Inx,"Sing="; Sing
End Sub 注意
1、按 值 结合,(含,址 变 值” 结合)
“马马虎虎;基本要求”
2、按 址 结合(实参变量对形参变量)
“严格要求”
举例,P172
形实结合合法性讨论:
回主目录
Private Sub Form_Click()
Dim S As Single
S = 125.5
Call Convert((S),"12" + ".5")
End Sub
Private Sub Convert(Inx As Integer,Sing As Single)
Inx = Inx * 2
Sing = Sing + 23
Print "Inx="; Inx,"Sing="; Sing
End Sub
1.形参要求按 址 结合,实际调用时可以将实参 改变 成按 值 结合 ;
2.如果 按值 结合,系统在 可能 的情况下,自动转换类型,结合 ;
3.如果 实变 对 形变 的 按址 结合,系统将,严格要求, ;
思考:如将 (s)改为 S?
递归过程 8.5
1、高级程序设计 技巧,
自己调用自己 ——递归
2、满足 条件,
?解决的问题有规律;
?有底
3、递归的 过程,
?下推
?上归
4,注意,从哪“下推”,就从那“上归”!
Private Function Fact(Byval N As Integer) As Long
If N = 0 Or N = 1 Then
Fact = 1
Else
Fact = N * Fact(N- 1)
End If
End Function
Private Sub Form_Click()
Dim N As Integer,F As Long
N = InputBox("输入一个正整数 ")
F = Fact(N) ‘ 调用函数
Print N; "!="; F
End Sub
设计求 n!的递归函数过程
发生递归
思考,若将 Byval N 中的 Byval去掉
思考:如下面有 print N 语句,结果?
主目录
思考
Fact(1)
If N = 1then
Fact = 1
Else
Fact = 1 * Fact(1-1)
End If
End Function
Fact(2)
If N = 1then
Fact = 1
Else
Fact = 2 * Fact(2-1)
End If
End Function
Fact(3)
If N = 1then
Fact = 1
Else
Fact = 3 * Fact(3-1)
End If
End Function
F=Fact(3)
3*Fact(2)
2*Fact(1)
返回函数值 1
返回函数值 2
返回函数值 6
下
推
上
归到底
动画
主目录
BACK
2011-7-18 Visual Basic Programming 54
END
2011年 7月 18日
变量的作用域
1、什么是 变量和过程 的 作用域?
2、如何 设置与鉴别 他们的作用域?
根据定义他们的 位置 和使用定义的 语句 。
8.6
?过程级变量
?模块级 /全局变量
?关于同名变量
?静态变量
过程级变量
? 位置:
在 某过程中 声明的变量是过程级的变量,其
作用范围仅限于该过程。出此过程被系统释
放,无效。
? 语句:
Dim; Static
? 注意:
不同于形参。
8.6.1
函数 Local_Variable
Private Function Local_Variable(N As Integer) As Integer
Dim X As Integer,Y As Integer,Z As Integer
X = N * 3
Y = X + 4
Z = X + Y
Local_Variable = X + Y- Z
End Function
模块级 /全局变量
? 位置:
在某 模块 中的,通用部分” 声明的变量。
? 语句:
(1) private,Dim:模块 级变量
作用域,本模块内
(2) Public,全局 变量
作用域,整个程序
模块级变量的例子
全局变量的例子
8.6.2
模块 级变量的例子
Dim TestString As String ‘在通用处定义
Private Sub Form_ Activate ()
Print,在 Foram_ Activate 事件过程中调用,"; TestString
Call ShowTestString
End Sub
Private Sub Form_Load()
TestString = "测试变量作用域 "
End Sub
Private Sub ShowTestString( )
Print "在过程 ShowTestString 中 调用,"; TestString
End Sub
三个过程均可访问的变量
RUN
关于同名变量
? 当变量的 作用域不同 时,变量的名字可以相同。可
用,模块名,变量名,访问其他模块中与自己模块中
的同名变量。
? 当不同作用域的同名变量发生冲突时,原则为 先内
后外;即 优先访问局限性大的变量。
? 示例程序
8.6.4
静态变量 8.6.5
1.静态变量是过程变量;
2.在过程中用关键字 Static定义。
3.静态变量的生命周期:
程序 开始 到 结束,静态变量的存储空间一直
保留,系统一直不释放。(同全局变量),所
以,其 值一直保持 。
4.比较 static变量与 Dim变量的区别
静态变量示例
静态变量的副作用
程序示例
例 8-4:简易文本编辑程序
例 8-5:利用级数法编程求 arcsin函数值
例 8-6:冒泡法排序
例 8-7:任意十进制正整数转换成 N 进制数
例 8-8:用辛普森法求定积分
例 8-9:用递归函数求两整数的最大公约数
例 8-10:验证大于 5的奇数可表成三素数和
例 8-11:直接插入排序
8.7
简易文本编辑程序 例
8-4
? 文本框的 MulitiLine属性被设为 True;
scrollbar属性设为 3 ;文件菜单包含了“打
开”、“关闭”、“退出”等命令;另外还
使用了公共对话框部件,以便通过它获得标
准的“打开”文件与“保存”文件对话框
? 使用,打开”命令,可以打开一个文本文件
并通过文本框的 Text属性把文件的内容显示
在文本框内。用户可浏览文件内容,也进行
编辑操作。使用,保存”命令,通过保存对
话框可将编辑过的文本再存盘
? 在退出程序时,利用 Unload事件过程,将提
示用户保存对已修改过的文本内容。在该过
程序界面设计
Option Explicit
Dim flag As Boolean
Private Sub Form_Unload(Cancel As Integer)
Dim f As Integer
If flag Then
f = MsgBox("文本已改变,要 保存吗?",vbYesNo,"程
If f = 6 Then
Call M1_2_Click
Else
End
End If
Else
End
End If
End Sub
Private Sub M1_1_Click()
Dim Iname As String,s As String
CommonDialog1.Filter = "*.txt(文本文件)|*.txt" '设
利用级数法编程求 arcsin函数值
例 8-5
? 要求用户通过 InputBox函数输入自变
量 x及允许误差值。若输入,0.5,1e-5”,
程序将自动把输入的数据分解为两
部分并分别赋给 x与 eps;函数过程
afun则用于求解级数第 n项的值
?
?
??
?
????????
?????????????????
???
????
??
???
???
n
i
i
ii
xixxxxxx
1
)12(753
1
)12)(2(42
)12(31
7642
531
542
31
32s i n
Option Explicit
Private Sub Cmdcalc_Click()
Dim x As Single,n As Integer,eps As Single
Dim s As Single,a As Single,temp As String
temp = InputBox("请输入一个绝 对值小于等于1的数与允许
"求函数值","0,1e-5")
temp = Trim(temp)
n = InStr(temp,",")
x = Left(temp,n - 1),eps = Right(temp,Len(temp) -
s = x,n = 1
Do
a = afun(x,n)
If a <= eps Then Exit Do
s = s + a
n = n + 1
Loop
Label2.Caption = "arcsin(" & CStr(x) & ")="
Text1.Text = s
冒泡法排序 例
8-6
? 冒泡法排序的算法
? 程序中设置 变量 Switch,在比较过程中,若发生数
据交换,将 其 设置为真,否 则将开关设为假。当
一轮比较处理结束后,都要检测 Switch,如果 Switch
的值为 True就需进行新一轮的比较。
? 在第二轮比较中,依次比较 Sort(1)和 Sort(2),
Sort(2)和 Sort(3),…… 直到对 Sort(8-2)和 Sort(8-1)
进行比较处理后,次大数存放在元素 Sort(8-1)中了。
如此重复地一轮一轮地比较,直到第 I轮比较时没
有发生数据交换,即 Switch 的值为 False时,则说
明数据已排好序。
? 程序代码
冒泡法排序的算法
? 将待排序的数存放在 Sort数组中,首先比较
Sort(1)和 Sort(2),如果 Sort(1) > Sort(2),则交
换这两个元素的值,接着比较 Sort(2)和
Sort(3),(此时的 Sort(2)可能是刚交换来的
值)若 Sort(2)> Sort(3),则交换这两个元素
的值。重复此过程,直到处理完 Sort(8-1)和
Sort(n)这两个元素的比较。经过 8-1 次比较
处理,最大的数被传到数组最后一个元素
中,而较小的数就会象气泡一样上浮。
任意十进制正整数转换成 N 进制数
例 8-7
? 程序中所使用
的对象及属性
设置
? 程序代码
程序中所使用的对象及属性设
置
控件名称 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 Frm1 数制转换
标签 1 Lal1 将十进制数转换为 无
标签 2 Lal2 进制数 无
标签 3 Lal3 十进制数 无
标签 4 Lal4 进制数 无
文本框 1 Text1 无 空白
文本框 2 Text2 无 空白
文本框 3 Text3 无 空白
命令按钮 1 Cmd1 开始转换 无
命令按钮 2 Cmd2 结束 无
用辛普森法求定积分 例
8-8
? 辛普森法求积分公式为
? 程序代码
y = {f(a)+f(b)+4[f(a+h)+f(a+3h)+… ]+2[f(a+2h)+f(a+4h)+… ]}
3
h
其中, a,b为积分区间 [a,b];若将区间分为 n等分, 则 h=
n
ab )( ?
用递归函数求两整数的最大公约数
例 8-9
? 程序中的 Function过程
Gcd 是按照欧几里德算
法(也称为辗转除法)
设计的一个递归函数,
其边界条件 (终止条件 )是:
当 R = 0时,函数赋值返
回
? 本例使用的对象及属性
设置
? 程序代码
对象及属性设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 Frm1
标签 1 Lal1 整数 无
标签 2 Lal2 与整数 无
标签 3 Lal3 最大公约数是 无
文本框 1 Text1 无 空白
文本框 2 Text2 无 空白
文本框 3 Text3 无 空白
命令按钮 1 cmd1 求公约数 无
命令按钮 2 cmd2 结束 无
验证大于 5的奇数可表成三素数和 例
8-10
? 给定一个大于 5的奇数 N,调用 Prime过程求
出 N以内的所有素数,放在一个数组内,再
通过穷举法,从该组素数中找出满足验证
条件的三个素数
? 程序代码
? 程序代码
直接插入排序 例
8-11
Temp
Sort(N)…… Sort(k) Sort(k+1)Sort(1) Sort(I) ……Sort(k+2) ……
①
②
③
多窗体程序设计
为了使程序结构分明,通常把程序分成
许多窗体。而各窗体的共用过程则放到标
准模块 (Module)中。在多窗体程序中,每个
窗体都可以有自己的界面和程序代码,完
成不同的操作。
? 多窗体程序设计
? 设置启动窗体
8.8
多窗体程序设计
多窗体程序设计和单窗体程序设计一样
基本分为三步,即建立程序界面,编写程
序代码和运行程序
? 添加窗体
? 在标准模块中添加过程
8.8.1
添加窗体
? 多窗体程序的界面是由多个窗体组成,第一个窗
体建立,通过, 文件, (File)菜单中的, 新工
程, (New Project)命令实现。其它窗体可以通过
,工程, (Project)菜单中的, 添加窗体, (Add
Form)命令实现。每创建一个窗体,该窗体作为一
个对象添加到工程中去了。可以在, 工程管理器
窗口中的 Form文件夹中看到该各窗体文件名。也
可以右键点击, 工程管理器窗口中的 Form文件夹,
从弹出的快捷菜单中,再点击, 添加, (Add)后,
从它的子菜单中,选择, 窗体, (Form)来,给工
程增加窗体。
在标准模块中添加过程
? 把多个窗体都要使的共用过程放置在标准
模块中,可以通过, 工程, 菜单中, 添加
模块, (Add Module)命令实现。在标准模块
中可以定义私有 (Private)过程,也可以定义
公有 (Public)过程。私有过程只能在模块内
调内,而公有过程,可以在应用程序的任
何地方调用。
? [例 8-12]一个既可以求排列,又能求组合的
应用程序
[例 8-12] 既可以求排列又能求组合的应用程
序
? 在该程序中包含 Frmmain,FrmCombinh和
FrmPermute等三个窗体和一个标准模块
? 三个窗体的参考界面
? 窗体 Frmmain 使用的对象及属性设置
? 窗体 Frmcombin 使用的对象及属性设置
? 窗体 Frmpermute 使用的对象及属性设置
? 标准模块 Module1中的程序代码
? 窗体 Frmmain的程序代码
? 窗体 Frmcombin的程序代码
? 窗体 Frmpermute的程序代码
三个窗体的参考界面
窗体 Frmmain 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 1 Frmmain From1
标签 1 Lal1 Visual Basic多窗
体程序
命令按钮 1 Cmd1 求组合
命令按钮 2 Cmd2 求排列
命令按钮 3 Cmd3 结束
窗体 Frmcombin 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 2 FrmCombin From2 组 合
标签 1 Lal1 C
标签 2 Lal2 =
文本框 1 Txtm M
文本框 2 Txtn N
文本框 3 Trtv
命令按钮 1 Cmdjs 计算
命令按钮 2 Cmdretn 返回
窗体 Frmpermute 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 3 Frmpesmute From3 排 列
标签 1 Lal1 A
标签 2 Lal2 =
文本框 1 Txtm M
文本筐 2 Txtn N
文本框 3 Txtv
命令按钮 1 Cmdjs 计算
命令按钮 2 Cmdretu 返回
标准模块 Module1中的程序代
码
Public Function Fact(n As Integer) As Long
If n = 0 Or n = 1 Then
Fact = 1
Else
Fact = n * Fact(n- 1)
End If
End Function
窗体 Frmmain的程序代码
Private Sub Cmd1_Click()
Frmmain.Hide
Frmcombin.Show
End Sub
Private Sub Cmd2_Click()
Frmmain.Hide
Frmpermute.Show
End Sub
Private Sub Cmd3_Click()
End
End Sub
设置启动窗体
多窗体程序是由多个窗体构成。在缺省
情况下,VB在应用程序执行时,把设计时
的第一个窗体,指定为启动窗体。如果希
望在程序运行时,首先显示其它的窗体而
不是设计时的第一个窗体,那么我们就应
该指定某一个窗体作为启动窗体。
? 指定一个启动窗体
? 指定一个启动过程
8.8.2
指定一个启动窗体
? 从, 工程, (project)菜单中,选择, 工程属
性, (project Properties)
? 在, 工程1 ──工程属性对话框, 中选取
,一般, (General)
? 在, 启动对象, (Startup Object)下拉列表框
中选取作为启动窗体的窗体
? 选取确定。, 工程属性, 对话框如 图 8-21所
示
图 8-21
指定一个启动过程
? 在标准模块中,编写一个名为 Main的通用
过程
? 从, 工程, 菜单中,选取, 工程属性,
? 在, 工程1 ──工程属性对话框, 中选取
,一般,
?, 启动对象, 下拉列表框中选取 Sub Main作
为启动过程
Sub Main
? 运行程序时,VB首先执行标准模块中的 Sub Main
过程,依次将窗体 Frmpermut和 Frmcombin装入内
存,显示窗体 Frmmain。这样窗体 Frmaim成为活动
窗体,就可以执行该窗体中的过程
Private Sub Main()
Load Frmpermute
Load Frmconbin
Frmmain Show
End Sub
小结
? 过程的定义与调用(事件过程和通用 Sub过
程,Function过程)
? 参数的传递方式(按值传递、按地址传递)
? 变量作用域的概念与应用
? 静态变量的应用
? 递归过程的定义方法及执行过程
? 应用(级数求和、数制转换、判断素数、
插入排序)
? Sub过程
? Function过程的定义
? 过程调用
? 参数的传递
? 再谈形实结合
? 递归过程
? 变量的作用域
? 程序示例
? 多窗体程序设计
? 小结
1.VB中的模块 (文件 )概念
2.过程的概念
3.过程的种类,
.Sub:过程 (无返回值 )
.Function:函数
.Property:属性过程
Sub过程
在 Visual Basic中有两种 Sub过程,
即事件过程和通用过程。
? 事件过程
? 通用过程
8.1
事件过程 8.1.1
事件就是能被对象 (窗体和控件 )所识别的动
作。把这些对发生的事件进行处理的代码放在过
程中,这样的过程称为事件过程。
事件过程是窗体和控件的附属物。事件过程
分为 窗体事件 过程和 控件事件 过程两种。
1.定义事件过程
2.定义控件事件过程
3.建立事件过程
1.定义 窗体 事件过程
Private Sub Form_事件名 (〔 参数列表 〕 )
〔 局部变量和常数声明 〕
语句块
Eud Sub
说明
1) 窗体事件过程名由词, Form”或, MDIForm”,
下划线和事件名结合而成 。
2),Private”的前缀, 表示使用范围是模块级的
在该窗体之外是不可见的;
3) 事件过程 有无 参数,
完全由具体事件本身所决定 。
例如:
Private Sub Form_Load ()
Call Move ((Screen.Width- Width)/2),_
(Screen.Heigh- Heigh)/2)
End Sub
说明
窗体的若干事件
? Initialize(初始化)事件是在窗体被 加载之
前,窗体被配置的时候触发
? Load(加载)事件,VB把窗体从磁盘或从
磁盘缓冲区读入内存 时 发生
? Activate(激活)事件是在窗体已经被装入
内存,变成 被激活 的窗体时触发 (多次 )
? GotFocus事件在窗体成为当前焦点时触发
? 窗体各事件的发生次序
窗体各事件的发生次序
建立窗体 装入内存 窗体被激活
Load
语句
Initialize Load Activate
P158:窗体事件触发的过程
及其微妙的变化
New关键
字或 VB
自动建立
3.定义 控件 事件过程
Private Sub 控件名 __事件名 ([参数列表 ])
〔 局部变量和常数声明 〕
语句块
End Sub
说明
说明
1)控件事件过程名由控件名, 下划线和事件
名组成 。
2)控件事件过程也是私有过程, 属于包含它
的窗体模块 。
例如:
Private Sub Cmdend_Click()
End
End Sub
建立事件过程
(1) 双击窗体或控件
(2) 单击工程管理窗口中的代码编辑窗口
……
回顾三个正确
回目录
通用过程 8.1.2
SUB的种类,事件 过程与 通用 过程
? 除了事件过程以外的过程而称之。
? 具有一定功能的独立程序段,这个程序段
被称为通用过程。被其他过程调用,
? 通用过程是一个必须从另一个过程 (事件过
程或其它通用过程 )显式调用的程序段。
1.通用 Sub过程的定义
2.建立通用 Sub过程
通用 Sub过程的定义
? 通用 Sub 过程的一般形式是:
[Private | Public] [Static] Sub 过程名 ([形 参数列表 ])
[局部变量和常量声明 ]
End Sub
? Sub过程不能嵌套定义
头部与尾部
局部声明
过程体
语句块
[Exit Sub]
语句块
Sub关键字,过程名
? Sub 过程以 Sub语句开头,
? 结束于 End Sub语句。
? 过程名必须唯一。
? 过程名不能与模块级变量同名。
Private /Public /Static选项
? Private:Sub过程是模块级的 (私有的 )过程,
只能被本模块内的过程调用。
? Public:Sub过程是应用程序级的 (公有 的或
全局 的 )过程。
例如,call form1.xyz(12)
? 系统 默认 值为 Public。
? Static:过程中的局部变量全部是“静态”变
量
参数列表
?参数的 作用, …,
?定义过程头部中的参数称为 形式参数 。若有
多个参数时,各参数之间用逗号分隔。
?Visual Basic的过程可以没有参数,但括号
不可以省略。
形式参数的 格式为,( P161)
[Optional][ByVal][ByRef] __
变量名 [( )] [As 数据类型 ]
有要求 (P161)
2.如何建立通用过程
创建通用过程的方法有两种 。
第一种方法是:
打开代码编辑器窗口 …,
第二种方法是:
在代码窗口中的对象列表框中选, 通
用, …,
演示,..,返回子目录
Function过程的定义
Function过程的形式是:
…,,Function函数名 ([参数列表 ]) [AS数据类型 ]
[局部变量和常数声明 ]
[语句块 ]
[Exit Function]
[语句块 ]
[函数名 = 表达式 ]
End Function
8.2
函数体
函数的种类:系统函数与自定义函数
函数要返回值
函数要返回值
例 8--1
举例
Private Function Fact(ByVal N As Integer) As Long
Dim K As Integer
Fact = 1
If N = 0 Or N = 1 Then
Exit Function
Else
For K = 1 To N
Fact = Fact * K
Next K
End If
End Function
返回主目录
过程调用
? 事件过程的调用
? Sub过程调用
? 调用 Function过程
? 调用其它模块中的过程
8.3
事件 过程的调用 8.3.1
事件过程由一个发生的事件来 自动 调用
同一模块中的其它过程 显式 调用。
例如:( P163)
Private Sub cmdend_Click()
Dim Flg As Integer,L As Boolean
Call Form_Unload(Flg)
If Flg = 1 Then
MsgBox "不退出, 继续运行程序 "
End If
End Sub
以前的概念
新的概念
Sub过程 调用 8.3.2
?Sub过程和 Function过程,
必须在事件过程或其它过程中 显式 调用
?调用与返回的过程图:
调用过程的执行流程
主调程序
调用过程 A
End Sub
过程 A
End Sub
每当程序调用一个 Sub
过程或 Function过程时,
Visual Basic就将程序的
返回地址(断点)、参
数、以及局部变量等压
入栈内。被调用的过程
运行完后,Visual Basic
将回收存放变量和参数
的栈空间。然后返回断
点继续程序的运行。
1.用 Call语句调用 Sub过程
? 调用 Sub过程的形式是:
Call <过程名 > (实在参数表 )
? <过程名 >是被调用的过程名字。
控制转向此过程;
? 实在 参数与 形式 参数的 个数、类型和顺序
相 匹配 。有多个参数时各实在参数之间用
逗号 分隔。如果被调用过程是一个 无参 过
程,则括号可省略。
[8-2]
Private Sub Command1_Click()
Dim Inta As Integer,St As String
Inta = Text1.Text
Call Factor(Inta,St)
Text2.Text = St
End Sub
Private Sub Factor(ByVal N As Integer,S As String)
Dim I As Integer
For I = 1 To N- 1
If N Mod I = 0 Then S = S & Str(I)
Next I
End Sub
区分:过程的类型?
调用时,原始数据?结果在?
调用
2.用 过程名 作为一个调用语句
调用过程的形式是:
过程名 [实参 1[,实参 2,…… ]]
与第一种方式相比, 它有两点不同:
1) 不需要 关键字 Call;
2),实在参数表, 不需要 加括号 。
例如,Factor Inta,St
等价与,call factor (inta,st)
调用 Function过程
调用 Function过程的形式是,(一般 在表达式中 )
函数名 ([实在参数表 ]) 同 sin(0.5)
必须给参数加上括号。
VB也允许象调用 Sub过程那样调用 Function过程
例如,Call Exam (Inx)
Exam Inx
用这两种方法调用函数时 VB放弃 函数的返回值
[8-3] 求二个正整数的最大公约数的程序
8.3.3
Private Sub Form_Click()
Dim N As Integer,M As Integer,G As Integer
N = InputBox("输入 N "),M = InputBox("输入 M ")
G = Gcd(N,M)
Print N; " 和 "; M; " 的最大公约数是,"; G
End Sub
Private Function Gcd(ByVal A As Integer,ByVal BAs Integer)
Dim R As Integer
R = A Mod B
Do While R <> 0
A = B, B = R, R = A Mod B
Loop
Gcd = B ‘结果返回到函数名上
End Function
N-----A M-----B
返回子目录
调用其它模块中的过程 8.3.4
1,调用其他窗体模块中的公有过程
Call Form1.ExamSub([ 实参表 ] )
2,调用标准模块中的公有过程
?标准模块中也必须用 public定义
例,call module1.xyz(12)
?解决 同名 问题
?解决 内 部与 外 部的 同名 问题
举例,“sub#例”
参数的传递
什么是“形实结合”?
实现调用程序和被调用的过程之间的
数据传递。
8.4
?形参与实参
?按值传递参数
?按地址传递参数
?数组参数
?对象参数
形参与实参 8.4.1
1,形参
在 定义 过程 的 形参表 中,说明自变量的
类型 和 形态, 及在过程中所, 扮演, 的角
色 。 形参可以是:
1) 除定长字符串 变量之外的合法变量名;
2)数组名:后面跟 ( ) 。
2,实参
实参是在 过程调用 的实参表中 。
3.“形实结合, 是按对应, 位置, 结合 ;举
例,
Private Sub Examsub(X AS integen,Y AS single)
……
End Sub
Private Sub Form_Click()
Dim X AS single,Y AS Integes
……
Call Examsub(Y,X)
……
End Sub
问, 1.是什么过程?
2.形参?
3.实参?
4.形实结合?
“形实结合”时的对应关系
形 参 实 参
变量 变量, 常数, 表达式, 数组元素, 对象
数组 数组
举例
示例
Private Sub Test (A AS single,Loc AS Boulean,_
Array1() AS Integez,Chr1 AS String)
……
End Sub
Private Sub Form_Click ( )
Dim X AS Single St AS sting*5
Dim A (5) AS Integez
Call Test (X^2,True,A,St)
End Sub
按 值 传递参数
? 程序设计 技巧,形实结合的两种方式
? 定义形参时用 Byval:表示按 值 传递的形参。
传递的只是实参变量的副本。
? 当采用 值 传递时,过程对参数的任何改变
实际上都是对临时单元中值的改变,仅在
过程内部有效,而 不会影响实参 变量本身。
? 示例程序
8.4.2
Private Sub Command1_Click()
Dim M As Integer,N As Integer
M = 15,N = 20
Call V-Change(M,N)
Print "m="; M,"n="; N
End Sub
Private Sub V-Change(ByVal X As Integer,_
ByVal Y As Integer)
X = X + 20
Y = X + Y
Print "X="; X,"Y="; Y
End Sub
RUN
图 8-5,8-6
15
20
15
20
返回地址内存
栈
Call Value(M,N)
X
Y
M
N
15
20
35
55
返回地址内存
栈
X
Y
M
N
BACK
X修改为 35,
但 M仍为 15
过
程
中
形
参
X
调
用
过
程
实
参
M
按 地址 传递参数
? 定义形参用 Byref或缺省,表示形参为按地
址传递。
? 原理:形参和实参 共用 内存的,同一,地
址,即 共享 同一个存储单元,形参 值在过
程中的一旦 被改变,相应的 实参 值 也 跟随
着 被改变 了。
? 示例程序
? 关于按地址传递的副作用
8.4.3
Private Sub Command1_Click()
Dim M As Integer,N As Integer
M = 15,N = 20
Call Value_Change(M,N)
Print "m="; M,"n="; N
End Sub
Private Sub Value_Change(X As Integer,_
ByVal Y As Integer)
X = X + 20 ?改变 X的值,实际就是改变 M的值
Y = X + Y
Print "X="; X,"Y="; Y
End Sub
缺省,为 Byref,
按地址传递
原理图
按 地址 传递的原理图
15
20
1000
20
返回地址
内存 栈Call Value(M,N)
X
Y
M
N
1000
1002
值 地址
35
20
1000
55
返回地址
内存 栈
X
Y
M
N
1000
1002
值 地址
M的地址
N的值M的值
改变了
N的值
没有改变
X = X + 20
Y = X + Y
编写程序计算 5!+4!+3!+2!+1!的值 。
Private Sub Form_click()
Dim Sum As Integer,I As Integer
For I = 5 To 1 Step8-1
Sum = Sum + Fact(I)
Next I
Print "SUM = "; Sum
End Sub
Private Function Fact(N As Integer) As Integer
Fact = 1
Do While N > 0
Fact = Fact * N
N = N- 1 ’ 改变了 N的值, I改变吗?
Loop
End Function
按值?按址?
返回后,I=?
先 RUN
怎么办? P172
数组参数 8.4.4
定义 过程时, VB允 许把数组作为 形式参数,
形参数组名 ( ) [As 数据类型 ] 注:形参只能是 ( )
1.形参数组只能是按 地址传递 的参数 。
2.对应实参必须也是数组且数据 类型相一致 。
3.实参表中只写数组名, 后面不跟圆括号 。
4.若 实参 用 固定 数组, 则在过程中 不 可以用 Dim语句
5.若 实参 用 动态 数组, 则在过程中 可用 ReDim语句重新
设置大小 。
注意,形实结合,严格要求!!!
举例
Private Sub Form_Click()
Dim Arraya() As Integer,I As Integer
ReDim Arraya(5)
Print "调用前数组维上界是,"; UBound(Arraya)
Call Changedim(Arraya) ?实形参的类型一致 。 但数组可固定, 可动态
Print "调用后数组维上界是,"; UBound(Arraya)
Print "数组各元素值是,";
For I = 1 To UBound(Arraya)
Print Arraya(I);
Next I
End Sub
Private Sub Changedim(A( ) As Integer)
Dim I As Integer
ReDim Preserve A(7)
For I = 1 To 7
A(I) = I
Next I
End SubBACK
形参只允许 A( )
对象参数
在 Visual Basic中也可以把 对象 作为 参数
向过程 传递 。
在形参表中,把形参变量的类型声明为
,Control”就可以向过程传递 控件 。
在形参表中,把形参变量的类型声明为
,Form”则可向过程传递 窗体 。
对象的传递只能是 按地址 传递。
8.4.5
举例
对象 名称 (Name) 标题 (Caption)
窗体 1 Frmfirst 对象参数的传递
标签 1 Lab1 欢迎使用 VB5.0
命令按钮 1 Cmd1 控件参数传递
命令按钮 2 Cmd2 窗件参数传递
窗体 2 Frmsecond Frmsecond
命令按钮 3 Cmd3 返回
Private Sub Cmd1_Click()
Call Objarg(Lab1)
End Sub
Private Sub Cmd2_Click()
Call Frmarg(frmsecond)
End Sub
Private Sub Form_Load()
frmfirst.Left = 2000
frmfirst.Top = 1500
Lab1.Caption = "学习使用 VB6.0"
End Sub
1.谁先被执行?
2.实参是控件 lab1
3,实参是窗体 frmsecond
Private Sub Objarg(Lad As Control)
Lad.BackColor = &HFF0000
Lad.ForeColor = &HFFFF&
Lad.Font = 14
Lad.FontItalic = True
Lad.Caption = " 对象参数的传递 "
End Sub
Private Sub Frmarg(F As Form)
F.Left = (Screen.Width8- F.Width) / 2
F.Top = (Screen.Height8- F.Height) / 2
frmfirst.Hide
F.Show
End Sub
传递控件 Lad
传递窗体 F
RUN回子目录
Call Objarg(Lab1)
Call Frmarg(frmsecond)
再谈形实结合 (1)P172
Private Sub Command1_Click()
Dim V1 As Integer,V2 As Integer,V3 As Integer
V1 = 2,V2 = 3,V3 = 4
Debug.Print V1 + V2 + V3 * Fun_Add(V1,V2,V3)
End Sub
Private Function Fun_Add(a As Integer,_
b As Integer,c As Integer)
a = a + 10
b = b + 10
c = c + 10
Fun_Add = a + b + c
End Function
函数的优先级高,
先调用函数,
改变了 V1等值
本想输出值 161,
但结果输出的是 571
再谈形实结合 (2)P172
下面是一个参数数据 类型转换 的程序示例 。
Private Sub Form_Click()
Dim S As Single
S = 125.5
Call Convert((S),"12" + ".5")
End Sub
Private Sub Convert(Inx As Integer,_
Sing As Single)
Inx = Inx * 2
Sing = Sing + 23
Print "Inx="; Inx,"Sing="; Sing
End Sub 注意
1、按 值 结合,(含,址 变 值” 结合)
“马马虎虎;基本要求”
2、按 址 结合(实参变量对形参变量)
“严格要求”
举例,P172
形实结合合法性讨论:
回主目录
Private Sub Form_Click()
Dim S As Single
S = 125.5
Call Convert((S),"12" + ".5")
End Sub
Private Sub Convert(Inx As Integer,Sing As Single)
Inx = Inx * 2
Sing = Sing + 23
Print "Inx="; Inx,"Sing="; Sing
End Sub
1.形参要求按 址 结合,实际调用时可以将实参 改变 成按 值 结合 ;
2.如果 按值 结合,系统在 可能 的情况下,自动转换类型,结合 ;
3.如果 实变 对 形变 的 按址 结合,系统将,严格要求, ;
思考:如将 (s)改为 S?
递归过程 8.5
1、高级程序设计 技巧,
自己调用自己 ——递归
2、满足 条件,
?解决的问题有规律;
?有底
3、递归的 过程,
?下推
?上归
4,注意,从哪“下推”,就从那“上归”!
Private Function Fact(Byval N As Integer) As Long
If N = 0 Or N = 1 Then
Fact = 1
Else
Fact = N * Fact(N- 1)
End If
End Function
Private Sub Form_Click()
Dim N As Integer,F As Long
N = InputBox("输入一个正整数 ")
F = Fact(N) ‘ 调用函数
Print N; "!="; F
End Sub
设计求 n!的递归函数过程
发生递归
思考,若将 Byval N 中的 Byval去掉
思考:如下面有 print N 语句,结果?
主目录
思考
Fact(1)
If N = 1then
Fact = 1
Else
Fact = 1 * Fact(1-1)
End If
End Function
Fact(2)
If N = 1then
Fact = 1
Else
Fact = 2 * Fact(2-1)
End If
End Function
Fact(3)
If N = 1then
Fact = 1
Else
Fact = 3 * Fact(3-1)
End If
End Function
F=Fact(3)
3*Fact(2)
2*Fact(1)
返回函数值 1
返回函数值 2
返回函数值 6
下
推
上
归到底
动画
主目录
BACK
2011-7-18 Visual Basic Programming 54
END
2011年 7月 18日
变量的作用域
1、什么是 变量和过程 的 作用域?
2、如何 设置与鉴别 他们的作用域?
根据定义他们的 位置 和使用定义的 语句 。
8.6
?过程级变量
?模块级 /全局变量
?关于同名变量
?静态变量
过程级变量
? 位置:
在 某过程中 声明的变量是过程级的变量,其
作用范围仅限于该过程。出此过程被系统释
放,无效。
? 语句:
Dim; Static
? 注意:
不同于形参。
8.6.1
函数 Local_Variable
Private Function Local_Variable(N As Integer) As Integer
Dim X As Integer,Y As Integer,Z As Integer
X = N * 3
Y = X + 4
Z = X + Y
Local_Variable = X + Y- Z
End Function
模块级 /全局变量
? 位置:
在某 模块 中的,通用部分” 声明的变量。
? 语句:
(1) private,Dim:模块 级变量
作用域,本模块内
(2) Public,全局 变量
作用域,整个程序
模块级变量的例子
全局变量的例子
8.6.2
模块 级变量的例子
Dim TestString As String ‘在通用处定义
Private Sub Form_ Activate ()
Print,在 Foram_ Activate 事件过程中调用,"; TestString
Call ShowTestString
End Sub
Private Sub Form_Load()
TestString = "测试变量作用域 "
End Sub
Private Sub ShowTestString( )
Print "在过程 ShowTestString 中 调用,"; TestString
End Sub
三个过程均可访问的变量
RUN
关于同名变量
? 当变量的 作用域不同 时,变量的名字可以相同。可
用,模块名,变量名,访问其他模块中与自己模块中
的同名变量。
? 当不同作用域的同名变量发生冲突时,原则为 先内
后外;即 优先访问局限性大的变量。
? 示例程序
8.6.4
静态变量 8.6.5
1.静态变量是过程变量;
2.在过程中用关键字 Static定义。
3.静态变量的生命周期:
程序 开始 到 结束,静态变量的存储空间一直
保留,系统一直不释放。(同全局变量),所
以,其 值一直保持 。
4.比较 static变量与 Dim变量的区别
静态变量示例
静态变量的副作用
程序示例
例 8-4:简易文本编辑程序
例 8-5:利用级数法编程求 arcsin函数值
例 8-6:冒泡法排序
例 8-7:任意十进制正整数转换成 N 进制数
例 8-8:用辛普森法求定积分
例 8-9:用递归函数求两整数的最大公约数
例 8-10:验证大于 5的奇数可表成三素数和
例 8-11:直接插入排序
8.7
简易文本编辑程序 例
8-4
? 文本框的 MulitiLine属性被设为 True;
scrollbar属性设为 3 ;文件菜单包含了“打
开”、“关闭”、“退出”等命令;另外还
使用了公共对话框部件,以便通过它获得标
准的“打开”文件与“保存”文件对话框
? 使用,打开”命令,可以打开一个文本文件
并通过文本框的 Text属性把文件的内容显示
在文本框内。用户可浏览文件内容,也进行
编辑操作。使用,保存”命令,通过保存对
话框可将编辑过的文本再存盘
? 在退出程序时,利用 Unload事件过程,将提
示用户保存对已修改过的文本内容。在该过
程序界面设计
Option Explicit
Dim flag As Boolean
Private Sub Form_Unload(Cancel As Integer)
Dim f As Integer
If flag Then
f = MsgBox("文本已改变,要 保存吗?",vbYesNo,"程
If f = 6 Then
Call M1_2_Click
Else
End
End If
Else
End
End If
End Sub
Private Sub M1_1_Click()
Dim Iname As String,s As String
CommonDialog1.Filter = "*.txt(文本文件)|*.txt" '设
利用级数法编程求 arcsin函数值
例 8-5
? 要求用户通过 InputBox函数输入自变
量 x及允许误差值。若输入,0.5,1e-5”,
程序将自动把输入的数据分解为两
部分并分别赋给 x与 eps;函数过程
afun则用于求解级数第 n项的值
?
?
??
?
????????
?????????????????
???
????
??
???
???
n
i
i
ii
xixxxxxx
1
)12(753
1
)12)(2(42
)12(31
7642
531
542
31
32s i n
Option Explicit
Private Sub Cmdcalc_Click()
Dim x As Single,n As Integer,eps As Single
Dim s As Single,a As Single,temp As String
temp = InputBox("请输入一个绝 对值小于等于1的数与允许
"求函数值","0,1e-5")
temp = Trim(temp)
n = InStr(temp,",")
x = Left(temp,n - 1),eps = Right(temp,Len(temp) -
s = x,n = 1
Do
a = afun(x,n)
If a <= eps Then Exit Do
s = s + a
n = n + 1
Loop
Label2.Caption = "arcsin(" & CStr(x) & ")="
Text1.Text = s
冒泡法排序 例
8-6
? 冒泡法排序的算法
? 程序中设置 变量 Switch,在比较过程中,若发生数
据交换,将 其 设置为真,否 则将开关设为假。当
一轮比较处理结束后,都要检测 Switch,如果 Switch
的值为 True就需进行新一轮的比较。
? 在第二轮比较中,依次比较 Sort(1)和 Sort(2),
Sort(2)和 Sort(3),…… 直到对 Sort(8-2)和 Sort(8-1)
进行比较处理后,次大数存放在元素 Sort(8-1)中了。
如此重复地一轮一轮地比较,直到第 I轮比较时没
有发生数据交换,即 Switch 的值为 False时,则说
明数据已排好序。
? 程序代码
冒泡法排序的算法
? 将待排序的数存放在 Sort数组中,首先比较
Sort(1)和 Sort(2),如果 Sort(1) > Sort(2),则交
换这两个元素的值,接着比较 Sort(2)和
Sort(3),(此时的 Sort(2)可能是刚交换来的
值)若 Sort(2)> Sort(3),则交换这两个元素
的值。重复此过程,直到处理完 Sort(8-1)和
Sort(n)这两个元素的比较。经过 8-1 次比较
处理,最大的数被传到数组最后一个元素
中,而较小的数就会象气泡一样上浮。
任意十进制正整数转换成 N 进制数
例 8-7
? 程序中所使用
的对象及属性
设置
? 程序代码
程序中所使用的对象及属性设
置
控件名称 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 Frm1 数制转换
标签 1 Lal1 将十进制数转换为 无
标签 2 Lal2 进制数 无
标签 3 Lal3 十进制数 无
标签 4 Lal4 进制数 无
文本框 1 Text1 无 空白
文本框 2 Text2 无 空白
文本框 3 Text3 无 空白
命令按钮 1 Cmd1 开始转换 无
命令按钮 2 Cmd2 结束 无
用辛普森法求定积分 例
8-8
? 辛普森法求积分公式为
? 程序代码
y = {f(a)+f(b)+4[f(a+h)+f(a+3h)+… ]+2[f(a+2h)+f(a+4h)+… ]}
3
h
其中, a,b为积分区间 [a,b];若将区间分为 n等分, 则 h=
n
ab )( ?
用递归函数求两整数的最大公约数
例 8-9
? 程序中的 Function过程
Gcd 是按照欧几里德算
法(也称为辗转除法)
设计的一个递归函数,
其边界条件 (终止条件 )是:
当 R = 0时,函数赋值返
回
? 本例使用的对象及属性
设置
? 程序代码
对象及属性设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 Frm1
标签 1 Lal1 整数 无
标签 2 Lal2 与整数 无
标签 3 Lal3 最大公约数是 无
文本框 1 Text1 无 空白
文本框 2 Text2 无 空白
文本框 3 Text3 无 空白
命令按钮 1 cmd1 求公约数 无
命令按钮 2 cmd2 结束 无
验证大于 5的奇数可表成三素数和 例
8-10
? 给定一个大于 5的奇数 N,调用 Prime过程求
出 N以内的所有素数,放在一个数组内,再
通过穷举法,从该组素数中找出满足验证
条件的三个素数
? 程序代码
? 程序代码
直接插入排序 例
8-11
Temp
Sort(N)…… Sort(k) Sort(k+1)Sort(1) Sort(I) ……Sort(k+2) ……
①
②
③
多窗体程序设计
为了使程序结构分明,通常把程序分成
许多窗体。而各窗体的共用过程则放到标
准模块 (Module)中。在多窗体程序中,每个
窗体都可以有自己的界面和程序代码,完
成不同的操作。
? 多窗体程序设计
? 设置启动窗体
8.8
多窗体程序设计
多窗体程序设计和单窗体程序设计一样
基本分为三步,即建立程序界面,编写程
序代码和运行程序
? 添加窗体
? 在标准模块中添加过程
8.8.1
添加窗体
? 多窗体程序的界面是由多个窗体组成,第一个窗
体建立,通过, 文件, (File)菜单中的, 新工
程, (New Project)命令实现。其它窗体可以通过
,工程, (Project)菜单中的, 添加窗体, (Add
Form)命令实现。每创建一个窗体,该窗体作为一
个对象添加到工程中去了。可以在, 工程管理器
窗口中的 Form文件夹中看到该各窗体文件名。也
可以右键点击, 工程管理器窗口中的 Form文件夹,
从弹出的快捷菜单中,再点击, 添加, (Add)后,
从它的子菜单中,选择, 窗体, (Form)来,给工
程增加窗体。
在标准模块中添加过程
? 把多个窗体都要使的共用过程放置在标准
模块中,可以通过, 工程, 菜单中, 添加
模块, (Add Module)命令实现。在标准模块
中可以定义私有 (Private)过程,也可以定义
公有 (Public)过程。私有过程只能在模块内
调内,而公有过程,可以在应用程序的任
何地方调用。
? [例 8-12]一个既可以求排列,又能求组合的
应用程序
[例 8-12] 既可以求排列又能求组合的应用程
序
? 在该程序中包含 Frmmain,FrmCombinh和
FrmPermute等三个窗体和一个标准模块
? 三个窗体的参考界面
? 窗体 Frmmain 使用的对象及属性设置
? 窗体 Frmcombin 使用的对象及属性设置
? 窗体 Frmpermute 使用的对象及属性设置
? 标准模块 Module1中的程序代码
? 窗体 Frmmain的程序代码
? 窗体 Frmcombin的程序代码
? 窗体 Frmpermute的程序代码
三个窗体的参考界面
窗体 Frmmain 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 1 Frmmain From1
标签 1 Lal1 Visual Basic多窗
体程序
命令按钮 1 Cmd1 求组合
命令按钮 2 Cmd2 求排列
命令按钮 3 Cmd3 结束
窗体 Frmcombin 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 2 FrmCombin From2 组 合
标签 1 Lal1 C
标签 2 Lal2 =
文本框 1 Txtm M
文本框 2 Txtn N
文本框 3 Trtv
命令按钮 1 Cmdjs 计算
命令按钮 2 Cmdretn 返回
窗体 Frmpermute 使用的对象及属性
设置
对象 名称 (Name) 标题 (Caption) 文本 (Text)
窗体 3 Frmpesmute From3 排 列
标签 1 Lal1 A
标签 2 Lal2 =
文本框 1 Txtm M
文本筐 2 Txtn N
文本框 3 Txtv
命令按钮 1 Cmdjs 计算
命令按钮 2 Cmdretu 返回
标准模块 Module1中的程序代
码
Public Function Fact(n As Integer) As Long
If n = 0 Or n = 1 Then
Fact = 1
Else
Fact = n * Fact(n- 1)
End If
End Function
窗体 Frmmain的程序代码
Private Sub Cmd1_Click()
Frmmain.Hide
Frmcombin.Show
End Sub
Private Sub Cmd2_Click()
Frmmain.Hide
Frmpermute.Show
End Sub
Private Sub Cmd3_Click()
End
End Sub
设置启动窗体
多窗体程序是由多个窗体构成。在缺省
情况下,VB在应用程序执行时,把设计时
的第一个窗体,指定为启动窗体。如果希
望在程序运行时,首先显示其它的窗体而
不是设计时的第一个窗体,那么我们就应
该指定某一个窗体作为启动窗体。
? 指定一个启动窗体
? 指定一个启动过程
8.8.2
指定一个启动窗体
? 从, 工程, (project)菜单中,选择, 工程属
性, (project Properties)
? 在, 工程1 ──工程属性对话框, 中选取
,一般, (General)
? 在, 启动对象, (Startup Object)下拉列表框
中选取作为启动窗体的窗体
? 选取确定。, 工程属性, 对话框如 图 8-21所
示
图 8-21
指定一个启动过程
? 在标准模块中,编写一个名为 Main的通用
过程
? 从, 工程, 菜单中,选取, 工程属性,
? 在, 工程1 ──工程属性对话框, 中选取
,一般,
?, 启动对象, 下拉列表框中选取 Sub Main作
为启动过程
Sub Main
? 运行程序时,VB首先执行标准模块中的 Sub Main
过程,依次将窗体 Frmpermut和 Frmcombin装入内
存,显示窗体 Frmmain。这样窗体 Frmaim成为活动
窗体,就可以执行该窗体中的过程
Private Sub Main()
Load Frmpermute
Load Frmconbin
Frmmain Show
End Sub
小结
? 过程的定义与调用(事件过程和通用 Sub过
程,Function过程)
? 参数的传递方式(按值传递、按地址传递)
? 变量作用域的概念与应用
? 静态变量的应用
? 递归过程的定义方法及执行过程
? 应用(级数求和、数制转换、判断素数、
插入排序)