Professional Documents
Culture Documents
计算机软件专业
人 民 邮 电 出 版 社
图书在版编目(CIP)数据
中文 Visual Basic 6.0 实用教程:结构化程序设计/沈大林,杨旭,关点,杜金编著.
—北京:人民邮电出版社,2005.6
中等职业学校计算机技能型紧缺人才培养规划教材.计算机软件专业
ISBN 7-115-13279-8
内 容 提 要
本书按项目驱动方式,以知识点配合实例的方法进行讲解,同时注意到知识的完整性、系统性和实用
性。全书共分 7 章,除了介绍大量的知识点外,还介绍了近 100 个应用实例。
本书为中等职业学校计算机软件专业教材,也可以作为各种计算机短期培训班的培训教材,以及广大
计算机爱好者自学或参考用书。
中等职业学校计算机技能型紧缺人才培养规划教材
计算机软件专业
中文 Visual Basic 6.0 实用教程——结构化程序设计
♦ 编 著 沈大林 杨 旭 关 点 杜 金 等
策划编辑 滑 玉
责任编辑 须春美
♦ 人民邮电出版社出版发行 北京市崇文区夕照寺街 14 号
邮编 100061 电子函件 315@ptpress.com.cn
网址 http://www.ptpress.com.cn
北京艺辉印刷有限公司印刷
新华书店总店北京发行所经销
♦ 开本:787×1092 1/16
印张:18.5
字数:438 千字 2005 年 6 月第 1 版
印数:1 – 3 000 册 2005 年 6 月北京第 1 次印刷
ISBN 7-115-13279-8/TP·4578
定价:25.00 元
读者服务热线:(010)67170985 印装质量热线:(010)67129223
中等职业学校计算机技能型紧缺人才培养规划教材
编 委 会
主 任 武马群
委 员 (以汉语拼音为序)
陈道波 陈丽敏 韩祖德 李 红 李文刚 李亚平
刘玉山 潘 沈大林 苏永昌 孙振业 谭建伟
王宇昕 向 伟 许成云 詹 虹 张惠珍 张 平
张世民 周越山 朱荣国 朱同庆
秘 书 张孟玮 赵鹏飞
编者的话
编者
丛书前言
实施信息化的关键在人才,在我国各行各业都需要大批的各个层次的计算机应用专业人
才。在未来几年内,我国经济和社会发展对计算机应用与软件专业初级人才具有很大的需求,
而这些人才的培养主要应由中等职业教育来承担。要培养具备综合职业能力和全面素质,直
接在生产、服务、技术和管理等第一线工作的技能型人才,必须在课程开发上,从职业岗位
技能分析入手,以教材建设推动中等职业教育教学改革,从而提高中等职业教育质量。
人民邮电出版社根据《教育部等七部门关于进一步加强职业教育工作的若干意见》
的指示精神,在深入调查研究的基础上,会同企业技术专家、中等职业学校教师、职业
教育教研人员按照专业的“培养目标与规格”教学要求进行整体规划设计了本套教材。
本套教材以教育部办公厅、信息产业部办公厅联合颁布的“中等职业学校计算机应用与
软件技术专业领域技能型紧缺人才培养培训指导方案”为依据,遵循“以全面素质为基
础,以职业能力为本位;以企业需求为基本依据,以就业为导向;适应行业技术发展,
体现教学内容的先进性和前瞻性;以学生为主体,体现教学组织的科学性和灵活性”等
技能型紧缺人才培养培训的基本原则。
本套教材适用于中等职业学校计算机及相关专业,按计算机软件、多媒体应用技术、
计算机网络技术及应用等 3 个专业组织编写。在教学内容的编排上,力求着重提高受教育
者的职业能力,具备如下特色特点:
(1)在具备一定的知识系统性和知识完整性的情况下,突出中等职业教育的特点,在
写作的过程中把握好“必须”和“足够”这两个“度”
。
(2)任务驱动,项目教学。让学生零距离接触所学知识,拓展学生的职业技能。
(3)按照中等职业教育的教学规律和学生认知特点讲解各个知识点,选择大量与知
识点紧密结合的案例。
(4)由浅及深,由易到难,循序渐进,通俗易懂,理论与案例制作相结合,实用与技
巧相结合。
(5)注重培养学生的学习兴趣、独立思考能力、创造性和再学习能力。
(6)适量介绍有关业内的专业知识和案例,使学生学习后可以尽快胜任岗位工作。
为了方便教师教学,我们提供辅助教师教学的“电子教案、习题答案以及模拟考试试
卷”
,其中部分教材配备为老师教学而提供的多媒体素材库,并发布在人民邮电出版社网站
(www.ptpress.com.cn)的下载区中。
随着中等职业教育的深入改革,编写中等职业教育教材始终是一个新课题;我们衷心
希望,全国从事中等职业教育的教师与企业技术专家与我们联系,帮助我们加强中等职业
教育教材建设,进一步提高教材质量。对于教材中存在的不当之处,恳请广大读者在使用
过程中给我们多提宝贵意见。联系方式:zhangmengwei@ptpress.com.cn
目 录
第 1 章 结构化程序设计概述 ........................................................................................................ 1
1.1 Visual Basic 6.0 简介和工作环境 ........................................................................................ 1
1.2 第 1 个简单的 Visual Basic 程序 ......................................................................................... 9
1.3 求 10 以内的偶数和 ........................................................................................................... 16
1.4 选择窗体 ............................................................................................................................. 22
思考与练习 .................................................................................................................................. 28
第 2 章 中文 Visual Basic 6.0 编程基础 ................................................................................ 31
2.1 输入密码 ............................................................................................................................. 31
2.2 计算圆周长、面积和球体积 ............................................................................................. 42
2.3 函数运算 ............................................................................................................................. 48
2.4 使用 Windows 的记事本和游戏程序 ................................................................................ 54
2.5 使用 Print 方法输出信息 ................................................................................................... 59
思考与练习 .................................................................................................................................. 62
第 3 章 基本算法和控制结构 ...................................................................................................... 65
3.1 提取人民币的方案 ............................................................................................................. 65
3.2 计算运费 ............................................................................................................................. 71
3.3 求一元二次方程的解 ......................................................................................................... 77
3.4 九九乘法表 ......................................................................................................................... 84
3.5 连续自然数的和 ................................................................................................................. 92
思考与练习 .................................................................................................................................. 97
第 4 章 优化算法和程序设计方法 ............................................................................................ 102
4.1 优化算法—有趣的 4 个自然数 ................................................................................... 102
4.2 解不定方程式 ................................................................................................................... 108
4.3 求 300 以内的素数和 ....................................................................................................... 113
4.4 两个数的最大公约数与最小公倍数 ............................................................................... 116
4.5 字符三角形图案 ............................................................................................................... 120
4.6 逻辑推理——谁是跳水运动员 ....................................................................................... 126
4.7 不同进制数之间的转换 ................................................................................................... 130
思考与练习 ................................................................................................................................ 137
2 中文 Visual Basic 6.0 实用教程—结构化程序设计
容与版本基本无关,如果屏幕显示的有些内容与用户所用系统不同,那就是版本不同的
缘故。
3.Visual Basic 语言的主要特点
Visual Basic 语言一方面继承了其早期 Basic 语言所具有的程序设计语言简单易用的特
点,另一方面在其编程系统中采用了面向对象、事件驱动的编程机制,用一种巧妙的方法把
Windows 的编程复杂性封装起来,提供了一种所见即所得的面向对象、事件驱动的可视化程
序设计工具。
可视化与面向对象程序设计是当今最流行的编程技术。Visual Basic 语言使得程序设计不
再只是程序开发者的专长,任何一个对程序设计有兴趣的人,只要愿意学习,很快就可以掌
握编程的方法,用 Visual Basic 6.0 开发出有用的程序。Visual Basic 程序设计语言的主要特点
如下。
(1)友好的 Visual Basic 集成开发环境:用户可快速设计界面、编写程序、调试程序,
直至把应用程序编译,生成.EXE 可执行文件,在 Windows 中运行。
(2)简单易学:它采用所见即所得的可视化程序设计方法,这样可以不需要编写大量代
码去描述界面外观,而只要使用预先建立的控件,即可像堆积木似的在屏幕上将界面外观制
作出来。程序员的编程工作仅限于编写事件驱动对象后所完成任务的程序,而各个事件动作
之间不一定有联系。这样的应用程序代码一般较短,采用结构化的程序设计语言,继承了
QBasic 语言的特点,而且易于维护,初学者只要掌握几个关键词就可以建立实用的应用程序。
Visual Basic 使程序设计成为一种享受,程序设计的效率也大大得到提高。
(3)事件驱动:传统的程序设计是一种面向过程的方式,程序总是按事先设计的流程运
行。在 Visual Basic 中,事件(即在程序运行中产生的动作、状况的改变等)掌握着程序运
行的流向,每个事件都能驱动一段程序的运行(即事件过程)。事件(Event)是指发生在某
一对象上的事情,是 Visual Basic 中预先设置好的,可以被对象识别的动作。在事件过程中,
可以输入相应的程序代码,当产生该事件时,这些代码得到执行,完成相应的动作,以对该
事件作出回应。
例如:按钮可以响应鼠标单击(Click)、鼠标移动(MouseMove)、鼠标按钮弹起(MouseUp)
等鼠标事件,又可响应键盘按下(KeyDown)等键盘事件。可以在按钮的事件过程中,添加
显示文字、打开文件、关闭窗口等所需要执行的程序代码。
(4)面向对象:采用面向对象的程序设计方法(OOP),是把具有共性的程序和数据封
装起来视为一个对象,对象(Object)是 Visual Basic 应用程序的基本单元,每个对象都作为
一个完整的独立组件出现在程序中。
用 Visual Basic 编程是用对象组装程序,在设计程序时只需要使用工具箱中的现有控件,
根据界面设计的要求,直接在屏幕上制作出窗口、菜单、按钮和滚动条等不同类型的对象,
并为每个对象设置属性。在程序中只要针对该对象进行简单的语句调用,就能执行所需要完
成的功能。
1.标题栏
中文 Visual Basic 6.0 的标题栏位于窗口的顶部,它的最左边有一个图标,单击该图标,
调出菜单,可对窗口进行还原、移动、最小化、最大化和关闭等操作。图标的右边显示打开
的 Visual Basic 工程文件名称(例如:
“工程 1”
)、“Microsoft Visual Basic”文字和系统的工作
状态,例如“设计”、“运行”和“中断”等。
标题栏的右边有 3 个按钮,从左到右分别为“最小化”按钮 、“最大化”按钮 和“关
闭”按钮 。单击“最小化”按钮,窗口会缩小为 Windows 任务栏上的一个按钮;单击“最
大化”按钮,窗口会放大到整个屏幕,此时按钮变成“向下还原”按钮 ;单击“向下还原”
按钮,窗口会变回原来的大小,此时按钮变成“最大化”按钮;单击“关闭”按钮,窗口会
被关闭。
双击标题栏也可以在“最大化”和“向下还原”状态之间切换,调整窗口的大小。
4 中文 Visual Basic 6.0 实用教程—结构化程序设计
2.菜单栏
菜单栏在标题栏的下边,单击主菜单选项,会调出它的子菜单。单击菜单之外的任何地
方或按 Esc 键,可以关闭已打开的菜单。中文 Visual Basic 6.0 菜单的形式与其他 Windows 软
件的菜单形式基本相同,都遵循以下的约定。
① 菜单中的菜单命令名称为深色时,表示当前可使用;为浅色时,表示当前不能使用。
② 如果菜单名后边有省略号(…),则表示单击该菜单选项后,会弹出一个对话框,要
求选定执行该菜单命令的有关选项。
③ 如果菜单名后边有黑三角(4),则表示该菜单选项有下一级联级菜单,将给出进一
步的选项。
④ 菜单项右边的组合按键名称,表示执行该菜单选项的对应热键,按下热键可以在不
打开菜单的情况下直接执行菜单命令。
3.标准工具栏
菜单栏的下边是标准工具栏。为了使用方便,中文 Visual Basic 6.0 把一些常用的操作命
令以按钮的形式组成一个标准工具栏,如图 1-1-2 中所示。标准工具栏中各工具按钮的名称
和作用如表 1-1-1 所示。
表 1-1-1 标准工具栏中各工具按钮的名称和作用
图 标 名 称 作 用
用来添加新的工程到工作组中。单击其右边的箭头,将弹出一个下拉菜单,
添加 Standard EXE 工程
可以从中选择需要添加的工程类型
用来添加新的窗体到工程中,单击其右边的箭头,将弹出一个下拉菜单,可
添加窗体
以从中选择需要添加的窗体类型
剪切 将选中的对象剪切到剪贴板中,快捷键为 Ctrl+X
复制 将选中的对象复制到剪贴板中,快捷键为 Ctrl+C
粘贴 将剪贴板中的内容粘贴到当前位置处,快捷键为 Ctrl+V
它在“代码”窗口打开时才有效,单击它可调出“查找”对话框,利用该对
查找
话框可查找字符,其快捷键为 Ctrl+F
撤消 撤消刚刚完成的操作,快捷键为 Ctrl+Z
重复 重新进行刚刚被撤消的操作
启动 开始运行当前的工程,快捷键为 F5
中断 暂时中断当前工程的运行,快捷键为 Ctrl+Break
结束 结束当前工程的运行
续表
图 标 名 称 作 用
属性窗口 打开“属性”窗口,快捷键为 F4
窗体布局窗口 打开“窗口布局”窗口
对象浏览器 打开“对象浏览器”对话框,快捷键为 F2
工具箱 打开“工具箱”窗口
数据视图窗口 打开“数据视图”窗口
名称为数字显示区,用来显示当前对象的位置与大小,左边的数字是对象的
坐标位置(窗体工作区左上角的坐标为(0,0));右边的数字是对象的大小,
即对象的高度和宽度,单位为像素
当鼠标指针移到工具按钮的上边并停留一些时间后,会显示出该按钮的名称。工具按钮
都有对应的菜单命令,也就是说,单击标准工具栏中的某一个按钮,即可产生与单击相应的
菜单命令完全一样的效果。
中文 Visual Basic 6.0 还有其他的工具栏,如编辑工具栏和调试工具栏等。单击“视图”→
“工具栏”菜单下的菜单命令,即可显示或隐藏相应的工具栏。例如,单击“视图”→“工具
栏”→“编辑”菜单命令,即可显示或隐藏编辑工具栏。
4.工具箱
工具箱如图 1-1-3 所示。在选择“新建工程”对话框中的“标准.EXE”项目类型后,在调
出的 Visual Basic 集成开发环境窗口中,工具箱内有默认的 21 个工具按钮,即 20 个控件制作
工具和一个指针工具。利用这些控件制作工具,用户可以在窗体上设计各种控件。这 20 个控
件称为标准控件,指针不是控件,它仅用于移动窗体和控件,以及调整它们的大小。用户还可
通过执行“工程”→“部件”菜单命令,将系统提供的其他标准控件工具装入工具箱中。
图 1-1-3 工具箱
在设计状态时,工具箱总是出现的。在运行状态下,工具箱会自动隐藏。将鼠标指针移
6 中文 Visual Basic 6.0 实用教程—结构化程序设计
(1)工程文件:它存储了与该工程有关的所有文件和对象的清单,这些文件和对象自动
链接到工程文件上,每次保存工程时,其相关文件信息也随之更新。当然,某个工程下的对
象和文件也可供其他工程共享使用。在工程的所有对象和文件被汇集在一起并完成编码以后,
就可以编译工程,生成可执行文件。
(2)窗体文件:它存储了窗体上使用的所有控件对象、对象的属性、对象相应的事件过
程及程序代码。一个应用程序至少包含一个窗体文件。
(3)标准模块文件:它存储了所有模块级变量和用户自定义的通用过程。通用过程是指
可以被应用程序各处调用的过程。
(4)类模块文件:用来建立用户自己的对象。类模块包含用户对象的属性及方法,但不
包含事件代码。
工程资源管理器是以树型结构图的方式对资源进行管理,类似于 Windows 资源管理器。
工程资源管理器的标题栏中显示的是工程的名称,标题栏下面的 3 个按钮,从左到右分别是
“查看代码”按钮、“查看对象”按钮和“切换文件夹”按钮。单击“查看代码”按钮可调出
“代码”窗口,用来显示和编辑代码;单击“查看对象”按钮可切换到模块的对象窗口;单击
“切换文件夹”按钮可决定工程中的列表项是否以目录的形式显示。
6.“属性”窗口
“属性”窗口用于设置和描述对象属性,如图 1-1-6 所示。在“属性”窗口中,标题栏内
显示的是当前对象的名称。标题栏下边是“对象”下拉列表框,用户可以在其中选择所需的
对象名称,“属性”窗口会随着选择对象的不同而变化。“对象”下拉列表框的下面是两个排
序选项卡,用来切换“属性”窗口的显示方式。在“属性”列表框中,列出了对象的属性名
称(左边)和属性值(右边),用户可以通过改变右边的取值来改变对象属性值。最下边是属
第1章 结构化程序设计概述 7
性含义提示信息显示框,如果对属性不熟悉,可以参考属性含义提示信息显示框内显示的属
性含义解释。
“属性”窗口有两种显示方式,一种是按照字母排序,各属性名称按照字母的先后顺序
排列显示;另一种是按照分类排序,即按照“外观”、“位置” 、“行为”等分类对各属性进行
排序显示。
打开“属性”窗口的方法通常有以下 3 种:
① 单击“视图”→“属性窗口”菜单命令;
② 单击标准工具栏中的“属性窗口”按钮 ;
③ 将鼠标指针移到相应的对象上,单击鼠标右键,调出它的快捷菜单,然后单击该快
捷菜单中的“属性窗口”菜单命令。
7.“窗体布局”窗口
“窗体布局”窗口的外观如图 1-1-7 所示,它用于设计应用程序运行时各个窗体在屏幕上
的位置。在“窗体布局”窗口中有一个计算机屏幕,屏幕中有一个窗体 Form1。用鼠标将 Form1
拖曳到适合的位置,程序运行后,Forml 将出现在屏幕中对应“窗体布局”窗口的位置。
单击“视图”→“窗口布局”菜单命令可调出“窗体布局”窗口。
8.“窗体”窗口
“窗体”窗口如图 1-1-2 中间部分所示。
“窗体”窗口具有标准窗口的一切功能,可被
移动、改变大小及缩小成图标。“窗体”窗口
的标题栏中显示的是窗体隶属的工程名称和
窗体名称。单击“工具”→“选项”菜单命
令,可调出“选项”对话框,单击该对话框中
的“通用”选项卡,如图 1-1-8 所示。在“通
用”选项卡中的“宽度”和“高度”文本框内
键入数字,可以调整窗体内网格点的间距大
小。选中“显示网格”复选框,则窗体内显示
网格,否则不显示网格。选中“对齐控件到网
图 1-1-8 “选项”对话框的“通用”选项卡
8 中文 Visual Basic 6.0 实用教程—结构化程序设计
格”复选框,则移动控件时,控件会自动定位到离其最近的网格上。
每个“窗体”窗口必须有一个惟一的窗体名字,建立窗体时默认的名字是 Form1、
Form2……在设计状态下,窗体是可见的。一个应用程序至少有一个“窗体”窗口,用户可
在应用程序中拥有多个“窗体”窗口。除了一般窗体外,还有一种 MDI(Multiple Document
Interface)多文档窗体,它可以包含子窗体,每个子窗体都是独立的。
9.“代码”窗口
“代码”窗口也叫代码编辑器,它是专门用来进行程序设计的窗口,可在其中显示和编
辑程序代码。单击“视图”→“代码窗口”菜单命令,调出“代码”窗口,如图 1-1-9 所示。
图 1-1-9 “代码”窗口
“代码”窗口标题栏下面有两个下拉列表框,左边是“对象”下拉列表框,可以选择窗
体内不同的对象名称;右边是“过程”下拉列表框,可以选择不同的事件过程名称(也叫事
件名称),还可以选择用户自定义过程名称。用户可以打开多个代码窗口,查看不同窗体中的
代码,并可以在各个“代码”窗口之间复制代码。
在选择了对象名称和事件名称后,Visual Basic 会自动将过程头和过程尾显示出来,用户
只需在过程头和过程尾之间输入程序代码即可。
10.快捷菜单
将鼠标指针移到菜单栏、工具栏、工具箱、窗体、窗口、对象或选中代码等之上,单击
鼠标右键,即可调出相应的快捷菜单。快捷菜单中集中了与鼠标右键单击的对象相关的菜单
命令,利用这些菜单命令可以方便地进行有关操作。例如:将鼠标指针移到窗体上,单击鼠
标右键,调出的快捷菜单如图 1-1-10 所示。将鼠标指针移到“代码”窗口的程序编辑区内,
单击鼠标右键,调出的快捷菜单如图 1-1-11 所示。
1.2.1 代码编辑器
图 1-2-1 自动显示该对象的全部属性和方法的列表
4.自动显示语句或函数的语法帮助信息
在输入一个正确的 Visual Basic 语句或函数名后,系统会自动将该语句或函数的语法显
示在语句或函数名的下边,并用黑体字显示出第 1 个参数名,如图 1-2-2 所示。在输入完第
一个参数后,第 2 个参数又会用黑体字显示,以后依次进行下去,直到整个语句或函数输入
完毕。当一些参数是系统提供的时候,则会以列表形式显示出来,供用户选择。
图 1-2-2 自动显示语句或函数的语法帮助信息
1.2.2 获取帮助
在编写程序中,有时会遇到一些疑问,例如:某个控件的使用方法,某个方法、事件或
者函数的用途与应用方法等。为了解决这类疑问,Microsoft 公司提供了 MSDN(Microsoft
Developer Network),MSDN 有上千兆字节的内容,是 Microsoft 公司为开发人员提供所需的
工具、技术、培训、信息、事件、示例代码、技术文章和其他一些技术资料。
如果用户使用的是 Visual Studio 6.0 中的 Visual Basic 6.0,则在 Visual Studio 6.0 套装中
已经包含了 MSDN。此外,还可以从 http://www.microsoft.com/msdn/网址获取 MSDN。
在安装完 Visual Studio 6.0 或 Visual Basic 6.0 中文版后,系统会提示安装 MSDN,MSDN
的安装方法比较简单,这里不再详述。
安装好 MSDN 后,单击“开始”→“所有程序”→Microsoft Developer Network→MSDN
Library Visual Studio 6.0 菜单命令,即可启动 MSDN Library Visual Studio 6.0,如图 1-2-3 所
示。单击窗口中的“Visual Basic”链接文字,即可进入到 Visual Basic 的帮助窗口。
第1章 结构化程序设计概述 11
另外,更常用的方法是在编程时通过联机帮助来使用 MSDN。要获取控件的联机帮助,
可在窗体中选取相应控件,再按 F1 键;要获取方法、函数或事件的相关帮助,则在“代码”
窗口中选中方法、函数或事件的关键字(见图 1-2-4 左图),再按 F1 键。此时,系统会自动
查找并打开相关信息,如图 1-2-4 右图所示。
图 1-2-4 通过联机帮助获取信息
1.2.3 项目实现
1.设计程序的界面
(1)双击 Windows 桌面上的 Windows Visual Basic 6.0 中文版图标
,启动中文 Visual
Basic 6.0,进入中文 Visual Basic 6.0 的集成开发环境窗口,如图 1-1-2 所示。
(2)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。
(3)单击工具箱中的 Pointer(指针)按钮 ,再单击工具箱中的 CommandButton(命令
按钮)按钮 ,然后在“Form1”窗体中拖曳鼠标,制作一个按钮,如图 1-2-6 所示。
2.设置对象的属性
(1)如果没有选中“Form1”窗体中的“Command1”按钮,可单击工具箱中的指针按
钮 ,再单击“Command1”按钮将其选中。
(2)在“属性”窗口中,单击“属性”列表框中的 Caption 属性值文本框,输入“显示
学习 VB 信息”文字,如图 1-2-7 所示。此时会看到“Form1”窗体中的“Command1”按钮
变成了“显示学习 VB 信息”按钮。Caption 属性是对象的标题属性,改变它的值可以改变对
象的标题显示,对于按钮对象,可以改变按钮上的文字。
(3)在“Command1”按钮的“属性”窗口中还有一个“名称”属性, “名称”属性的值
是对象的名字,它用于程序中指示相应的对象。按钮对象“名称”属性的默认值是“Command”
加一个数字序号,第 1 个按钮“名称”属性的默认值是“Command1”,如图 1-2-6 所示。以
后再创建的第 2 个按钮的“名称”属性默认值是“Command2”,依此类推。此处按钮对象
的名字采用其默认值。
“名称”属性的值由一些字符组成,可以修改,字符可以是数字、字母、带下划线的字符
和汉字,但第一个字符必须是字母或汉字,不能有标点符号和空格,最多不能超过 40 个字符。
(4)单击工具箱中的指针按钮 ,再单击窗体。在窗体的“属性”窗口中,可以看到它
的“名称”属性的默认值是“Form1”,窗体的“名称”属性值也可以修改,但不可以有两
个窗体使用相同的名字。窗体对象“名称”属性的默认值是“Form”加一个数字序号,第 1
个窗体“名称”属性的默认值是“Form1”,第 2 个窗体“名称”属性的默认值是“Form2”,
依此类推。此处窗体对象的名字采用其默认值。
3.输入代码程序
(1)将鼠标指针移到窗体内,单击鼠标右键,弹出它的快捷菜单,单击该菜单中的“查
看代码”菜单命令,调出相应的“代码”窗口,如图 1-2-8 所示。
(2)在“代码”窗口内的“对象”下拉列表框中,选择“Form”对象名称,此时的“代
第1章 结构化程序设计概述 13
码”窗口内会自动生成一个空的事件过程,它只有两行代码(过程头代码和过程尾代码),如
图 1-2-9 所示。
第一行语句(即过程头)是过程声明语句,第二行语句(过程尾代码)是过程结束语句。
过程声明语句中,Sub 是关键字,表示过程的开始。Form_Load( )是过程名字,过程名字由两
部分组成,并遵循如下规则:
第一部分是事件所针对的对象的“名称”属性的值,对于“窗体”对象,这部分均为“Form” 。
第二部分是事件的名字,在本例中的 Load( )是“加载过程”事件的名字,Load 事件的作用
是当 Visual Basic 加载窗体对象或调用窗体对象时,先把窗体属性设置为初始值,再执行
Load 事件过程。过程名字的两部分之间必须用下划线“_”连接。
(3)在“过程”下拉列表框中选择“Activate”事件,此时的“代码”窗口如图 1-2-10
所示。其中,Activate 事件是当一个对象(此处是窗体)为活动窗体(窗体可见)时,才执
行 Activate 事件过程。运行该窗体程序后,可使窗体成为活动窗体。
(4)用鼠标拖曳选中 Load 事件过程的过程头和过程尾代码,然后按 Backpace 删除键,
将选中的代码删除。
(5)单击 Activate 事件过程的过程头代码和过程尾代码之间的空行,使光标出现,然后
输入:“Print "跟我学 Visual Basic 程序设计语言"”代码,如图 1-2-11 所示。
(6)双击窗体中的“显示信息”按钮,“代码”窗口中会增加 Command1_Click()事件过
程的过程头代码和过程尾代码。其中,Command1 是按钮的名称,Click 是按钮的默认事件(鼠
标单击按钮事件)。然后输入:“Print"欢迎进入中文 Visual Basic 6.0 世界!"”代码。按回车
键,输入“Print"只要努力,您会很快学会!"”代码。再按回车键,输入“Form1.Caption = "
跟我学 VB 程序设计语言"”代码。最后,按回车键,输入“Command1.Caption = "显示学习
VB 信息完毕!"”代码。注意:此处的“=”是赋值号,而不是等号,它表示将赋值号右边
字符串赋给左边的变量,而并不表示“=”号两边相等。Print 命令用来显示该命令右边字符
14 中文 Visual Basic 6.0 实用教程—结构化程序设计
1.2.4 项目拓展
1.保存程序
(1)单击“文件”→“保存工程”菜单命令,可调出“文件另存为”对话框,如图 1-2-14
所示。选择文件夹,输入文件名称,单击“保存”按钮,将窗体文件保存(扩展名为.frm),
然后调出“工程另存为”对话框,如图 1-2-15 所示。在“文件名”文本框中输入文件名称,
然后单击“保存”按钮,即可将工程文件(扩展名为.vbp)保存。
(2)如果在修改程序后,再保存文件,可以单击“文件”→“保存工程”菜单命令。如
果要将文件以其他名字保存,可单击“文件”→“工程另存为”菜单命令。
2.运行程序和生成可执行文件
(1)运行程序:运行程序有如下 3 种方法。
方法一:单击“运行”→“启动”菜单命令。
方法二:单击标准工具栏内的“启动” 按钮。
方法三:按 F5 键。
运行程序后,即可在屏幕中显示图 1-2-5 左图所示的画面;再单击窗体中的“确定”按
钮,即可显示图 1-2-5 右图所示的画面。然后,单击标准工具栏内的“结束”按钮 ,或者
单击窗体窗口右上角的“关闭”按钮,即可回到程序编辑状态。
(2)生成 EXE 文件:在保存文件后,单击“文件”→“生成工程 1.exe”菜单命令,调
出“生成工程”对话框。再输入文件名称,单击“确定”按钮,即可生成扩展名为“.exe”
的可执行文件。
3.使用 Visual Basic 开发应用程序的步骤
使用 Visual Basic 编程,一般先设计应用程序的外观,然后分别编写各对象事件的程序
代码或其他处理程序。这样,编写程序的工作会轻松得多。使用 Visual Basic 开发应用程序
通常采用下述步骤。
(1)创建应用程序界面:界面是用户和程序交互的桥梁,用 Visual Basic 创建标准的
Windows 应用程序界面一般由窗体、文本框、按钮、菜单和图像框等构成。在设计应用程序
时,首先应根据程序的功能要求和用户与程序之间的信息交流的需要,来确定需要哪些对象
规划界面的布局,创建应用程序的界面。
(2)设置界面上各个对象的属性:根据规划的界面要求设置各个对象的属性,例如对象
的外貌、名称、颜色和大小等。大多数属性取值既可以在设计时通过“属性”窗口来设置,
也可以在程序代码中通过编程在程序运行时进行属性设置的修改。
(3)编写对象响应事件动作的程序代码:界面仅仅决定程序的外观,设计完界面后就要
通过“代码编辑器”窗口来添加代码,实现一些在接受外界信息后做出的响应、信息处理等
任务,代码编辑窗口如图 1-2-8 所示。
(4)保存工程:一个 Visual Basic 程序就是一个工程。在设计一个应用程序时,系统
建立一个扩展名为“.vbp”的工程文件。工程文件包含该工程所建立的所有文件的相关信
息,保存工程同时保存该工程的所有相关文件。比如,当设计界面时产生的窗体保存在扩
展名为.frm 和.frx 的窗体文件中,在打开一个工程文件时,与该工程有关的所有文件同时
被装载。
(5)运行和调试程序:通过“运行”菜单中的选项来运行程序。当出现错误时,Visual
Basic 系统会显示相应的提示信息,也可通过“调试”和“运行”菜单命令来查找和排除
错误。
(6)生成可执行程序:为了使程序可以脱离 Visual Basic 环境,可单击“文件”→“生
成工程 1.exe”菜单命令,生成可执行程序,此后即可直接执行该文件。在生成可执行程序后,
再通过安装向导,将所有相关文件打包,就可作为一个软件产品在 Windows 环境下安装后独
立运行。
16 中文 Visual Basic 6.0 实用教程—结构化程序设计
1.3 求 10 以内的偶数和
1.3.1 什么是结构化程序设计
选择结构的事件发生后,会出现两种或多种不同的结果,最终是一种什么样的结果,要
根据不同的条件是否成立来决定。例如,公司老总给某个职工下达一天的任务:先打扫办公
室,再到传达室取文件,再看是否下雨,如果不下雨,则采购一台计算机;如果下雨,则在
办公室整理材料;最后都要向公司部门主管汇报一天的工作结果。
在程序设计中,同样存在这种情况。在这种情况下,程序不再按照顺序来执行各语句行
的语句,而是根据给定的条件来决定选取哪条路径,执行哪些语句。选择结构的特点是:根
据所给定选择条件是否为真(即条件成立),而决定从各实际可能的不同操作分支中,选择
执行某一分支的相应操作。例如,对于计算机程序自动依次产生的正整数 1 到 10,判断它是
否是偶数,如果是偶数则累加,如果不是偶数则不累加,最后输出 1 到 10 之间所有偶数的和。
从顺序结构与选择结构的执行过程来看,计算机在执行程序时,顺序结构中所有书写出
来的语句都必然要执行,但选择结构中书写出来的分支语句并不一定都要执行,并且一般情
况下均有“无论分支多少,仅选其一”的特性。
3.循环结构
所谓循环,就是某些事情或某些操作需要重复运作和执行。但如果是无限次的循环,就
会构成死循环。做任何事情都要有个“度”,这个“度”就是循环结束的条件。循环就像我们
游泳一样,游一个来回,再游一个来回,游累了或游够了规定的次数就结束游泳。这里所谓
的游累了或到了规定的次数就是游泳这个重复动作结束的条件。
在编写程序让计算机工作时,常需要在某个条件成立时(或不成立时)反复执行某段
程序或某条语句,直到条件不成立后(或成立后)才停止这种重复工作。这类的程序结构
叫循环结构。例如:求从 1 到 10 正整数之间所有偶数的和。在该问题中,“累加”的过程
就是一个重复执行的动作,从 2 开始累加,一直累加到 10 或一直累加完 10 以内所有偶数
为止。
1.3.2 创建安装程序和安装应用程序
1.创建安装程序
在编写完程序后,常常需要将程序打包,并创建相应的安装程序。使用 Visual Basic 6.0
提供的“打包和展开向导”,可以很容易地为应用程序创建安装程序。在创建安装程序时,系
统将不断显示有关的提示信息,引导用户输入某些信息,从而方便地创建所需要的安装程序。
另外,在创建安装程序时,还可以使用 Visual Basic 6.0 提供的安装工具包,使创建的安装程
序的功能更强大。
(1)启动“打包和展开向导”的方法:启动“打包和展开向导”的方法有以下两种。
方法一:不启动 Visual Basic 6.0 的工作环境。单击 Windows 环境下的“开始”→“所有
程序”→“Microsoft Visual Basic 6.0 中文版”→“Microsoft Visual Basic 6.0 中文版工具”→
“Package & Deployment 向导”菜单命令,调出“打包和展开向导”对话框,如图 1-3-1 所示。
如果没有调出要打包的程序,则应在该对话框的“选择工程”文本框中输入要打包的工程文
件的路径和文件名,也可以单击其右边的“浏览”按钮,调出“打开工程”对话框。利用该
对话框选择要打包的工程文件。
方法二:启动 Visual Basic 6.0 的工作环境。关闭当前编辑的工程,单击“外接程序”→
“外接程序管理器”菜单命令,调出“外接程序管理器”对话框,如图 1-3-2 所示。单击选择
18 中文 Visual Basic 6.0 实用教程—结构化程序设计
“可用外接程序”栏中的“打包和展开向导”选项,单击选中“加载行为”栏中的“在启动中
加载”复选框,然后单击“确定”按钮,将向导添加到 Visual Basic 6.0 的工作环境中。
(6)单击该对话框中的“新建文件夹”按钮,调出“新建文件夹”对话框,如图 1-3-5
所示。在该对话框的文本框中输入文件夹的名称
(例如:我的工程 1),单击“确定”按钮,返回
“打包和展开向导 - 打包文件夹”对话框。
(7)单击“下一步”按钮,完成在硬盘中生成
一个文件夹, 存储所有生成的安装程序部件的任务。
如果丢失了文件,向导还会提示用户。此时会调出 图 1-3-5 “新建文件夹”对话框
“打包和展开向导 - 包含文件”对话框。
(8)在“打包和展开向导 - 包含文件”对话框中选择要打包的文件,然后单击“下一步”
按钮,调出“打包和展开向导 - 压缩文件选项”对话框。利用该对话框来确定安装程序的发
行类型,可以选择生成一个压缩文件或者是生成几个压缩文件。
(9)单击“下一步”按钮,调出“打包和展开向导 - 安装程序标题”对话框,利用该对
话框输入安装程序的标题。
(10)此后,可以为安装包中的文件选择图标,设置启动菜单,选择安装包中文件的安
装位置,选择安装后可以共享的文件等。每完成一项设置就单击一次“下一步”按钮,调出
新的对话框,根据向导的提示,进行新的设置。最后调出“打包和展开向导 - 已完成!”对话
框,利用该对话框输入脚本名称,然后单击“完成”按钮,完成安装程序的创建工作,并保
存创建安装程序的脚本。
此时,安装程序所在的文件夹内的文件如图 1-3-6 所示。
图 1-3-6 安装程序所在的文件夹内的文件
2.安装应用程序
(1)退出 Visual Basic 6.0 程序和其他相关程序。
(2)双击安装程序所在的文件夹内的 Setup 文件,开始安装应用程序。
(3)根据向导的提示信息,进行应用程序保存位置的设置和文件名的输入等操作。每完
成一步设置,就单击一次“下一步”按钮,直到完成所有安装工作。
1.3.3 项目实现
中的 CommandButton 按钮 ,然后在“Form1”窗体中拖曳鼠标,制作一个按钮。
(2)单击选中“Command1”按钮,在其“属性”窗口中,设置 Caption 属性值为“求
10 以内的偶数和”,“名称”属性采用默认值“Command1”。
(3)单击工具箱中的指针按钮 ,再单击窗体。在窗体的“属性”窗口中,设置“名称”
属性的值采用默认值“Form1”,Caption 属性值为“求 10 以内的偶数和”。此时的窗体如
图 1-3-8 所示。
2.输入代码程序
(1)将鼠标指针移到窗体内,单击鼠标右键,弹
出它的快捷菜单,单击该菜单中的“查看代码”菜单
命令,调出相应的“代码”窗口。
(2)双击窗体中的 Command1 按钮, “代码”窗
口中会增加 Command1_Click( )事件过程的过程头和
过程尾代码。然后,按照本章第 2 节所述方法输入如
下程序(程序中的“'”及其右边的文字是语句的注
图 1-3-9 “代码”窗口 释,程序运行时不执行它们),“代码”窗口如图 1-3-9
所示。
Private Sub Command1_Click() '单击“Command1”按钮后产生事件,执行下面的过程程序
M=0 '给变量 M 赋初值 0
For N = 1 To 10 '构成一个循环,可以依次产生 1 到 10 之间的正整数,赋给变量 N
If N Mod 2 = 0 Then '如果变量 N 的值除以 2 的余数为 0,即偶数,则
M=M+N '将变量 N 的值与变量 M 的值相加后,赋给变量 M,即进行累加运算
End If '选择结构结束语句
Next N '与 For 语句一起构成一个循环
Print "10 以内的偶数和等于:"; M'显示“10 以内的偶数和等于:”和变量 M 的值,即累加结果
End Sub
(3)For 语句和 Next 语句,以及其间的语句,构成循环结构程序。执行 For 语句后,变
量 N 的值为 1。执行 Next N 语句后,变量 N 的值自动加 1,变为 2,再返回执行 For 语句下
边的 If 语句。直到变量 N 的值为 11 后执行 Next N 语句下边的语句。
(4)If 语句和 End If 语句,以及其间的语句,构成选择结构程序。Mod 是取余(或模)
运算符,N Mod 2=0 用来判断变量 N 的值除以 2 的余数是否为 0(为 0 时,变量 N 的值为偶
数;不为 0 时,变量 N 的值为奇数) ,如果为 0,则执行其下边的 M=M+N 语句;否则不执
行 M=M+N 语句,执行 End If 语句下边的语句。
(5)M=M+N 语句是累加语句,用来累计变量 N 的多个不同的值,即累加 1 到 10 之间
第1章 结构化程序设计概述 21
所有偶数的值。
(6)Print 语句不但可以显示其右边的字符串内容,还可以显示其右边变量 M 的值。
1.3.4 项目拓展
1.什么是面向对象程序设计
面向对象的程序设计是另一种重要的程序设计方法,它能够有效地改进结构化程序设计
中存在的问题。“对象”是指具有一定结构、属性和功能的“实体”,对象是代码和数据的集
合,采用“对象”和“对象类”,以及对象之间的相互通信的“消息”,描述客观世界中的各
种事物及其相互关系,建立面向“对象”和“消息”的具有层次结构的模型。面向对象的程
序设计是基于上述面向对象模型,采用面向对象的程序设计语言。在现实生活中的实体就是
对象,例如人、汽车、猫、花草、计算机等。对象中还可以包含其他对象,也就是说对象可
以由多个子对象组成,例如,汽车是由车身、4 个车轮等对象组成的;计算机由主机、显示
器、键盘和鼠标等对象组成的。
Visual Basic 应用程序的基本单元就是对象,用 Visual Basic 设计程序就是用对象组装程
序。在 Visual Basic 程序设计中,整个应用程序就是一个对象,应用程序中还包含着窗体
(Form)、命令按钮(CommandButton)、列表框(ListBox)、菜单、应用程序代码和数据库等
对象。例如:上面实例中的窗体(Form1)、命令按钮(Command1)就是实例 1 程序中的两
个对象。对象都具有属性(数据)和方法(作用于对象的操作)。对象将它的属性和方法封装
成一个整体,供程序设计者使用。对象之间的作用通过消息传送来实现,例如,上面实例 1
中的“Form1.Caption = "跟我学 Visual Basic 程序设计语言"”语句就是通过单击按钮对象后,
用字符串“跟我学 Visual Basic 程序设计语言”替换窗体对象的 Caption(标题)属性的值。
在结构化的程序设计中,要解决某一个问题,是将问题进行分解,然后用许多功能不同
的函数来实现,数据与函数是分离的。
面向对象的程序设计方法的思考方式是面向问题结构的,它认为现实世界是由对象组成
的,要解决某个问题,必须要首先确定这个问题是由哪些对象组成的。它是将问题抽象成许
多类,将数据与对数据的操作封装在一起,对象是类的实例,程序是由对象组成的。
对象的属性(Property)是指用于描述对象的名称、位置和大小等特性。例如,汽车这个
对象就有颜色、品牌、型号和生产年份等属性。Visual Basic 中的命令按钮对象就具有名称、
Caption(标题)、Width(宽度)、Height(高度) 、字体(Font)和文字颜色等属性。
可以通过改变对象的属性值来改变对象的属性特性。对象属性的设置可以有两种方法,
一种是使用“属性”窗口修改其属性值来完成,另一种是在程序中使用代码来完成。有些属
性可以使用上述两种方法来设置,而有些属性则必须通过编写的代码在运行程序时完成设置
或使用“属性”窗口来完成设置。可以在运行程序时读取和设置值的属性称为读写属性,只
能读取的属性称为只读属性。
在程序中使用代码进行属性设置的语句格式是:
对象.属性 = 属性值
例如,上面实例 1 中的“Form1.Caption = "跟我学 Visua1 Basic 程序设计语言"”语句,
就是将“跟我学 Visual Basic 程序设计语言”字符串属性值赋给“Forml”窗体对象的 Caption
属性。
22 中文 Visual Basic 6.0 实用教程—结构化程序设计
对象的方法(Method)是改变对象属性的操作,例如,在纸上写文字,改变布的颜色,
将米饭煮熟等。在 Visual Basic 中,方法就是针对对象进行操作的程序和改变对象属性值的
程序。例如:上面实例 1 中,在窗体对象中显示文字就使用了 Print 方法;使用赋值运算符“=”
将字符串“跟我学 Visual Basic 程序设计语言”赋给窗体 Form1 的 Caption 属性这种方法,就
改变了窗体 Form1 的 Caption 属性值。
2.什么是事件驱动程序设计
事件(Event)是指由用户或操作系统引发的动作,是指发生在某一对象上的事情。对于
对象而言,事件就是发生在该对象上的事情。例如,有一个按钮对象,单击按钮就是发生在
这个对象上的一个事件。
事件又可分为鼠标事件及键盘事件等。例如,命令按钮(CommandButton)可以响应鼠
标单击(Click)、鼠标移动(MouseMove)、鼠标抬起(MouseUp)等鼠标事件,又可响应键
盘按下(KeyDown)等键盘事件。窗体也具有响应一些外部事件的能力,例如 Activate 事件、
Load 事件、鼠标单击(Click)事件和鼠标双击(DblClick)事件等。
当在对象上发生了某个事件后,必须想办法处理这个事件,而处理这个事件的步骤就是
事件过程。事件过程是针对事件的,而事件过程中的处理步骤就是所谓的程序代码。换句话
说,程序设计者的主要工作,就是为对象编写事件过程中的程序代码。
在结构化程序设计中,应用程序自身控制了代码的执行顺序,按应用程序中预定的路线
执行。在事件驱动的应用程序中,代码的执行不再是按照预定的路径,而是响应事件时,根
据事件的不同,去执行有关代码段。这些事件的顺序决定了代码执行的顺序,因此,应用程
序每次运行时所经过的代码的路径都是不同的。
程序运行后,它会先等待某个事件的发生,然后再去执行处理此事件的事件过程(这可
以采用结构化程序设计方法设计的程序)。事件过程要经过事件的触发才会被执行,这种动作
模式就称为事件驱动程序设计。也就是说,由事件控制整个程序的执行流程。
1.4 选 择 窗 体
有用户界面。
3.窗体的二进制数据文件
窗体的二进制数据文件含有窗体内控件的二进制属性数据。这些文件是在创建窗体时自
动产生的。
4.标准模块文件
标准模块文件用于存放在几个窗体内都需要使用的公共代码,包含常数、类型、变量声
明、过程声明和过程代码。
单击“工程”→“添加模块”菜单命令,或单击标准工具栏内按钮 的黑色箭头按钮,
调出它的菜单,单击该菜单中的“添加模块”菜单命令,调出如图 1-4-1 所示的对话框。单
击选择“新建”选项卡,单击“打开”按钮,即可调出“工程 1-Module2(Code)”窗口,如
图 1-4-2 所示。利用该窗口可以创建标准模块文件。
5.类模块文件
类模块文件用于创建新对象,这些对象可以包含自定义的属性和方法。类模块既包含代
码又包含数据,可被应用程序内的过程调用。类模块可以视为没有物理表示的控件。
Visual Basic 的文件还包括 ActiveX 控件的文件(.ocx)以及单个资源文件(.res)。使用
Visual Basic 的专业版和企业版,还可创建其他类型的可执行文件。
1.4.2 工程属性的设置和添加工程文件
1.工程属性的设置
单击“工程”→“工程属性”菜单命令,调
出“工程 1 - 工程属性”对话框,如图 1-4-3 所示。
利用该对话框可以设置工程的属性,该对话框中
各选项的作用如下。
① “工程类型”下拉列表框:用来设置工程
的类型,默认为“标准 EXE”选项。
② “启动对象”下拉列表框:用来选择程序
运行时最先启动的窗体,或者选择使用“Sub Main”
选项。
③ “工程名称”文本框:用来输入工程的
名称。 图 1-4-3 “工程 1-工程属性”对话框
24 中文 Visual Basic 6.0 实用教程—结构化程序设计
(2)添加现有工程:单击“文件”→“添加工程”菜单命令,调出“添加工程”对话框,
选中“现存”选项卡,单击选中现有的工程文件,单击“打开”按钮,即可在“工程 - 工程
1”窗口内添加一个现有的工程。注意:打开的工程名称不可以与已有的工程名称相同。
3.在工程中添加文件
(1)在工程中添加窗体:单击“文件”→“工程窗体”菜单命令,调出“添加窗体”对
话框,选中“新建”选项卡,单击选中“窗体”选项,单击“打开”按钮,即可在工程资源
管理器窗口当前工程下添加一个窗体,如图 1-4-4 所示。另外,单击标准工具栏内的“添加
窗体”按钮 ,可以直接在工程资源管理器窗口内添加一个窗体。
(2)在工程中添加其他文件:可以在工程中添加模块、属性页和用户控件等文件,通过
单击选择“工程”菜单的各种添加命令,即可在工程中添加文件。
1.4.3 项目实现
方法如下。
1.将不同工程中的窗体放在同一个工程文件中
将 3 个不同工程(例如:实例 1、实例 2 和实例 3)中的 3 个不同的窗体放置在同一个
工程当中,可以采用如下的方法。
(1)单击“文件”→“打开工程”菜单命令,调出“打开工程”对话框,利用该对话框
打开实例 3 的工程文件。再单击“文件”→“工程另存为”菜单命令,调出“工程另存为”
对话框,将实例 3 的工程文件保存到“实例 2-选择窗体”目录中。
(2)在工程资源管理器(“工程 - 工程 1”窗口)中,双击“Form1(Form1.frm)”图
标,如图 1-4-6 所示。将实例 3 工程文件内的窗体打开,修改窗体属性窗口中“名称”属
性的值为“Form3”,修改 Caption 属性的值为“Form3”。再将程序中的“Form1”改为
“Form3”。
(3)单击“文件”→“Form1.frm 另存为”菜单命令,调出“文件另存为”对话框。将
打开的窗体文件以名称“Form3.frm”另保存到“实例 2-选择窗体”目录中。此时的“工程 -
工程 1”工程资源管理器如图 1-4-7 所示。更改窗体文件名称的目的是,在一个工程文件中不
可以有相同名称的窗体文件。
(4)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。单击该对话框
的“现存”选项卡,选择实例 2 中的窗体文件“Form1.frm”,此时的“添加窗体”对话框如
图 1-4-8 所示。单击“打开”按钮,即可将该窗体文件打开,并加载到当前的工程中。此时
的工程资源管理器(“工程 - 工程 1”窗口)如图 1-4-9 所示。
图 1-4-8 “添加窗体”对话框
26 中文 Visual Basic 6.0 实用教程—结构化程序设计
(5)按照上述第(2)、(3)操作步骤修改和保存窗体文件。此时的工程资源管理器( “工
程 - 工程 1”窗口)如图 1-4-10 所示。注意:要将程序中的“Form1”改为“Form2”。
(6)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。单击该对话框
的“现存”选项卡,选择实例 1 中的窗体文件“Form1.frm”,单击“打开”按钮,即可将该
窗体文件打开,并加载到当前的工程中。此时的“工程-工程 1”工程资源管理器如图 1-4-11
所示。
(7)单击“文件”→“保存工程”菜单命令,将当前工程文件保存到“实例 2-选择窗体”
目录中。至此已将 3 个实例的窗体文件加载到同一个工程文件当中。
(8)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。单击“打开”
按钮,即可在当前工程中创建一个新的窗体,窗体的名称自动设置为“Form4”。此时的工程
资源管理器如图 1-4-12 所示。
StartUpPosition 属性设置为“2-屏幕中间”。
(4)“Label1”标签对象 Caption 属性设置为“选择实例”
;BackColor 属性设置为灰色,
字体属性设置为宋体,大小为小四号,字形为粗体,字体颜色为黑色。
3.输入代码程序和设置启动的窗体文件
(1)双击“Form4”窗体对象,调出“代码”窗口。也可以单击选中“Form4”窗体,再
单击“视图”→“代码窗口”菜单命令,调出“代码”窗口。然后,输入代码程序。
该程序的代码程序如下。
Private Sub Command1_Click()
Form1.Show '显示 Form1 窗体,即使它为活动窗体
End Sub
Private Sub Command2_Click()
Form2.Show '显示 Form2 窗体,即使它为活动窗体
End Sub
Private Sub Command3_Click()
Form3.Show '显示窗体 Form3,即使它为活动窗体
End Sub
Private Sub Command4_Click()
End '退出程序的运行
End Sub
Object.Show 方法用来显示 Object 指定的窗体。Object 是窗体的名称。在该程序中,
“Forml.Show”语句中的“Forml”是 Object 指定的窗体;“Form2.Show”语句中的“Form2”
是 Object 指定的窗体。如果调用 Show 方法时指定的窗体还没有装载,则 Visual Basic 会自动
装载该窗体。
(2)设置启动的窗体文件:单击“工程”→“工程 1 属性”菜单命令,调出“工程 1-工
程属性”对话框的“通用”选项卡。在“启动对象”下拉列表框中选择“Form4”选项,然
后单击“确定”按钮。以后,单击标准工具栏内的“启动”按钮或者按 F5 键,即可运行新
创建的“Form4”窗体程序。
设置启动的窗体文件还可以通过修改工程文件来完成,只要将工程文件中的
“Startup="Form4"”菜单命令中的窗体文件名称进行修改即可。用记事本软件打开该程序的工
程文件后,部分命令如图 1-4-13 所示。
图 1-4-13 用记事本打开程序的工程文件
28 中文 Visual Basic 6.0 实用教程—结构化程序设计
1.4.4 项目拓展
1.删除工程和工程中的文件
(1)删除工程:在工程资源管理器窗口中选择需要删除的工程名,单击“文件”→“删
除工程”菜单命令,即可从工程组中删除选中的工程。
(2)删除工程中的文件:在工程资源管理器中选中要删除的文件(例如窗体文件等),
然后单击“工程”→“移除…”菜单命令,或者鼠标右键单击工程资源管理器窗口内部,调
出它的快捷菜单,单击该菜单中的“移除…”菜单命令。
2.保存工程组和设置启动工程
(1)保存工程组:单击“文件”→“保存工程组”菜单命令,按照提示,分别依次保存
Form1.frm 窗体文件、工程 1.vbp 工程文件、Form1.frm 窗体文件和工程 2.vbp 工程文件,最
后保存工程组的组 1.vbg 文件。
(2)设置启动工程:此时,如果通过单击标准工具栏内的“启动”按钮 或者按 F5 键
运行程序,则只会运行“工程 1”的程序,不会运行新创建的“工程 2”的程序。
如果要运行“工程 2”的程序,可以用鼠标单击选中工程资源管理器(即“工程 - 工程 1”
窗口)内“工程 2(工程 2.vbp)”行。再单击鼠标右键,弹出其快捷菜单,单击该菜单中的
“设置为启动”菜单命令。以后可以通过单击标准工具栏内的“启动”按钮 或按 F5 键来运
行“工程 2”的程序。
3.利用工程和窗体文件创建多窗体的工程
一个工程是各种类型文件的集合,它包括工程文件(Vbp)和窗体文件(Frm)等。工
程文件存储了与该工程有关的所有文件和对象的清单,这些文件和对象自动链接到工程文
件上。窗体文件存储了窗体上使用的所有控件对象、对象的属性、对象相应的事件过程及
程序代码。工程文件和窗体文件实质是文本文件,可以使用 Windows 的记事本软件对它们
进行显示和修改。
利用工程和窗体文件创建多窗体工程的方法如下。
(1)将要加载的窗体文件复制到工程文件所在的文件夹中(例如:“实例 4”文件夹)。
如果要加载的窗体文件名称与工程文件所在的文件夹中的窗体文件有重名的,则在复制前,
必须要对加载的窗体文件名进行修改,例如将“Form1”改为”Form3” 。
(2)用记事本软件打开复制的窗体文件,如果该窗体文件中的窗体名称有与其他窗体文
件(同一工程文件所在的文件夹中)的窗体名称重名的,需要修改窗体文件中的窗体名称(例
如:将“Form1”改为“Form2”)。
( 3 ) 用 记 事 本 软 件 打 开 工 程 文 件 , 在 该 文 件 的 前 面 加 入 “ Form=Form1.frm ”、
“Form=Form2.frm”和“Form=Form3.frm”命令,表示在该工程中加载了名称为“Form1.frm” 、
“Form2.frm”和“Form3.frm”的窗体文件。
思考与练习
1.填空题
(1)中文 Visual Basic 6.0 包括________、________和________3 个版本。
第1章 结构化程序设计概述 29
2.1 输 入 密 码
2.1.1 数据的类型
数据是描述客观事物的数、字符和所有能输入到计算机并被计算机程序处理的符号集
合。在中文 Visual Basic 6.0 中,数据是指常量、变量、字符串和数组等。每一个数据都属于
一种特定的数据类型,不同的数据类型所占的存储空间不一样,表示和处理的方法也不一样,
这就需要进行数据类型的说明或定义。
Visual Basic 的数据类型可分为标准数据类型和用户自定义数据类型两大类。标准数据类型
又称为基本数据类型,它是由 Visual Basic 直接提供给用户的数据类型,用户不用定义就可以直
接使用;用户自定义数据类型是由用户在程序中以标准数据类型为基础,并按照一定的语法规则
创建的数据类型,它必须先定义,然后才能在程序中使用。标准数据类型如表 2-1-1 所示。
表 2-1-1 Visual Basic 的标准数据类型
数 据 类 型 关 键 字 类 型 符 字 节 数 范 围
负数:−3.402823E38 到−1.401298E-45
单精度型 Single ! 4
正数:1.401298E-45 到 3.402823E38
负数约为:−1.8D308 到−4.9D-324
双精度型 Double # 8
正数约为:4.9D-324 到 1.8D308
−922 337 203 685 477.5808
货币型 Currency @ 8
到 922 337 203 685 477.5807
1.数值型数据
在 Visual Basic 程序设计语言中,数值型数据是指能够进行加、减、乘、除、整除、乘
方和取模(Mod)等算术运算的数据,它包括整数类型和实数类型数据。
(1)整数类型:数据类型又分为字节型、整型和长整型 3 种数据类型,它们的运算速度
快、精确,但可表示数的范围小。默认的初值为 0。
字节型(Byte):它除了可以保存数字之外,其最主要的用途是保存声音、图像和动画等
二进制数据,以便与其他 DLL 或 OLEAutomation 对象联系。
整型(Integer):由数字和正负符号组成,不带小数点,正数可以不要正号。可以在数据
后面加尾符“%”来表示整型数据,例如 123、986、37%。
长整型(Long):由数字和正负符号组成,数值中不可以有逗号分割符。可以在数据后
面加尾符“&”表示长整型数据,例如 34732、−75473、36&。
整数类型的数据不但可以用十进制数来描述,而且还可以用十六进制数或八进制数来表
示。用十六进制数表示时,以&H 为引导,其后的数据位数为 1~4 位(整型数据)或 1~6
位(长整型数据),对于长整型数据还要以&结尾,例如&HFFFF、&HAF、&HFFFFFF&、
&H00FF00&等。
用八进制数表示时,以&O 或&为引导,其数据范围为&0~&177777(整型数据)或&0~
&37777777777&(长整型数据),对于长整型数据还要以&结尾,例如&O388888888&、
&O566886873&。
(2)实数类型:实数类型又分为单精度(Single)实型、双精度(Double)实型和货币
(Currency)类型 3 种。对于单精度实型数据和双精度实型数据,在 Visual Basic 中都有两种
表示方法。
定点表示法:它是我们日常生活中普遍采用的计数方法,在这种表示方法中,小数点的
位置是固定的,此种方法书写比较简单,适合表示那些大小比较适中的数。
单精度实型数据最多可表示 7 位有效数字,精确度为 6 位,可在数据后面加感叹号“!” ,
例如:123! 、1234.56。双精度实型数据最多可表示 15 位有效数字,精确度为 14 位,可在数
据的后面加“#”号,例如 3456.78#。
浮点表示法:当一个数特别大或者特别小的时候,如果仍然采用定点表示法,那么数码
就会变得很长,既不便于书写和输入,又很容易出错,这时可以将该数用科学计数法表示,
例如:3.158×10−3 和 86.168×1016。由于在计算机中无法输入上标,所以 Visual Basic 中用一个
大写英文字母(单精度实型数用字母 E,双精度实型数用字母 D)表示底数 10,例如上边的
两个数可表示为 3.158E-2 和 86.168D15。
可见,浮点数由三部分组成:尾数部分、字母 E 或 D、指数部分。尾数部分既可以是
整数,也可以是小数,正号可省略;指数部分是带正负号的不超过 3 位数的整数,正号可
省略。
在这种表示方法中小数点的位置是不固定的,但是在输入时,无论将小数点放在何处,
Visual Basic 都会自动将它转化成尾数的整数部分为 1 位有效数字形式(即小数点在最高有效
位的后面)。这种形式的浮点数叫做规格化的浮点数。
(3)货币类型:它是精确的定点实数类型,用于货币计算。整数部分最多有 15 位,小
第2章 中文 Visual Basic 6.0 编程基础 33
以用 Set 语句指定一个被声明的对象数据,去引用应用程序所识别的任何实际对象。默认的
初值为 Nothing(无指向)。
5.变体型数据
变体型数据是一种特殊的数据,它具有数据处理的智能性,可以根据程序上下文的需要,
自定义为一种相应的数据类型,包括上述的数值型、日期型、对象型和字符型的数据。所有
未定义的变量的缺省数据类型都是变体数据类型。
此外,它还可以包含以下 4 种特殊的数据。
① Empty(空):表示未指定确定的数据。
② Null(无效) :表示数据不合法、未知数据或丢失的数据。
③ Error(出错) :指出过程中出现了一个错误的状态。
④ Nothing(无指向):表示数据还没有指向一个具体对象。
要检测变体型变量中保存的数值究竟是什么类型,可以用 VarType 函数进行检测,它的
预定义常量、返回值与数据类型的关系如表 2-1-2 所示。例如,VarType(123)返回值为 2,
表示为整型;VarType("迎接北京奥运")返回值为 8,表示为字符型。
表 2-1-2 VarType 函数的返回值与数据类型的关系
数 据 类 型 返 回 值 数 据 类 型 返 回 值
空(Empty) 0 字符型(String) 8
整型(Integer) 2 错误(Error) 10
长整型(Long) 3 布尔型(Boolean) 11
单精度型(Single) 4 变体数组(Variant) 12
货币型(Currency) 6 字节型(Byte) 17
6.用户自定义型数据
用户自定义型数据由若干个标准数据类型组成。自定义类型通过 Type 语句来实现。关
于用户自定义数据类型将在以后的章节中详细介绍。
2.1.2 常量
(4)日期常量:它是用两个“#”括起来的日期形式的字符组成,例如#2005-2-23 8:19:26#、
#2/15/2005#、#January1,2005#等。
数值整数大多数是十进制的(基数为 10),但有时也用十六进制数(基数为 16)或八进
制数(基数为 8)。各种数值常量表示和实例如下:
十进制数:例如 689,−689,0,3.1415926。
八进制数:用前缀&O( “O”是英文字母)表示八进制数,例如&O681,−&O7l。
十六进制数:用前缀&H 表示十六进制数,例如&H689,&HABC。
2.符号常量
符号常量是在程序中用符号表示的常量。因为程序中多次使用一些常量,这些常量一般字
符比较长,很难记住,多次重复输入时,即费事又很容易出错。另外,如果某个一般常量在程
序中多次重复出现时,如果要改变此一般常量的值,就需要改动程序中的许多地方,既麻烦又
很容易遗漏。这时可以用一个符号常量来代替永远不变的数值或字符串常量,符号常量可以是
具有一定含义、容易理解和记忆的字符。在程序中,凡出现该常量的地方,都用该符号常量代
替。这样不但易于输入,还便于理解此常量的含义,如要想改变某一常量的值时,也只需改变
程序中声明该符号常量的一条语句就可以了,即方便又不易出错。在代码中使用符号常量可使
程序清楚简洁,增加代码的可读性。符号常量又可分为标准符号常量和自定义符号常量。
在程序中使用自定义的符号常量,应当使用
Const 语句先行说明。Const 语句可以说明数值、日
期时间和字符串常量。程序中不能对符号常量赋以
新值。
(1)标准符号常量:它是 Visual Basic 系统提供
的应用程序和控件的系统定义的常量,它们可与对
象、属性和方法一起在应用程序中使用。可在“对象
浏览器”中查看标准符号常量。单击“视图”→“对
象浏览器”菜单命令,可以调出“对象浏览器”对话
框,如图 2-1-1 所示。 图 2-1-1 “对象浏览器”窗口
【说明】等号(=)右边的表达式可以是数值型、字符串型、布尔型或日期型表达式,甚
至可用先前定义过的常量来定义新常量。但在表达式中不能出现变量和函数运算,也不能出
现用户自定义类型数据。虽然在定义符号常量的表达式中可以出现其他已经定义的符号常量,
但应注意在两个或两个以上的常量之间不能出现循环定义。 用 Const
另外,需要特别指出的是,
语句定义的符号常量,虽然名字与变量名很相似,但它与变量有着本质的区别,不能给已定
义的符号常量再赋值。
符号常量名必须以字母开头,不能包含句号或者类型声明字符,不能超过 255 个字符,
也不能和受到限制的关键字同名,常量名中的字母不区分大小写。
Public 说明的常量可在整个应用程序中使用,Private 说明的常量只在该过程范围内使用。
命令格式中,括号“[]”内的参数表示是可选参数,“|”两边的参数表示任选一个。
【举例】求圆面积的程序如下。
Private Sub Form_Activate( )
Const PI As Single = 3.1415926
Area1 = PI*6*6
Print Area1
End Sub
此程序在窗体的 Activate 事件中首先定义了一个表示圆周率的常量 PI(单精度型)
,再
计算半径为 6 的圆的面积并赋给变量 Area1,然后显示圆面积的值。
2.1.3 变量
.变量是在程序执行过程中其值可以变化的量。在应用程序的执行过程中,常用变量来存
储临时数据。变量的内容因程序的运行而变化。变量具有名字和数据类型。变量有两种类型,
一是属性变量,二是用户自定义变量。针对程序中的每一个对象,系统会自动为它创建一组
相应的属性变量,并为每一个属性变量赋默认值,程序设计人员可直接使用这些属性变量,
给它们赋值。下面介绍用户自定义变量(简称变量)。
1.变量名命名规则
变量名是代表数据的一个名称,通过变量引用它所存储的值。变量的命名必须遵循下列
五条规则。
(1)变量名必须以字母开头,不能以数字或其他字符开头。例如,61csb,$ABC 都是不
合法的。
(2)变量名必须由字母、数字或下划线(_)组成。
(3)变量名不能包含句点(.)、空格或者类型声明字符(%、$、@、#、&、!)。例如,
AB.C、N%M、A B 等都是不合法的。
(4)变量名最长不能超过 255 个字符(对象等名称不可超过 40 个字符),一个汉字相当
于一个字符。
(5)变量名不能和受到限制的关键字同名。例如,Or、Loop、Len、Abs、Mod 等都是关
键字,不能作为变量名。
(6)Visual Basic 系统以第一次定义的名称为准,以后输入的名称自动向首次定义的名称
转换。
第2章 中文 Visual Basic 6.0 编程基础 37
所有过程都起作用,但对其他模块不起作用。
(3)用类型符直接声明变量:用类型符直接声明变量的方法如下。
【格式】变量名+类型符
例如:Dim intsum%,intsum1!语句与声明变量 intsum 和 intsum1 的语句 Dim intsum As
Integer,intsum1 As Single 效果是一样的。n1%声明了一个整型变量,Ln1&声明了一个长整
型变量,n1!声明了一个单精度型变量,Dn1#声明了一个双精度型变量,Cn1@声明了一个
货币型变量,SS1$声明了一个字符型变量。注意:变量名与类型符之间没有空格。类型符
参见表 2-1-1。
4.强制显示声明变量
用 Dim 语句声明变量和用类型符直接声明变量都属于显示声明变量。显示声明变量可以
有效地降低因写错变量名而引起的麻烦。为了避免因写错变量名而引起的麻烦,可以规定,
只要使用一个变量,就必须先进行变量的显示声明;遇到一个未经显式声明的变量名,Visual
Basic 就会自动显示“Variable not defined”警告信息。为此,需要在类模块、窗体模块或标
准模块的通用声明段内加入下面这条语句:
Option Explicit
可以单击“工具”→“选项”命令,调出“选项”对话框,再单击“编辑器”选项卡,
选中“要求变量声明”复选框。这样就会在以后新增的任何新模块中的通用声明段内自动插
入 Option Explicit 语句。但这种方法不会在已经编写的模块中自动插入该语句。
注意:Option Explicit 语句的作用范围仅限于它所在的模块,所以对每个需要强制显式声
明变量的窗体模块、标准模块及类模块,都必须将 Option Explicit 语句放在这些模块的通用
声明段中。加入该语句后,Visual Basic 就能够识别出不认识的变量名,从而显示出警告信息,
提示用户必须先显示声明变量,然后才能在程序中使用该变量。
5.变体型变量
如果在变量声明时没有说明变量的数据类型,则该变量的数据类型将被默认为变体型变
量。变体型变量可以在不同场合代表不同的数据类型,能够存储所有系统已定义的标准类型
的数据,所以变体(Varian)型变量可以使程序设计人员不必在数据类型之间进行转换,Visual
Basic 系统会自动完成各种必要的数据类型转换。
使用变体型变量,对于初学者来说是非常方便的。但是,使用变体型变量也会同时带来
变量占用的存储空间大、应用程序运行速度慢、变量名用错后不易查找等缺点。所以,如果
要想提高应用程序的运行速度,易于查找程序的错误,就要避免使用变体型变量。
2.1.4 函数
1.函数的定义和分类
函数(Function)是一些特殊的语句或程序段,每一种函数都可以进行一种具体的运算。
在程序中,只要给出函数名和相应的参数就可以使用它们,并可得到一个函数值。在 Visual
Basic 中,函数可分为标准函数和用户自定义函数两大类。下面只介绍标准函数。
标准函数也叫内部函数或预定义函数,它是由 Visual Basic 语言直接提供的函数。标准
函数按其功能来划分有输入函数、消息(输出)函数、数学函数、字符串函数、日期和时间
函数、转换函数、判断函数和格式输出函数等。
第2章 中文 Visual Basic 6.0 编程基础 39
2.输入函数
【格式】InputBox [$](提示,[,标题][[默认值][,x 坐标,y 坐标]]
【功能】在应用程序的运行过程中,出现一个“输入”对话框,用来给一变量赋值。
【说明】
① $:有它时,返回的是字符型数据;没有它时,返回的是变体型数据。
② 提示:它是一个字符串,用来提示用户输入什么内容。它可以是汉字,可以显示多
行文字,但必须在每行文字的末尾加回车 Chr(13)和换行 Chr(10)。
③ 标题:它是一个字符串,是“输入”对话框标题栏中的标题。它是可选项,省略此
参数时,则将工程名作为标题。
④ 默认值:为可选项,用来在“输入”对话框的输入文本框中显示一个默认值。
⑤ x 坐标,y 坐标:表示对话框(左上角)在屏幕上出现的位置。如果省略此参数,则
对话出现在屏幕的中央。屏幕左上角为原点。
⑥ 此函数常常出现在赋值号的右边,用来给赋值号左边的变量赋值。
2.1.5 项目实现
1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。然后,
用鼠标双击工具箱中的 CommandButton(命令按钮)按钮 ,在窗体内的下边创建 1 个按
钮控件对象。然后,单击工具箱中的 Pointer(指针)按钮 ,用鼠标拖曳按钮控件对象,将
它移到窗体内的下边。
(2)单击工具箱中的 Pointer(指针)按钮 ,单击选中窗体内部,在其“属性”窗口内
的 Caption 属性值文本框中输入“输入密码”文字,保留“名称”文本框中的默认名称“Form1”
。
单击选中窗体内的按钮,在“属性”窗口内的 Caption 属性值文本框中输入“请输入密码”
文字,保留“名称”文本框中的默认名称“Command1”。
(3)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在窗体的上边创
建一个标签对象。单击工具箱中的 Pointer (指针)按钮 ,单击选中新创建的标签对象,
在“属性”窗口内的 Caption 属性值文本框中输入“输入密码” ,保留“名称”文本框中的默
40 中文 Visual Basic 6.0 实用教程—结构化程序设计
认名称“Label1”。
(4)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在按钮的上边创
建另一个标签对象。单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的标签对象,
在其“属性”窗口中,删除 Caption 属性值文本框中的“Label1”字符,保留“名称”文本框
中的默认名称“Label2”。
(5)单击标签对象“属性”窗口内的“Font”属性栏右边的按钮 ,调出“字体”对话
框,按照图 2-1-5 所示进行设置,即设置标签对象中显示文字的字体。单击“确定”按钮退
出该对话框,完成标签字体的设置。
(6)单击标签对象“属性”窗口内的“ForeColer”属性栏右边的按钮 ,调出调色板,
如图 2-1-6 所示。单击该调色板中的蓝色色块,为标签文字选中红色。
(7)按照上述方法,设置另一个标签对象“Label2”具有相同的字体和颜色。再设置按
钮的字体和文字颜色属性,设置的方法与标签对象字体和文字颜色的设置方法一样。
2.输入代码程序
在“代码”窗口中输入的代码程序如下。程序中用到了选择结构的语句,它的详细内容
将在下一章介绍。
Dim MM As Long '定义一个长整型变量 MM
Const MMC As Long = 19471107 '定义一个长整型常量 MMC
Rem ********* 单击“Command1”(标题为“请输入密码” )按钮输入密码 **********
Private Sub Command1_Click ( )
Dim TS$ '定义一个字符型变量 TS$
TS$ = "请您输入密码!" + Chr(13) + Chr(10) + "密码是:"
MM = Val(InputBox(TS$, "请您输入密码", 0, 5000, 1600)) '将输入的密码赋给变量 MM
Rem 选择结构:判断变量 MM 与 MMC 是否相等,如果相等,则将“密码正确!”文字赋给标签 Label2
的 Caption 属性;如果不相等,则将“密码不正确! ”文字赋给标签 Label2 的 Caption 属性
If MM = MMC Then '判断变量 MM 与 MMC 是否相等
Label2.Caption="密码正确!" '如果相等,则执行该语句
Else
Label2.Caption="密码不正确!" '如果不相等,则执行该语句
End If
End Sub
第2章 中文 Visual Basic 6.0 编程基础 41
2.1.6 项目拓展——输出“消息”对话框
1.消息函数
【 格 式 】 MsgBox(提示[,按钮值][,标题])
【 功 能 】 出现一个“消息”对话框,在此“消息”对话框中显示提示信息,等待用户单
击按钮,并返回一个整型数值,告诉应用程序用户单击的是哪一个按钮。
【说明】
① 提示:它是一个字符串表达式,表示显示在对话框中的提示信息。它可以是汉字,
可以显示多行提示文字。
② 标题:它是一个字符串表达式,是“消息”对话框标题栏中的标题文字。省略此参
数时,则将工程名作为标题。它是一个可选项。
③ 按钮值:它是可选项,是一个数值型表达式,表示在对话框中显示的按钮的数目、
形式、图标样式和缺省按钮以及等待模式等信息,如表 2-1-3 所示,在此表的每组值中取一
个数字相加,即可生成此参数值。如果省略此参数,则默认为 0。
例如:如果“消息”对话框内显示“是(Y)”、“否(N)”和“取消”按钮,同时显
示“!”图标,则按钮参数的取值应为 3+48=51;如果“消息”对话框内显示“重试(R)”
和“取消”按钮,同时显示“?”图标,则按钮参数的取值应为 5+32=37。
表 2-1-3 按钮参数的取值及其含义
类 型 按 钮 值 解 释
0 在“消息”对话框中显示“确定”按钮
1 在“消息”对话框中显示“确定”和“取消”按钮
2 在“消息”对话框中显示“终止(A)”、重试(R)”和“忽略(I)”按钮
按钮
3 在“消息”对话框中显示“是(Y)”、“否(N)”和“取消”按钮
4 在“消息”对话框中显示“是(Y)”和“否(N)”按钮
5 在“消息”对话框中显示“重试(R)”和“取消”按钮
16 在“消息”对话框中显示“X”图标
32 在“消息”对话框中显示“?”图标
图标
48 在“消息”对话框中显示“!”图标
64 在“消息”对话框中显示“I”图标
0 在“消息”对话框中第 1 个按钮是缺省值
0 应用程序暂停运行,直到用户对“消息”对话框做出响应才继续执行下面的程序
等待模式
4096 全部应用程序都被挂起,直到用户对消息框做出响应才执行下面程序
表 2-1-4 消息函数的函数值及其含义
函 数 值 含 义 函 数 值 含 义 函 数 值 含 义 函 数 值 含 义
2.利用消息函数输出“消息”对话框
在窗体的 Activate( )事件中,输入下面的程序。然后运
行该程序,此时屏幕显示如图 2-1-7 所示的“消息”对话框。
该“消息”对话框中的提示信息是“确定是否继续运行程
序?”,标题栏内的标题是“确定是否继续”,有“是(Y)” 、
“否(N)”和“取消”3 个按钮。
图 2-1-7 “消息”对话框 单击“是(Y)”按钮或按回车键,即可关闭“消息”对
话框,同时将按钮值赋给变量 N1;再执行 Print N1 语句,即可在窗体中显示按钮值 6。单击
“否(N)”按钮,则显示的按钮值为 7。单击”取消”按钮,则显示的按钮值为 2。
Private Sub Form_Activate( )
Dim N1 As Integer
N1 = MsgBox("确定是否继续运行程序?", 51, "确定是否继续")
Print N1
End Sub
2.2 计算圆周长、面积和球体积
2.2.1 代码的书写规则
1.语句书写规则
(1)在一行中可以书写多条语句,各条语句之间必须用冒号“:”分隔。
(2)一行语句可分多行书写,在续行的前一行末尾应加入一个空格和一个下划线。
(3)一行语句允许最多 255 个字符。
2.注释方法
注释语句用来进行程序的说明,该语句在程序运行中是不执行的,在代码编辑器中它的
现实颜色为浅绿色。注释语句有以下两种:
(1)以命令 Rem 开头,其后跟着说明的文字;
(2)以撇号“'”开头,其后跟着说明的文字,它可以直接放在一条语句的后边。
2.2.2 表达式
1.算术表达式
算术表达式也叫数值表达式,它是用算术运算符和圆括号将数值型的常量、变量和函数
连接起来的有意义的式子,算术表达式的运算结果为数值型。
(1)算术运算符:Visual Basic 中的算术运算符有以下 8 种:
^(乘方)、−(减)、+(加)、*(乘) 、/(除)、\(整除)、Mod(取模)和-(负号)
Mod 是取模(或取余)运算符,其值为两数四舍五入之后相除所得的余数,其值为整型
数数值。“\”是整除运算符,其值为两数四舍五入之后相除所得商的整数部分。例如,
23.5\5.9=4,19.2\1.8=9,26.6 Mod 5.9=3,19.2 Mod 1.8=1。
(2)日期型数据减法:在减法运算中,如果两个数据均为日期(Date)型数据,则运算
结果为双精度(Double)型数据,表示两个日期之间的间隔
天数。
另外,将一个 Date 型数据加减任何能够转化成 Date 型的
其他类型的数据,其结果仍为 Date 型,表示一个日期经过一
定天数之后或之前的日期和时间。例如,下面程序的执行结果
如图 2-2-1 所示。程序中的 CDate 是转换函数,可以将括号内
图 2-2-1 程序运行结果
的字符串转换为日期型数据;Date 函数可以获得当前日期。
Private Sub Form_Activate( )
Print CDate("2005-3-20") - CDate("2003-8-10") '语句执行后显示 588
Print CDate("2005-3-20 12:00:00") - CDate("2003-8-10") '语句执行后显示 588.5
Print Date - 8.5 '当前日期是 2005 年 2 月 10 日,语句执行后显示 2005-2-1 12:00:00
Print CDate("2005-3-10") + 10 '语句执行后显示 2005-3-20
End Sub
(3)表达式的书写规则:Visual Basic 中的算术表达式就相当于数学中的代数式,但与数
学中代数式的书写方法不同。
① 表达式中,所有字符都必须写在同一行上。另外,要注意各种运算符的运算次序,
可以通过加圆括号“( )”来调整运算次序。
② 代数式中省略的乘号,在书写成 Visual Basic 表达式时必须补上。例如,代数式 6X+A
写成 Visual Basic 表达式时应改为 6*X+A。
③ 代数式中的分式,写成 Visual Basic 表达式时,要改成除式,并且不能改变原代数
式的运算顺序,必要时应加上括号。例如,代数式(X+9)÷Y 写成 Visual Basic 表达式时,
应写成(X+9)/Y。
④ 所有的括号,包括大括号和方括号,都必须用圆括号“( )”代替,圆括号必须成对出
现,并且可嵌套使用。
⑤ 要把数学代数式中 Visual Basic 不能表示的符号用 Visual Basic 可以表示的符号代替。
(4)算术表达式的运算顺序:在一个表达式中可以出现多个运算符,因此必须确定这些
运算符的运算顺序,如果运算顺序不同,所得的结果也就不同。
算术运算符的运算顺序如下:( )(圆括号)→ −(负号)→ ^(乘方)→ *(乘) 、/(除)→
\(整除)→ MOD(取模)→ +(加)、−(减)。
同级运算自左至右顺序进行。
44 中文 Visual Basic 6.0 实用教程—结构化程序设计
(5)不同类型数据的混合运算:在一个算术表达式中,如果包含各种不同类型的数值型
数据,则它们运算结果的数据类型遵从下述规定。
① 相同类型数据的运算,其运算结果的数据类型不变。但应注意运算结果不能超过该
类型数据所表示的数值范围,否则将出现“溢出”错误信息。
② 不同类型数据的运算,其运算结果与表示数据最精确的数据类型相同。在加减法运
算中,精确度由低到高的顺序为:
Byte→Integer→Long→Single→Double→Currency
在乘除法运算中,其精确度与加减法的精确度顺序略有不同:在乘除法运算中 Double
型数据的精确度高于 Currency 型数据的精确度。整型数据和长整型数据在一起运算后的结果
为长整型数据,单精度型数据和双精度型数据在一起运算后的结果为双精度型数据,长整型
和单精度型数据运算后的结果为单精度型数据。
如运算结果的数据类型是变体(Variant)型数据,但超过本身原数据类型所能表示的数
据范围时,则自动转换成可以表示更大数据范围的数据类型。例如,参加运算的变体型数据
原来是整型数据,运算结果超出了整型数据的数据范围时,则转换成长整型数据。
除此之外,也有一些例外情况。例如,在加法和乘法运算中,一个单精度型数据和一个
长整型数据相加或相乘,其结果不是单精度型数据,而是双精度型数据等。因此,应多加注
意,并不断总结。
2.字符串表达式
(1)字符串运算符:字符串运算符有两个,一个是“+”运算符,另一个是“&”运算符,
它们都是字符串连接运算符。在字符串变量后边使用“&”运算符时,变量与“&”运算符
之间应加一个空格,以避免 Visual Basic 系统认为是长整型变量。
(2)字符串表达式:字符串表达式是用字符串运算符和圆括号将字符常量、变量和函数
连接起来的有意义的式子,它的运算结果仍为字符串。
【格式】<参数 1> &|+ <参数 2>
【功能】将字符串 1 和字符串 2 连接起来,组成一个新的字符串。“+”运算符与“&”运
算符有如下差别。
“+”运算符:运算符两边的参数必须是字符串型数据或字符串型表达式,如果一个为字
符串型数据,另一个为数值型数据,则会产生错误。
“&”运算符:运算符两边的参数可以是字符型数据,也可以是数值型数据,进行数据连
接以前,先将它们转换为字符型数据,然后再连接。
【说明】字符串表达式的书写规则与算术表达式的书写规则完全相同。例如,"2008 年" &
"奥运"="2008 年奥运","北京" & 2008="北京 2008","北京"+"2008 年奥运"="北京 2008
年奥运"。
3.关系表达式
(1)关系运算符:关系运算符又称比较运算符,是进行比较运算所使用的运算符,包括>
(大于)、<(小于)、=(等于)、>=(大于等于) 、<=(小于等于)和<>(不等于)6 种。其
中>、<和=运算符与数学上的相应运算符写法完全一样,另外 3 种运算符与数学上的相应
运算符写法虽不完全一样,但其含义是完全一样的。
(2)关系表达式:用关系运算符和圆括号将两个相同类型的表达式连接起来的式子。
第2章 中文 Visual Basic 6.0 编程基础 45
② Not(逻辑非):将原逻辑数值取反。
③ And(逻辑与):两个数值均为 True 时,计算结果才为 True。
④ Or(逻辑或):两个数值中只要有一个为 True,则计算结果为 True。
⑤ Xor(逻辑异或):两个数值相同时,计算结果为 False,否则为 True。
⑥ Eqv(等价):两个数值相同时,计算结果为 True,否则为 False。
⑦ Imp(蕴含):左边的数为 True,右边的数为 False 时,计算结果为 False;其余情况,
计算结果为 True。
⑧ 逻辑运算符的运算次序如下。
Not(非)→And(与)→Or(或)→Xor(异或)→Eqv(等价)→Imp(蕴含)
46 中文 Visual Basic 6.0 实用教程—结构化程序设计
例如:
Dim A,B,C,D,E,F,G,H,I
A=16:B=9:C=8
D=A>B And B>C:E=B>A And B>C:F=A>B Or B>C:G=B>A Or C>B
H=A>B Xor B>C:I=B>A Xor B>C
其中, 变量 D 的值为 True,变量 E 的值为 False,变量 F 的值为 True,变量 G 的值为 False,
变量 H 的值为 True,变量 I 的值为 False。
2.2.3 项目实现
1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。在窗体
内的下边创建 5 个按钮控件对象。
(2)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在按钮的上边的
左边创建一个标签对象。单击工具箱中的 Pointer(指针)按钮 ,选中新创建的标签对象,
在其“属性”窗口中,删除 Caption 属性值文本框中的“Label1”字符,保留“名称”文本框
中的默认名称“Label1”。
(3)单击标签对象“属性”窗口内的“Font”属性栏右边的按钮 ,调出“字体”对话
框,如图 2-1-5 所示。利用该对话框设置标签对象中显示文字字体为三号字、宋体、加粗。
单击“确定”按钮退出该对话框,完成标签字体的设置。
第2章 中文 Visual Basic 6.0 编程基础 47
(4)单击标签对象“属性”窗口内的“ForeColer”属性栏右边的按钮 ,调出调色板,
如图 2-1-6 所示。单击该调色板中的蓝色色块,为标签文字选中蓝色。
(5)单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的标签对象,单击标准工
具栏中的“复制”按钮 ,将选中的标签对象复制到剪贴板中。然后,鼠标右键单击窗体,
弹出它的快捷菜单,再单击该菜单中的“粘贴”菜单命令,调出一个“Microsoft Visual Basic”
对话框,单击该对话框中的“否”按钮,即可复制一个标签对象。然后,将该标签对象的文
字颜色改为红色,它的名称为默认值“Label2” 。
(6)再设置窗体和按钮的相关属性,字体和文字颜色的设置方法与标签对象字体和文字
颜色的设置方法一样。此时,程序有多个控件对象:1 个窗体、2 个标签和 5 个按钮,它们的
主要属性设置如表 2-2-2 所示。对象的序号按从上到下、从左到右的顺序依次排号。
表 2-2-2 程序中控件对象的属性设置
序 号 类 别 名 称 Caption 文 字 特 点
2 标签 Label1 空 三号、蓝色、粗体
3 标签 Label2 空 三号、红色、粗体
8 按钮 Command15 退出 5 号、黑色、粗体
2.输入代码程序
在“代码”窗口中输入的代码程序如下。
Rem 声明变量 R、L、S 为单精度型,在整个窗体模块程序中有效
Rem 声明常量 PI=3.1415926,在整个窗体模块程序中有效
Dim R As Single, L As Single, S As Single, V As Single '定义三个单精度型变量
Const PI As Single = 3.1415926 '定义一个单精度型常量 PI
Rem *************** 输入半径的值 ***************
Private Sub Command11_Click( )
Dim TS$
TS$ = "请输入半径" + Chr(13) + Chr(10) + "R="
R = Val(InputBox(TS$, "输入半径", 8, 5000, 1600)) '将输入的半径数值赋给变量 R
End Sub
Rem *************** 计算圆的周长 ***************
Private Sub Command12_Click( )
L = 2 * PI * R '计算圆的周长,赋给变量 L
Label1.Caption = "圆周长是:" '将“圆周长是: ”赋给标签 Label1 的 Caption 属性
Label2.Caption = L '将变量 L 的值赋给标签 Label2 的 Caption 属性
End Sub
Rem *************** 计算圆的面积 ***************
Private Sub Command13_Click( )
S = PI * R * R '计算圆的面积,赋给变量 S
48 中文 Visual Basic 6.0 实用教程—结构化程序设计
Label1.Caption = "圆面积是:"
Label2.Caption = S
End Sub
Rem *************** 计算球的体积 ***************
Private Sub Command14_Click( )
V = 4 / 3 * PI * R ^ 3 '计算球的体积,赋给变量 V
Label1.Caption = "球体积是:"
Label2.Caption = V
End Sub
Rem *************** 退出程序运行 ***************
Private Sub Command15_Click( )
End
End Sub
2.2.4 项目拓展
1.复合表达式的运算顺序
复合表达式中可以有多种运算符,它们的运算次序如下。
算术运算符→字符串运算符→关系运算符→逻辑运算符。
例如:19−6>2+4 And 6*2=12
先进行算术运算“19−6” 、“2+4”和“6*2”,分别得 13、6 和 12;再进行关系运算“13>6”
和“12=12”,其值都是 True;再进行逻辑运算“True And True”,其值为 True。
2.表达式运算的 验 证 程 序
判 断 和 转 换 函 数 及 表 达 式 的 验 证 程 序 如 图 2-2-6 所 示 ,程 序 是 用 来 验 证 上 面 介
绍 的 判断和转换函数的一些概念, 程 序 运 行 结 果 如 图 2-2-7 所 示 。
2.3 函 数 运 算
2.3.1 数学函数
1.数学函数列表
数学函数的函数名、函数值类型和函数功能如表 2-3-1 所示。
表 2-3-1 数学函数
第2章 中文 Visual Basic 6.0 编程基础 49
函 数 名 函数值类型 功 能 举 例
2.数学函数列表说明
(1)表中的 N 表示是数值表达式;
(2)在三角函数中,自变量的单位是弧度;
(3)自然对数是以自然常量 e 为底的对数,在数学上写为 Ln。假如要求以任意数 n 为底,
以数值 x 为真数的对数值,可使用换底公式:
LognX=Ln(X)/Ln(n)
如求以 10 为底,X 的常用对数为:LgX=Ln(x)/Ln(10)。
在将数学代数式写为 Visual Basic 表达式时,必须将 Ln 改写为 Log。
2.3.2 字符串函数和字符串格式化
1.字符串函数列表
字符串函数的函数名(可以省略$符号)、函数值类型和函数功能如表 2-3-2 所示。
表 2-3-2 字符串函数
函 数 名 函数值类型 功 能 举 例
Asc("A")=65
Asc(C) Integer 求字符串中第一个字符的 ASCII 码 Asc("ABC")=65
Asc("")会产生错误
续表
函 数 名 函数值类型 功 能 举 例
将字符串 C 中的小写英文字母转换成大
Ucase$(C) String Ucase("Basic")="BASIC"
写英文字母
将字符串 C 中的大写英文字母转换成小
Lcase$(C) String Ucase("Basic")="basic"
写英文字母
Len(Space(5))=5
Space$(N) String 产生 N 个空格的字符串
注:引号内有 5 个空格
从字符串 C 的最右边开始,截取 N 个字
Right$(C,N) String Right$("BASIC",3)="SIC”
符
2.字符串函数列表说明
(1)表 2-3-2 中的 C 表示是字符串表达式,表中的 N 表示是数值表达式。
(2)对于数值函数 Val(C),逗号“,”和美元符号“$”,都不能被识别;空格、制表符和
换行符都将从参数中去掉;当遇到字母 E 或 D 时,将其按单精度或双精度实型浮点数处理。
(3)另外,还有 LenB(C)函数,该函数与 Len(C)函数功能相近,只不过 LenB 函数求的
是字符串的字节数,而不是字符串中字符的个数。例如,LenB("ABCabc123")=18,LenB("字
符串")=6。
(4)对于产生字符串函数 String$(N,C),C 参数可以为任何有效的数值表达式或字符串
表达式,如果为数值表达式,则表示组成字符串的字符为 ASCII;如果为字符串表达式,则
其第一个字符将用于产生字符串。
(5)对于字符串左截函数 Left(C,N),N 参数为数值表达式,其值指出函数值中包含多
少个字符。如果其值为 0,则函数值是长度为零的字符串(即空串);如果其值大于或等于字
符串 C 中的字符数,则函数值为整个字符串。
另外,还有 LeftB 函数,该函数与 Left 函数功能相近,只不过 LeftB 函数求的是字符串
的字节数,而不是字符串中字符的个数。LeftB("ABCDE",8)="ABCD"。
(6)对于字符串右截取函数 Right(C,N),N 参数为数值表达式,其值指出函数值中包
第2章 中文 Visual Basic 6.0 编程基础 51
2.3.3 项目实现
1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。
(2)单击工具箱中 CommandButton(按钮)按钮 ,然后在窗体中拖曳鼠标,在窗体
内的下边创建 1 个按钮控件对象。然后使用相同的方法,再在窗体内的下边创建 5 个按钮控
件对象。6 个按钮的 Caption 和“名称”属性如表 2-3-4 所示。
表 2-3-4 按钮的属性
属 性 名 称 1 2 3 4 5 6
2.3.4 项目拓展
1.转换函数
转换函数可将一种类型的数据转换成另一种类型的数据。常见的转换函数的函数
名和函数值类型如表 2-3-5 所示。
表 2-3-5 转换函数
函 数 名 函数值类型 函 数 名 函数值类型
(1)参数可以是任何类型的表达式,究竟是哪种类型的表达式,需根据具体函数而定。
(2)如果转换之后的函数值超过其数据类型的范围,将发生错误。
(3)当参数为数值型,且其小数部分恰好为 0.5 时,CInt 和 CLng 函数会将它转换为最
接近的偶数值。例如,Cint(0.5)的函数值为 0,Cint(1.5)的函数值为 2。
(4)当将一个数值型数据转换为日期型数据时,其整数部分将转换为日期,小数部分将
转换为时间。其整数部分数值 表示 相对于 1899 年 12 月 30 日前后天数,负数是指 1899 年
12 月 30 日以前的天数,正数是 1899 年 12 月 30 日以后的天数。例如,Cdate(30.5)的函数值
为 1900-1-29 12:00:00, Cdate(-30.25)的函数值为 1899-11-30 6:00:00。
2.判断函数
(1)IsNumeric 函数
【格式】IsNumeric(参数)
54 中文 Visual Basic 6.0 实用教程—结构化程序设计
【功能】判断参数的值是否为数值型。
【说明】参数可以是任何有效的表达式,函数值为 Boolean 型。如果表达式的值为数值型,
则函数值为 True,否则函数值为 False。
(2)判断类型函数(VarType)
【格式】VarType(参数)
【功能】求参数的类型。
【说明】参数可以是任何有效的表达式,表达式中可以包含除用户自定义数据类型的变量
之外的任何其他类型的变量。函数值为整型。函数值与数据类型的对应关系如表 2-1-2 所示。
(3)TypeName 函数
【格式】TypeName(参数)
【功能】求参数的类型。
【说明】参数可以是任何有效的表达式,表达式中可以包含除用户自定义数据类型变量
之外的任何其他类型变量。函数值为字符型,说明参数的类型。
3.转换函数和判断函数验证程序
判 断 和 转 换 函 数 及 表 达 式 的 验 证 程 序 如 图 2-3-5 所 示 。程 序 是 用 来 验 证 上 面 介
绍 的 判断和转换函数的一些概念, 程 序 运 行 结 果 如 图 2-3-6 所 示 。
2.4.1 日期和时间函数
1.日期和时间函数列表
日期和时间函数的函数名、函数值类型和函数功能如表 2-4-1 所示。
表 2-4-1 日期和时间函数
函 数 名 函数值类型 功 能
Now Date 返回当前的系统日期和系统时间
Date[$][( )] Date 返回当前的系统日期
Time"$""( )" Date 返回当前的系统时间
续表
函 数 名 函数值类型 功 能
判断参数是否可转换成日期,参数可以是任何类型的有效表达式。可转化则
IsDate(参数) Boolean
函数值为 True,否则函数值为 False
2.日期和时间函数列表说明
(1)在表 2-4-3 中,日期参数 D 是任何能够表示为日期的数值型表达式、字符串型表达式或
它们的组合。时间参数 T 是任何能够表示为时间的数值型表达式、字符串型表达式或它们的组合。
当参数 D 是数值型表达式时,其值表示相对于 1899 年 12 月 30 日前后天数,负数是指
1899 年 12 月 30 日以前,正数是指 1899 年 12 月 30 日以后。
(2)星期函数 Weekday(D)的函数值与星期的对应关系如表 2-4-2 所示。
表 2-4-2 星期函数 Weekday(D)的函数值与星期的对应关系
函 数 值 1 2 3 4 5 6 7
星期 星期日 星期一 星期二 星期三 星期四 星期五 星期六
(3)对于函数 DateAdd(时间单位,时间,D),其时间单位为一个字符串,表示所要加
上的时间单位,其取值及含义如表 2-4-3 所示;时间参数可以是数值型表达式,表示所要加
上的时间;其函数值可以是正数(得到未来的日期),也可以是负数(得到过去的日期) 。如
果 T 参数值包含小数点,则在计算时先四舍五入,再求函数值。
表 2-4-3 DateAdd 函数中的时间单位参数取值及含义
单 位 yyyy q m d y w ww h n s
含义 年 季 月 日 一年天数 一周天数 周 时 分 秒
2.4.2 调用外部应用程序函数(Shell)
1.格式和功能
【格式】Shell(字符串,窗口类型)
【功能】按照指定的窗口类型调出指定的外部可执行程序。同时还可以在外部可执行程
序中打开指定的文件,例如,在打开记事本的同时打开一个文本文件。
56 中文 Visual Basic 6.0 实用教程—结构化程序设计
2.函数说明
(1)字符串是要调用的外部文件的路径和文件名称,文件必须是可执行文件,其扩展名
为.EXE、.COM、.PIF 和.BAT。如果所调用的程序与 Visual Basic 程序在同一文件夹内,则可
省略路径。
(2)如果要在外部可执行程序中打开指定的文件,则字符串格式为:
外部文件的路径和文件名称+“ ”+打开文件的路径和文件名称
例如:在窗体中加入一个按钮,按钮的单击事件响应程序如下:
Private Sub Command1_Click( )
N=Shell("F:\Visual Basic\NOTEPAD.exe" + " " + "F:\Visual Basic\TEXT\TEXT1.TXT", 1)
End Sub
(3)窗口类型表示执行应用程序的窗口大小,为整型数据,其含义如表 2-4-4 所示。
表 2-4-4 窗口类型及含义
类 型 含 义 类 型 含 义 类 型 含义
0 窗口不显示 3 最大窗口,有指针 5 最小窗口,无指针
1 正常窗口,有指针 4 正常窗口,无指针 6 最大窗口,无指针
2 最小窗口,有指针
(3)函数的返回值是一个任务标识 ID,它是运行程序的惟一标识。
2.4.3 项目实现
1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。在窗体
内的下边创建两个按钮控件对象。两个按钮的 Caption 属性分别为“使用记事本程序”和“使
用游戏程序” ,“名称”属性采用默认值“Command1”和“Command2”。
(2)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在窗体内的上边创建
一个标签对象。单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的标签对象,在其“属
性”窗口内 Caption 属性值文本框中输入“使用 Windows 的记事本和游戏程序”文字,保留“名
称”文本框中的默认名称“Label1” ,设置文字字体为楷体、5 号、加粗,颜色为红色。
(3)将 Windows 的记事本程序 NOTEPAD.exe 保存在“F:\邮电职高\Visual Basic-结构化程序
设计\游戏和记事本”路径下,将一个文本文件 TEXT3.TXT 保存在“F:\邮电职高\Visual Basic-结
第2章 中文 Visual Basic 6.0 编程基础 57
2.4.4 项目拓展
1.格式输出函数(Format$)
用格式输出函数 Format$可以使数值、日期或字符串按指定的格式输出,一般用于 Print
方法中。其格式如下:
【格式】Format$(表达式[,"格式化符号"])
其中:表达式是要格式化的数值、日期和字符串类型表达式。格式化符号是表示输出表
达式值时所采用的输出格式。格式化符号要用引号括起来。
• 数值格式化:它是将数值型表达式的值按“格式化符号”指定的格式输出。有关格式
化符号及其应用举例如表 2-4-5 所示。注意:对于符号 0 与#,若要显示的数值表达式的整数
部分位数多于格式化符号的位数,则按实际数值显示,若小数部分的位数多于格式化符号的
位数,则四舍五入显示。
表 2-4-5 数值格式化的格式化符号及其作用
符 号 作 用 数值表达式 格式化字符串 显 示 结 果
• 日期和时间格式化:它是将日期型或数值型表达式的值转换为日期、时间的序数值,
并按“格式化符号”指定的格式输出。有关格式化符号及其应用举例如表 2-4-6 所示。
表 2-4-6 日期和时间格式化的格式化符号及其作用
符 号 作 用 符 号 作 用
d ,个位前不加 0
显示日期(1~3) dd 显示日期(01~31),个位前加 0
m ,个位前不加 0
显示月份(1~12) mm 显示月份(01~12),个位前加 0
y 显示一年中的天数(1~366) yy 两位数显示年份(00~99)
h ,个位前不加 0
显示小时(0~23) hh 显示小时(00~23),个位前加 0
m 在 h 后显示分(0~59),个位前不加 0 mm 在 h 后显示分(00~59)
,个位前加 0
s 显示秒(0~59),个位前不加 0 ss ,个位前加 0
显示秒(00~59)
其 中 ,分 钟 的 格 式 化 符 号 m、mm 与 月 份 的 格 式 化 符 号 相 同,区 分 的 方 法 :是 跟
在 h、 hh 后 的 为 分 钟 , 否 则 为 月 份 。 非 格 式 化 符 号 -、 /、 : 等 照 原 样 显 示。
2.格式输出函数应用举例
例 1 数值格式化输出验证程序如图 2-4-3 所示,程序运行结果如图 2-4-4 所示。
例 2 日 期 和 时 间 格 式 化 输 出 验 证 程 序 如 图 2-4-5 所 示 , 程 序 运 行 结 果 如 图
2-4-6 所 示 。
第2章 中文 Visual Basic 6.0 编程基础 59
• 字符串格式化:字符串格式化是将字符串按格式化符号指定的格式进行强制大小写显
示等。常用的字符串格式化符号及使用举例如表 2-4-7 所示。
表 2-4-7 字符串格式化的格式化符号及其作用
符 号 作 用 字符串表达式 格式化符号 显 示 结 果
实际字符位数小于符号 ABCDEF,
@ ABCDEF “@@@@@@@@”
位时,字符前加空格 在“ABCDEF”前有 2 个空格
实际字符位小于符号位 ABCDEF,在“ABCDEF”前
& ABCDEF “&&&&&&&&&”
时,字符前不加空格 无空格
3.日期和时间函数的验证程序
日期和时间函数的验证程序如图 2-4-7 所示,程序是用来验证上面介绍的判断和转换函
数的一些概念,程序运行结果如图 2-4-8 所示。
2.5.1 赋值语句
1.赋值语句的格式与功能
【格式】[Let] 变量名=表达式
或者:[Let][对象名称.]属性名称=表达式
【功能】计算表达式的值,再将其值赋给赋值号“=”左边的变量或对象的属性。
【说明】
① Let 关键字可以省略。当不要“对象名称”时,针对的是默认对象。
② 表达式的类型应与变量的类型一致(变体型变量除外) 。当同为数值型,但精度不一
样时,强制转换为变量的精度。
③ 赋值号与等号同为“=”,但它们的含义完全不一样,Visual Basic 系统会根据“=”在
语句中的位置,自动判断它是赋值号还是等号。例如,N=A=123 语句中,左起第一个“=”
是赋值号,其他的“=”是等号。如果变量 A 的值是 2,则变量 N 的值是 True。
④ 将表达式的值赋给变量后,变量的原值将被表达式的值所替代。
2.赋值语句的常规使用举例
(1)给变量赋值:N1!=8.6:A1$="BASIC":N2%=689
(2)给对象的属性赋值:Text1.text="赋值语句的使用实例"
(3)两个变量(A 和 B)数值的互换:N=A:A=B:B=N
(4)计数:N=N+1 '将变量 N 的数值加 1 后再赋给变量 N。
(5)累加:SUM=SUM+N '将变量 SUM 的数值加上变量 N 的值,再赋给变量 SUM。
(6)累积:SUM=SUM*N '将变量 SUM 的数值乘上变量 N 的值,再赋给变量 SUM,
显然变量 SUM 的初值不可以为 0 。
1.Print方法
Print 方法在窗体、图片框、立即窗口和打印机等对象中,用来显示文本字符串和表达式
的值。Print 方法的格式和功能与早期 Basic 语言中的 PRINT 语句类似。
【格式】[对象名称.]Print[表达式表]
【功能】首先计算表达式的值,然后在指定的对象中,输出表达式的值。
【说明】
① 对象可以是窗体(Form)、立即窗口(Debug) 、图片框(PictureBox)和打印机(Printer)
等,如果省略对象名称,则在当前窗体上输出。
② Print 关键字可以用“?”代替,Visual Basic 会自动将它翻译为 Print。
③ 表达式表是由若干个表达式组成,各表达式之间可用分隔符为逗号(,)、分号(;)
第2章 中文 Visual Basic 6.0 编程基础 61
3.Cls方法
【格式】Cls
【功能】将窗体(Form) 、图片框(PictureBox)等内的文本内容清除。默认的对象是窗体。
例如:Form1.Cls、Picture1.Cls、Cls。Form1.Cls 和 Cls 语句的效果一样。
2.5.3 项目实现
2.5.4 项目拓展
1.Beep语句的格式与功能
【格式】Beep
【功能】使计算机喇叭响一声。
2.End语句的格式与功能
【格式】End
【功能】使正在运行的程序中止运行。
思考与练习
1.填空题
(1)Visual Basic 中变量、符号常量和自定义函数的名称以________或________开头,变
量名称不可以超过________个字符,对象名称不可以超过________个字符。一个汉字相当于
个字符。
(2)Visual Basic 中的数据类型可分为________和________两大类。
(3)标准数据类型可分为________、________、________、________、________、________、
________、________、________、________、________、________和________类型。
(4)日期型数据有________和________两种表示方法。
(5)如果没有声明变量的数据类型,则该变量将被默认为是________类型。
(6)一行语句允许最多________个字符,一行中的多条语句之间必须用________分隔。
第2章 中文 Visual Basic 6.0 编程基础 63
(7)一行语句可以分多行书写,在续行的前一行末尾应加入________。
(8)Abs(-9.6)=________,Asc("cde")=________,Chr(69)=________,Len("2008 年北京
奥运")=________。
( 9 ) Str$(-16)+Str$(16)=________ , Val("68")+Val("21abc")=________ , Len(Space(9))=
________,String$(2,"2008 年北京奥运")=________。
(10)Left("中华人民共和国",4)=________,Right("2008 年北京奥运",6)=________,
Mid("迎接 2008 年北京奥运",2,6)=________,"ABC"&123=________。
(11)32\3=________,7 Mod 2=________,-7 Mod 2=________,7 Mod-2=________,-7
Mod-2=________,4^3=________。
(12) Int(100/2)=_______,Abs(10-23)=_______,Sgn(10-23)=_______,Fix(-5.6) =_______,
Int(-5.6) =________,Fix(5.6) =________,Int(5.6) =________。
2.回答下列问题
(1)单精度实型和双精度实型数据有哪两种表示方法,分别适合在什么情况下使用?
(2)语句的书写规则有哪几条?
(3)如何强制显示声明变量?
(4)如何调用外部应用程序?
(5)如何判断“=”是赋值号还是等号?
(6)Print 方法的作用是什么,如何使用 Print 方法,与 Print 方法有关的函数有哪些,这
些函数的功能是什么?
(7)什么是字符串,字符串型数据可分为哪几种类型?
(8)表达式有几种,各种表达式的运算顺序是怎样的?
3.下列 Visual Basic 数据中,哪些是合法的,哪些是非法的,为什么?
(1)12,45 (2)-12.3E+5 (3)E-12 (4)1.2E
(5)12a34 (6)1.23-45 (7)1.2D+3 (8)7.35D-6
(9)"123" (10)"123A321" (11)'ABC' (12)"!@#$%&*"
4.判断下面的符号哪些是 Visual Basic 的变量,其中的变量各属于哪一类变量。
(1)X1 (2)123 (3)AB12CD (4)12AB (5)中国
(6)X/Y (7)A*B (8)_ABC (9)D6% (10)N1$
(11)Y78$ (12)$ABC (13)ABC! (14)B2# (15)GW12@
(16)abc1@ (17)True (18)Print (19)Cls (20)End
5.将下列 Visual Basic 表达式转化为数学代数式。
(1)2*A*B+Sqr(A^2+B^2)
(2)Sqr(A*(A-B)*(B-C)*(C-D))/A^2+B2+C^2
(3)X-1/(X-(1/(X-1/X)))
(4)N1*x^3+2*N2*X*X+N3+15*Abs((8-5/2)+9)-10
(5)Abs(A*A*A+B*B*B)/Sqr(A^3+B^3)
(6)Sin(2*a^2-3*b+c)+Cos(a+b*c+d)
(7)Sin(5*Abs(6-Sqr(Exp(2)/5*3)))+Log(Abs(Exp(5)/2))
(8)1/(N-(1/(N-1/(N-1/(N-1)))))
64 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.计算下列表达式的值,并指出其值是什么数据类型。
(1)Int(28.2 + 12.5)> Fix(42.35−Abs(-2))
(2)((15 < 3) And (11 > 6)) Or ((6 >= 2) Xor(-3 <-2))
(3)Not 10-5 > 12 + 3 And 3 * 2 = 6 Or 5 <= 3
7.根据要求编写程序。
(1)输入货物的重量(单位公斤)和运费单价(元/公斤),计算并显示出运费。
(2)输入三角形的 3 个边长,计算并显示三角形的周长和面积。
(3)输入边长,计算并显示正方形周长、正方形面积和正方体体积。
(4)显示大写字母和小写字母的 ASCII 和与对应的字母。
(5)输入角度的弧度值,将弧度转换为度、分、秒的角度值并显示出来。
(6)将度、分、秒的角度值换算为弧度值。设度、分、秒分别用变量 A、B、C 表示,
则其弧度值 D=(A+B/60+C/3600)*3.1415926/180。输入的度、分、秒的角度值应是小数形式。
例如:68 度 32 分 45 秒输入的数据是 68.3245。
(7)编写一个“四则运算”程序。程序运行后,窗体中显示“四则运算”标题,有 3 个
标签和 6 个按钮。左边两个标签内会显示两个 100 以内的随机正整数。分别单击“+”、“−” 、
“×”和“÷”按钮,可以在右边标签中显示出这两个数的和、差、积、商。单击“下一个”
按钮,可以产生并显示新的随机数,单击“退出”按钮,可以退出程序的运行。
(8)输入一元二次方程 A*X2+B*X+C=0 中的 3 个系数 A、B 和 C 的值,计算并显示出
该一元二次方程 A*X2+B*X+C=0 的实数根(输入的 3 个系数应符合 B*B-4*A*C>=0)。
基本算法和控制结构
第 3章
3.1 提取人民币的方案
3.1.1 算法概述
1.什么是算法
广义地说,做任何事情都需要先确定算法,然后去实现这个算法以达到目的。对于计算
机来说,算法就是为了解决一个特定问题而采取的特定和有限的操作步骤,就是用于求解某
个特定问题的一些指令的集合。具体地说,用计算机所能实现的操作或指令,来描述问题的
求解过程,就得到了这一特定问题的计算机算法。
例如:计算 5!的步骤是:计算 1×2 的值为 2→计算 2×3 的值为 6→计算 6×4 的值为 24→
计算 24×5 的值为 120,即 5!=120。
利用计算机来解决问题需要编写程序,在编写程序前要对问题进行充分的分析,设计解
题的步骤与方法,也就是设计算法,然后根据算法编写程序。例如,计算 5!的值,上面已给
出了计算的步骤,要实现上述计算,需用变量 SUM 存放初值 1,以后存放每次乘积的值和最
后的计算结果,用变量 N 存放初值 0,用 N=N+1 语句使 N 再依次取整数 1,2,3,4 和 5,用
SUM=SUN*N 语句完成每次的乘法运算。根据上述算法,设计计算 5!的程序如下。
SUM=1:N=0
N=N+1:SUM=SUM*N
N=N+1:SUM=SUM*N
N=N+1:SUM=SUM*N
N=N+1:SUM=SUM*N
N=N+1:SUM=SUM*N
Print “5!=”;SUM
2.算法的特征
一个算法具有下列 5 个重要特性。只有具有这 5 个特性才能够被称为算法。
① 有穷性:对任何合法的输入数值来说,一个算法必须总是在执行有穷(即有限)的
操作步骤之后结束,且每一个操作步骤都可在有穷(即有限)时间内完成。
② 确定性:算法中每一步操作都必须有准确的含义,不允许有二义性。算法的正确性
要求,对于相同的输入,算法只有惟一的一条执行路径,即对于相同的输入只能得出相同的
输出。
③ 可行性:算法中描述的所有操作,都可以通过执行有限次的基本运算来实现。
66 中文 Visual Basic 6.0 实用教程—结构化程序设计
④ 输入性:一个算法有零个或多个的输入,这些输入取自于特定对象的集合。如果没
有输入,则算法的内部应确定其初始条件。
⑤ 输出性:一个算法有一个或多个输出,没有输出的算法毫无意义。算法的输出与算
法的输入之间存在着特定的关系,算法完成从输入到输出之间的数据加工。
算法的 5 个特性中最重要的是有穷性,如果不具有有穷性,只称为计算方法。
3.算法的控制结构
一个算法的功能不仅与选用的操作有关,而且与这些操作之间的执行顺序有关。算法的
控制结构给出了算法的执行框架,它决定了算法中各种操作的执行次序。算法的控制结构有
3 种基本的形式:顺序结构、选择结构和循环结构。任何复杂的算法都可以用顺序、选择和
循环这 3 种控制结构的组合来描述。所以,这 3 种控制结构称为算法的 3 种基本控制结构。
(1)顺序结构:是指通过安排语句的排列顺序来决定程序流程的程序结构。在这种结构中,
各个操作是依次执行的。一个算法总有一个入口,经过有限次的顺序操作后,由一个出口结束
算法的操作。这种结构有单入单出的性质。一个程序通常可分为输入、处理和输出 3 个部分。
由于顺序结构是按语句在程序中出现的次序,一条一条地执行的,无分支、无循环,所
以不会出现死语句和死循环。因此,顺序结构是最简单结构化程序。
(2)选择结构:在许多情况下,算法不会按部就班地从第一条操作依次执行到最后一条
操作,往往需要根据某个条件来决定执行哪条语句,这种结构就是选择结构。选择结构有单
选结构、双选结构和多选结构 3 种类型,也具有单入单出的性质,但它是开放型的,即一旦
进入选择结构,执行了与判定条件相对应的一组操作后,就立即退出选择结构。
(3)循环结构:算法中的循环结构是指需要反复地执行某组操作的结构。循环控制就是
指由特定的条件决定某些语句重复执行次数的控制方式。它也具有单入单出的性质,是封闭
型的,一旦进入循环结构,只要循环条件未达到结束状态,就始终执行循环体内的操作。循
环结构又分为当型循环结构与直到型循环结构,前者是先进行条件判断,再执行程序段语句;
后者是执行一次要重复执行的程序段语句,再进行条件判断。
3.1.2 算法的描述方法
为了将算法正确的表示出来,需要使用各种算法描述工具。算法有许多描述方法,常用
的有两类:文字描述(也叫自然语言描述,如汉语、英语或数学语言)和图形描述。例如前
面所用的方法是文字描述,即使用人们日常使用的自然语言描述解决问题的步骤与方法。使
用文字描述的算法通俗易懂,容易掌握,但算法的表达与计算机的具体高级语言形式差距较
大,而且比较烦琐,对条件转向等描述欠直观,还具有“歧义性”(即对同一段文字,不同的
人会有不同的理解)。针对文字描述的缺点,就产生了图形描述法。图形描述法主要有流程图
法、N-S 图法和 PAD 图法 3 种。
计算机的算法有数值型算法和非数值型算法。计算 5!的算法属于数值型运算算法,而进
行数据检索、分类、排序和计算机绘图等都属于非数值型算法。
1.流程图描述方法
流程图是一种用图形来表示算法的描述方法,它通过各种几何框图和流程线来描述各步
骤的操作和执行的过程。这种方法直观形象、逻辑清楚、容易理解,但它占用篇幅大,流程
随意转向,较大的流程图不易读懂。对于初学者或编写较小的程序时,可采用流程图的方法。
第3章 基本算法和控制结构 67
起始框:表示程序的起始和终 输入输出框:表示输入输出数据
止
处理框:表示完成某种项目的 流程线:表示程序执行的方向
操作
判断框:表示进行判断 连接点:表示两段流程图流程的连
接点
A 成立
条件
不成立
B A B
(a) (b)
A
A
成立 成立
条件 条件
不成立 不成立
当型循环 直到型循环
(c)
2.N-S 图描述方法
N-S 图是 1973 年美国科学家 Nassi 和 Shneid erman B 首次提出的一种描述算法的图形方
法。N-S 图形方法完全去掉了流程线,全部算法写在一个矩形框内,总框内包含其他的功能
框。用 N-S 图描述程序的 3 种基本结构如图 3-1-2 所示。
条件 条件
A 不
成立 成立 A
B A B A
条件
次关系。这种描述算法的方法,层次清楚,逻辑关系明了,在有多次嵌套时,不易出错。用
PAD 图描述程序的 3 种基本结构如图 3-1-3 所示。
A A
条
件 当条件 A 直到条件 A
当型循环 直到型循环
B B
3.1.3 项目实现
储户到银行提取存款时,银行的出纳员应如何付款才可以使储户拿到的人民币的张数最
少呢?“银行取款”程序可以根据用户输入的金额数,计算出每种面值所需的数量,程序运
行后的画面如图 3-1-4 所示。在“取款总金额”标签右边的两个文本框内分别输入要提取金
额的整数和小数部分,单击“面值分配方案”按钮,则会在下面的标签中显示出各种人民币
的数量,如图 3-1-5 所示。
1.设置对象的属性
创建窗体如图 3-1-4 所示,在窗体中,有两个文本框对象、多个标签对象和 1 个按钮对
象。按钮对象的 Caption 属性为“面值分配方案” ,两个文本框的 Text 属性为空串,显示文字
的标签、文本框和按钮对象的名称均采用默认值。最下面一排的 13 个标签的名称从左到右分
别为:LabelB0,LabelB1,LabelB2,…,LabelB11,LabelB12,它们的 SackStyle 的属性都
为 1-Opaque。这些对象的属性设置,用户可以自行完成。
2.输入代码程序
Private Sub Command1_Click( )
Dim N As Long
N = Val(整数.Text) * 100 + Val(小数.Text) '将金额以分为单位表示
Yl00 = N \ 10000 '求 100 元票张数
N = N - Yl00 * 10000 '求剩余款额
Y50 = N \ 5000 '求 50 元票张数
N = N - Y50 * 5000 '求剩余款额
Y20 = N \ 2000 '求 20 元票张数
N = N - Y20 * 2000 '求剩余款额
Y10 = N \ 1000 '求 10 元票张数
N = N - Y10 * 1000 '求剩余款额
Y5 = N \ 500 '求 5 元票张数
第3章 基本算法和控制结构 69
N = N - Y5 * 500 '求剩余款额
Y2 = N \ 200 '求 2 元票张数
N = N - Y2 * 200 '求剩余款额
Y1 = N \ 100 '求 1 元票张数
N = N - Y1 * 100 '求剩余款额
J5 = N \ 50 '求 5 角票张数
N = N - J5 * 50 '求剩余款额
J2 = N \ 20 '求 2 角票张数
N = N - J2 * 20 '求剩余款额
J1 = N \ 10 '求 1 角票张数
N = N - J1 * 10 '求剩余款额
F5 = N \ 5 '求 5 分票张数
N = N - F5 * 5 '求剩余款额
F2 = N \ 2 '求 2 分票张数
N = N - F2 * 2 '求剩余数额
Fl = N '求 1 分票张数
Rem 给相应的标签对象的 Caption 属性赋值
LabelB0.Caption = Yl00
LabelB1.Caption = Y50: LabelB2.Caption = Y20
LabelB3.Caption = Y10: LabelB4.Caption = Y5
LabelB5.Caption = Y2: LabelB6.Caption = Y1
LabelB7.Caption = J5: LabelB8.Caption = J2
LabelB9.Caption = J1: LabelB10.Caption = F5
LabelB11.Caption = F2: LabelB12.Caption = Fl
End Sub
程序中,变量 Yl00 用来保存 100 元票面的张数,变量 Y50 用来保存 50 元票面的张数,
变量 Y20 用来保存 20 元票面的张数,变量 Yl0 用来保存 10 元票面的张数,变量 Y5 用来保
存 5 元票面的张数,变量 Y2 用来保存 2 元票面的张数,变量 Y1 用来保存 1 元票面的张数;
变量 J5 用来保存 5 角票面的张数,变量 J2 用来保存 2 角票面的张数,变量 J1 用来保存 1 角
票面的张数,变量 F5 用来保存 5 分票面的张数,变量 F2 用来保存 2 分票面的张数,变量 F1
用来保存 1 分票面的张数。
3.1.4 项目拓展——“四则运算”程序
1.“四则运算”程序的对象属性设置
“四则运算”程序的控件对象有 6 个标签和 7 个按钮,如图 3-1-7 所示。这些对象的主要
属性设置如表 3-1-2 所示。对象的序号按从上到下、从左到右的顺序依次排号。
表 3-1-2 “四则运算”程序控件对象的属性设置
序 号 类 别 名 称 Caption 文 字 特 点
3 标签 数1 空 宋体、三号、黑色
4 标签 符号 空 黑体、三号、红色
5 标签 数2 空 宋体、三号、黑色
6 标签 等号 = 黑体、三号、红色
7 标签 结果 空 宋体、三号、黑色
8 按钮 加 + 黑体、三号、黑色
9 按钮 减 − 黑体、三号、黑色
10 按钮 乘 * 黑体、三号、黑色
11 按钮 除 ÷ 黑体、三号、黑色
12 按钮 重新 重新 宋体、三号、黑色
13 按钮 退出 退出 宋体、三号、黑色
2.输入“四则运算”程序的代码
“四则运算”程序的代码程序如下。
Private Sub Form_Activate( )
Rem 显示窗体后,产生两个两位的随机正整数,分别赋给标签“数 1”和“数 2”
Randomize
数 1.Caption = Int(Rnd * 90) + 10 '产生 2 位的随机整数
数 2.Caption = Int(Rnd * 90) + 10 '产生 2 位的随机整数
End Sub
Rem 单击“+”按钮,进行加法运算,将其值赋给“结果”标签
Private Sub 加_Click( )
结果.Caption = CInt(数 1.Caption) + CInt(数 2.Caption) '计算两个数的和
符号.Caption = "+" '给“符号”标签赋加运算符号
End Sub
Rem 单击“-”按钮,进行减法运算,将其值赋给“结果”标签
Private Sub 减_Click( )
结果.Caption = CInt(数字 1.Caption) - CInt(数字 2.Caption) '计算两个数的差
符号.Caption = "-" '给“符号”标签赋减运算符号
End Sub
Rem 单击“*”按钮,进行乘法运算,将其值赋给“结果”标签
Private Sub 乘_Click()
结果.Caption = CInt(数 1.Caption) * CInt(数 2.Caption) '计算两个数的积
符号.Caption = "*" '给“符号”标签赋乘运算符号
End Sub
第3章 基本算法和控制结构 71
Rem 单击“÷”按钮,进行除法运计算,将其值赋给“结果”标签
Private Sub 除_Click()
结果.Caption = CInt(数 1.Caption) / CInt(数 2.Caption) '计算两个数的商
符号.Caption = "÷" '给“符号”标签赋除运算符号
End Sub
Rem 单击“重新”按钮后,产生两个 100 以内的随机整数,分别赋给标签“数 1”和“数 2”
Private Sub 重新_Click()
Randomize
数 1.Caption = Int(Rnd * 90) + 10 '产生 2 位的随机整数
数 2.Caption = Int(Rnd * 90) + 10 '产生 2 位的随机整数
符号.Caption = "" '清空“符号”标签
结果.Caption = "" '清空“结果”标签
End Sub
Rem ********* 在单击“退出”按钮后,退出程序运行 *********
Private Sub 退出_Click()
End
End Sub
3.2 计 算 运 费
3.2.1 单选择双分支语句
【功能】当条件成立时,执行“语句序列 1”中的各条语句;当条件不成立时,执行“语
句序列 2”中的各条语句,如果没有“Else 语句序列 2”选项,则不执行,然后执行 End If 后
面的各条语句。括号“[ ]”内的内容是可选项,其功能可参看图 3-1-1 至图 3-1-3 中的(b)图。
【说明】“语句序列 1”和“语句序列 2”可以由一个语句行或多个语句行组成。在编程
的习惯上,常把夹在关键字 If、Then 和 Else 之间的语句序列以缩排的方式排列,这样会使程
序更容易阅读理解。
不成立
不成立 不成立
不成立
条件 1 条件 2 …… 条件 N–1
成立 成立 成立
3.2.3 项目实现
1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。在窗体
内的下边创建两个按钮控件对象。两个按钮的 Caption 属性分别为“输入货物的重量”和“退
出”,“名称”属性采用默认值“Command1”和“Command2”。
(2)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在窗体内的上边
创建一个标签对象。单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的标签对象,
在其“属性”窗口内 Caption 属性值文本框中输入“计算货物的运费”文字,保留“名称”
文本框中的默认名称“Label1”,设置文字字体为宋体、四号、加粗,颜色为红色。
(3)再创建两个标签对象,从上到下,标签对象的“名称”属性值分别为“Label2”和
“Label3”,Caption 属性值都为空串,文字字体为宋体、5 号、加粗,颜色为黑色。
下面采用 3 种语句来输入代码程序,程序的运行效果一样。
2.使用单行式 If Then Else 语句
Private Sub Command1_Click()
Dim N, P As Single
TS$ = "请您输入货物的重量数!" + Chr(13) + Chr(10) + "货物重量数是:"
Rem 将输入的货物的重量数赋给变量 N
N = Val(InputBox(TS$, "请输入货物重量数", 0, 5000, 1600))
If N <= 30 Then P = N * 2 Else P = N * 2 + (N - 30) * 0.8
Label2.Caption = "货物的重量是:" & N
Label3.Caption = "货物的运费是:" & P
End Sub
Private Sub Command2_Click()
End
End Sub
单击“文件”→“保存工程”菜单命令,将当前的工程保存为“工程 1.vbp”文件。单
击“文件”→“保存 Form1.frm”菜单命令,将当前窗体文件保存为“Form1.frm”文件。程
序中的选择结构程序的流程图如图 3-2-5 所示。
3.使用区块式 If Then Else 语句
将窗体的“名称”和 Caption 属性改为“Form2”。单击“文件”→“工程另存为”菜单
命令,将当前的工程保存为“工程 2.vbp”文件。单击“文件”→“Form1.frm 另存为”菜单
74 中文 Visual Basic 6.0 实用教程—结构化程序设计
命令,将当前的窗体文件保存为“Form2.frm”文件。将程序修改如下,程序中的选择结构程
序的流程图如图 3-2-5 所示。
If N <= 30 Then
P=N*2
Else
P = N * 2 + (N - 30) * 0.8
End If
4.使用 If Then Elself 语句
将窗体的“名称”和 Caption 属性改为“Form3”
。然后,单击“文件”→“工程另存为”
菜单命令,将当前的工程保存为“工程 3.vbp”文件。单击“文件”→“Form2.frm 另存为”
菜单命令,将当前的窗体文件保存为“Form3.frm”文件。将程序修改如下,程序中的选择结
构程序的流程图如图 3-2-6 所示。
不成立
不成立
N<=30 N<=30 N>30
成立 成立 成立
P=N*2+ P=N*2+
P=N*2 P=N*2
(N–30)×0.8 (N–30)×0.8
If N <= 30 Then
P=N*2
ElseIf N > 30 Then
P = N * 2 + (N - 30) * 0.8
End If
3.2.4 项目拓展
1.“符号函数”程序
【实例】 制作一个“符号函数”程序。该程序运行后的画面如图 3-2-7 左图所示。单击
窗体中的“输入一个数值”按钮,即可调出“请输入一个数”对话框,要求输入一个数。输
入一个数(此处输入 100),如图 3-2-7 中图所示,然后单击“确定”按钮,即可关闭“请输
入一个数”对话框,回到原窗体中,并在窗体中显示输入数的特性(正数、负数或零),此处
显示“这是正数!”,如图 3-2-7 右图所示。如果输入的是负数,则显示“这是负数!”;如果
输入的是零,则显示“这是零!”。
“符号函数”程序的窗体设计和对象属性设置比较简单,用户可自行完成。注意要设置
标签对象的“BorderStyle”属性值为“1-Fixed Singled”,表示标签为三维形状。
可以看出,该程序的窗体与“计算运费”窗体基本一样,只是显示的文字内容不一样。
该窗体的设计用户可自行完成。代码程序如下,程序中的选择结构程序的流程图如图 3-2-8
第3章 基本算法和控制结构 75
所示。
不成立 不成立
N>0 N=0 N<0
成立 成立 成立
图 3-2-12 书如不同的工资数后显示不同的统计结果
成立 成立 成立 成立 成立
N2=(N1–1000)×0.05
N2=(N1–1000)×0.05
N2=(N1–1000)×0.05+ +(N1–1500)×0.15+
N2=0 N2=(N1–1000)×0.05 +(N1–1500)×0.15+
(N1–1500)×0.15 (N1–5000)×0.1
(N1–5000)×0.1
+(N1–10000)×0.1
3.3 求一元二次方程的解
3.3.1 选择结构的嵌套
选择结构的语句中的“语句序列”可以是一个选择结构语句,这就叫选择结构的嵌套。
例如,上一节中介绍的“符号函数”程序可以采用选择结构的嵌套方式修改如下。
Private Sub Command1_Click()
Dim N As Single, FH As String
TS$ = "请您输入一个数!" + Chr(13) + Chr(10) + "输入的数是:"
Rem 将输入的数赋给变量 N
N = Val(InputBox(TS$, "请输入一个数", 0, 5000, 1600))
Rem 如果变量 N 大于或等于 0,则
If N >= 0 Then
Rem 如果变量 N 大于 0,则 FH="这是正数!";变量 N 等于 0,则 FH="这是零!"
If N > 0 Then
FH = "这是正数!"
Else
FH = "这是零!" 嵌套的选择结构语句
End If
Else
FH = "这是正数!"
78 中文 Visual Basic 6.0 实用教程—结构化程序设计
End If
Label2.Caption = "输入的数是:" & N
Label3.Caption = FH
End Sub
Private Sub Command2_Click()
End
End Sub
程序中,If N >= 0 Then 语句的语句序列 1 是由一个区块式 If Then Else 语句序列成的,
它的语句序列 2 是由 FH = "这是正数!"语句序列成的。程序中的选择结构程序的流程图如图
3-3-1 所示。
成立 不成立
N>=0 N>0
不成立 成立
图 3-3-1 选择结构的嵌套流程图
表达式
计算表达式的值与取值列
表 N–1 中的数据不相等
取值列表 1 取值列表 2 …… 取值列表 N–1
3.3.3 项目实现
图 3-3-3 一元二次方程的根
80 中文 Visual Basic 6.0 实用教程—结构化程序设计
2
2 − b ± b − 4ac
一元二次方程 ax +bx+c=0 的求根公式 x = 是数学中最常用的公式之一,
2a
Text3.Text = ""
End Sub
Rem 退出程序运行
Private Sub Command3_Click()
End
End Sub
程序中的 Sqr()是求数学表达式平方根的函数。Chr()函数用于返回给定 ASCII 值对应的
字符,Chr(13)为回车符,用于换行。Str()函数用于将数值表达式的值转换为字符串。
单击“文件”→“保存工程”菜单命令,将当前的工程保存为“工程 1.vbp”文件。单
击“文件”→“保存 Form1.frm”菜单命令,将当前的窗体文件保存为“Form1.frm”文件。
程序中的选择结构程序的流程图如图 3-3-4 所示。
不成立
不成立
D<0 D=0
成立 成立
x1=(–b+Sqr(D))/(2×a)
FCG="该方程 x1=(–b)/(2×a)
无实根!" x2=(–b–Sqr(D))/(2×a)
FCG="x1="+Str(x1)
FCG="x1="+Str(x1)+"x2="+Str(x2)
图 3-3-4 选择结构的嵌套流程图
D
(D=b×b–4×a×c)
x1=(–b+Sqr(D))/(2×a)
FCG="该方程 x1=(–b)/(2×a)
无实根! " x2=(–b–Sqr(D))/(2×a)
FCG="x1="+Str(x1)
FCG="x1="+Str(x1)+ "x2="+Str(x2)
3.3.4 项目拓展——“工资扣税”程序
3.4 九九乘法表
在解决实际问题时,常常需要重复某些相同的操作,即对某一语句或语句序列重复执行
多次,解决此类问题,就要用到循环结构语句。
Print N,
Next N
Print: Print "N="; N
End Sub
该程序运行后,执行 For 语句,循环变量 N 取值 2<8(终值) ,因步长值为正数,没有超
出终值,则执行循环体语句“Print N,” ,在窗体中第 1 行第 1 列显示变量 N 的值 2。执行 Next
语句时,N 加步长值 3 后再赋值给变量 N 等于 5,与终值 8 比较(5<8),没有超出终值,再
执行“Print N,”语句,在窗体中第 1 行第 15 列(第 2 显示区的第 1 列)显示 N 的值 5。
再执行 Next 语句时,N 加步长值后的取值为 5+3=8,与终值 8 比较没有超出终值,再执行
“Print N,”语句,在窗体中第 1 行第 29 列(第 3 显示区的第 1 列)显示 N 的值 8。然后,再执
行 Next 语句,N 加步长值后的取值为 8+3=11,超出终值,退出循环语句,执行“Next N”语句
下面的语句“Print:Print "N=";N”
,在第 2 行第 1 列显示 N 的值 11。窗体显示如图 3-4-2 所示。
【实例 2】程序如下。
For N = 8 To 2 Step -3
Print N,
Next N
Print : Print "N=";N
该程序运行后,执行 For 语句,循环变量 N 取值 8>2(终值) ,因步长值为负数,没有超
出终值,则执行语句“Print N,”,在窗体中第 1 行第 1 列显示变量 N 的值 8。执行 Next 语句
时,N 加步长值−3 后再赋值给 N 等于 5,与终值 2 比较(5>2) ,没有超出终值,再执行“Print
N,”语句,在窗体中显示 5。再执行 Next 语句时,N 加步长值后的取值为 2,与终值 2 比较
没有超出终值,再执行“Print N,”语句,在窗体中显示 1。
然后,再执行 Next 语句,N 加步长值后的取值为−1,超出终值,退出循环语句,执行“Next N”
语句下面的语句“Print:Print "N=";N”
,在第 2 行第 1 列显示 N 的值−1。窗体显示如图 3-4-3 所示。
SUM=0 SUM=1
N=1 N=1
终止为 100 终止为 10
步长值为 1 步长值为 1
SUM=SUM+N SUM=SUM×N
N=N+1 否 N=N+1 否
N>100? N>10?
是 是
3.4.2 循环结构的嵌套
1.循环嵌套分析
可以把一个循环结构放入另一个循环结构之中,这称为循环结构的嵌套。例如,可以在一
个 For Next 语句中嵌套另一个 For Next 语句,组成嵌套循环。下面的程序就是一个循环嵌套结
构,变量 A 是外循环的循环变量,变量 B 是内循环的循环变量。它的执行过程分析如下(为了
说明方便,给每条语句加上了编号) ,它的流程图如图 3-4-7 所示。程序运行结果如图 3-4-8 所示。
Private Sub Form_Activate()
1 For A = 1 To 2
2 For B = 5 To 3 Step -2
3 Print A,B
4 Next B
5 Next A
6 Print "A=";A,"B=";B
End Sub
N=1
终值为 100 B=B+步长值–2
步长值为 1
否
B<终值 3?
SUM=SUM+N
SUM1=SUM1+SUM
是
A=A+步长值 1
N=N+1
否
A>终值 2?
否
N>100?
是
是 显示变量 A 和 B 的值
3.4.3 项目实现
1.九九乘法表 1
“九九乘法表 1”程序运行后的画面如图 3-4-9 所示。程序如下。
Private Sub Form_Activate()
Dim N1, N2 As Integer '声明变量 N1 和 N2 为整型变量
FontSize = 15 '设置“九九乘法表”标题文字的大小
ForeColor = vbRed '设置“九九乘法表”标题文字的颜色为红色
FontBold = True '设置“九九乘法表”标题文字为粗体
Print Tab(30); "数学九九乘法表": Print
FontSize = 10 '设置“九九乘法表”文字的大小
ForeColor =vbBlue '设置“九九乘法表”文字的颜色为蓝色
FontBold = False '设置“九九乘法表”文字为非粗体
For N1 = 1 To 9
For N2 = 1 To N1 '外循环变量 N1 作为内循环的终值
Print Tab(N2 * 12 - 12); Str$(N1) + "×" + Str$(N2) + "=" + Str$(N1 * N2);
Next N2
第3章 基本算法和控制结构 89
Print '每显示完一行后换行
Next N1
End Sub
3.九九乘法表 3
“九九乘法表 3”程序运行后的画面如图 3-4-11 所示。程序只是将“九九乘法表 2”程序
“九九乘法表 3”程序如下。
中的内循环语句进行如下修改即可。
Private Sub Form_Activate()
90 中文 Visual Basic 6.0 实用教程—结构化程序设计
3.4.4 项目拓展
1.在程序中设置窗体文字的属性
(1)FontName:是字符型数据,用来设置文字的字体。
(2)FontSize:是整型数值数据,用来设置文字的大小。
(3)FontBold:是逻辑型数据,用来设置文字是否为粗体。取值为 True 时,设置文字为
粗体;取值为 False 时,设置文字为非粗体。
(4)FontItalic:是逻辑型数据,用来设置文字是否为斜体。取值为 True 时,设置文字为
斜体;取值为 False 时,设置文字为正体。
(5)BackColor:用来设置对象的背景色。
(6)ForeColor:用来设置对象的前景色(文字颜色)。
设置颜色的语句格式如下:
Object.BackColor=Color
Object.ForeColor=Color
其中,Object 是对象名称,对象为窗体时可省略。Color 是描述颜色的数值,Color 可以有 4
种表示方法,其中可以使用系统提供的描述颜色的常量,例如,vbRed 表示红色,vbGreen
表示绿色,vbBlue 表示蓝色,vbBlack 表示黑色,vbWhite 表示白色,vbYellow 表示黄色,vbCyan
表示青色。
第3章 基本算法和控制结构 91
2.Goto 语句
【格式】 Goto 标号
标号:语句序列
【功能】可以无条件地转到标号(例如:BT)所指示的语句行,标号的右边一定要加冒
号“:”。在程序中应尽量少用 Goto 语句。
3.“求 3 个有趣的整数”程序
【实例】 有 3 个正整数,其和为 23,第 1 个数的两倍、第 2 个数的三倍和第 3 数的五倍三
者的和为 81,第 1 个数与第 2 个数的和的 10 倍减去 3 个数的积除以 2 为−76,编程求这 3 个数。
设第 1、2、3 个数分别为 A、B、C,由题意可知 2*A+3*B+5*C=81,10*(A+B)−A*B*C/2= −76。
解决这类问题可以产生 0 到 23 的数分别赋给 A、B、C,然后按照条件进行筛选,符合条件
的便显示出来。程序如下:
Private Sub Form_Activate()
Dim A, B As Integer
For A = 0 To 23
For B = 0 To 23
C = 23 - A - B '保证 A+B+C=23
If 2*A+3*B+5*C=81 And 10*(A+B)-A*B*C/2=-76 Then
Print "A="; A, "B="; B, "C="; C
End If
Next B
Next A
End Sub
程序运行结果是:A=6 B=8 C=9
4.“猜父子年龄”程序
【实例】 父子二人,已知儿子年龄不大于 90 岁,父亲年龄不大于 100 岁,8 年前父亲年
龄是儿子年龄的 3 倍,8 年后父亲年龄是儿子年龄的整数倍,求父子现在的年龄。
设父、子年龄各为 A、B 岁,8 年前儿子的最小岁数是 1 岁,现在至少为 9 岁,现在父
亲年龄至少 11 岁。由此可设 A 的初值为 11,B 的初值为 9;A 的终值为 100,B 的终值为 90。
程序中的判断式子是:A−8=(B−8)*3 和 Int((A+8)/(B+8))=(A+8)/(B+8),如果该式子成立,则
说明 8 年后父亲年龄是儿子年龄的整数倍。程序如下。
Private Sub Form_Activate()
Dim A, B As Integer
For A = 11 To 100
For B = 9 To 90
If (A-8)=(B-8)*3 And (A+8)/(B+8)=Int((A+8)/(B+8)) Then
Print "父亲现在岁数:"; A, "儿子现在岁数:"; B
End If
Next B
Next A
End Sub
程序运行结果是:父亲现在岁数:56 儿子现在岁数:24
另外,可以采用如下方法来编写程序。
92 中文 Visual Basic 6.0 实用教程—结构化程序设计
3.5 连续自然数的和
[循环体语句序列]
Wend
【功能】当条件成立时,重复执行语句序列,否则,转去执行关键字 Wend 后面的语句。
执行 Wend 语句的作用就是返回到 While 语句去执行。While Wend 语句的功能可参看图 3-5-2
所示的流程图。
【说明】条件实际上是一个表达式,对它的要求与对 If Then Else 语句的要求一样。经常
使用的是关系和逻辑表达式。
2.分析程序的运行结果
【实例 1】程序如下。程序运行结果如图 3-5-1 所示。它的执行过程分析如下(为了说明
方便,给每条语句加上了编号),它的流程图如图 3-5-2 所示。
Private Sub Form_Activate()
1 Dim N, SU As Integer
2 N = 0: SU = 0
3 While N <= 6
4 N = N + 2:SU = SU + N
5 Print SU, N
6 Wend
7 Print "SU="; SU
End Sub
N=0 SU=0
不成立
N<=6?
成立
N=N+2
Print " SU=";SU
SU=SU+N
Print SU, N
Wend
N=10:A=1:B=2:C=3
不成立
N>4?
成立
C=A:A=B:B=C
Print " N=";N
N=N–3
Print A, B, C
Wend
3.5.2 Do Loop 语句
1.当型 Do Loop 语句
【格式】 Do [While|Unitl 条件]
第3章 基本算法和控制结构 95
[循环体语句序列]
Loop
【功能】选关键字 While,当条件成立(其值为 True、非零的数或非零的数字符串)时,
重复执行循环体语句序列的语句;当条件表达式不成立(其值为 False、0 或“0”)时,转去
执行关键字 Loop 后面的语句。它的流程图如图 3-5-5 所示。
选关键字 Unitl,当条件表达式不成立(其值为 False、0 或“0”)时,重复执行循环体语
句序列的语句;当条件成立(其值为 True、非零的数或非零的数字符串)时,转去执行关键
字 Loop 后面的语句。
当型 Do Loop 语句是先判断条件,再执行循环体语句序列中的语句。
【说明】条件实际上是一个表达式,对它的要求与对 If Then Else 语句的要求一样。经常
使用的是关系和逻辑表达式。
在 Do Loop 循环语句的循环体语句序列中可以使用 Exit Do 语句,它的作用是退出该循
环体,它一般用于循环体语句序列中的判断语句。
2.直到型 Do Loop 语句
【格式】 Do
[循环体语句序列]
Loop [While|Unitl 条件]
【功能】与当型 Do Loop 语句的功能基本一样,只是直到型 Do Loop 语句是先执行循环
体语句序列中的语句,再判断条件。它的流程图如图 3-5-6 所示。
Loop
不成立 循环体语句序列
While 条件?
成立 成立
While 条件?
循环体语句序列 Loop 下边的语句
不成立
While 条件下边的语句
Loop
3.5.3 项目实现
图 3-5-7 “连续自然数的和”程序运行的两个画面
96 中文 Visual Basic 6.0 实用教程—结构化程序设计
1.设置对象的属性
在窗体中创建 3 个标签、3 个文本框和两个按钮对象。它们的名称均采用默认值,3 个
标签对象的 Caption 属性分别为:“N=”、“M=”和“计算的结果”,3 个文本框对象的 Text
属性均为 0,两个按钮对象的 Caption 属性分别为: “计算”和“退出”。
2.使用 While Wend 语句的代码程序
Private Sub Command1_Click()
Dim N, M, K As Integer, SUM As Long
N = Text1.Text
M = Text2.Text
SUM = 0 '给变量 SUM 赋初值 0
Rem 可循环 M-N+1 次,每一次循环使变量 N 自动加 1,K 依次取值 N、N+1……M
K=N
While K <= M - N + 1
SUM = SUM + K '累加语句,进行变量 K 的累加运算
K=K+1 '变量 K 自动加 1
Wend
Text3.Text = SUM '显示计算结果
End Sub
Private Sub Command2_Click()
End
End Sub
3.使用 Do Loop 语句的代码程序
下面只给出有关的循环语句程序,其他程序与使用 While Wend 语句编写的程序一样。
K=N
Do While K <= M - N + 1
SUM = SUM + K '累加语句,进行变量 K 的累加运算
K=K+1 '变量 K 自动加 1
Loop
3.5.4 项目拓展
1.“显示裴波纳契数列”程序
【实例】 “裴波纳契数列”程序运行后会显示裴
波纳契数列前 40 个数以及它们的和。裴波纳契数列的
第 1 个数是 0,第 2 个数是 1,以后的数总是前两个数
图 3-5-8 程序的运行结果
的和,因此以后的数是:1,2,3,5,8,13,21,34,
55…程序运行后的画面如图 3-5-8 所示。程序如下。
Private Sub Form_Activate()
Dim N, A, B, K As Integer, SUM As Long, S$
A = 0: B = 1: K = 0: SUM = 0 '给变量 A、B、K,SUM 赋初值
For N = 1 To 20
第3章 基本算法和控制结构 97
程序运行中,前 4 次循环中,循环次数(序号)
、变量 K 的值、式子 5+K * 16 和 21+K *
16 的取值变化如表 3-5-1 所示。
表 3-5-1 程序运行中各有关项的取值变化
1 0 5 21 3 0 5 21
2 2 37 53 4 2 37 53
2.“求 2!+4!+…+10!的值”程序
使用 While Wend 语句编写的程序如下。程序运行结果为 2!+4!+…+10!=3669866。
Private Sub Form_Activate()
Dim I, J As Integer, N, SUM As Long
SUM = 0: I = 2 '给变量赋初值
FontSize = 10 '设置窗体中文字的大小
ForeColor =vbblue '设置窗体中文字的颜色为蓝色
While I <= 10 '产生 2 到 10 的偶数
J = 1: N = 1 '给变量赋初值
While J <= I '求偶数的阶乘
N=N*J '进行累积运算
J=J+1 '变量 I 自动加 1
Wend
SUM = SUM + N '进行阶乘的累加
I=I+2 '变量 J 自动加 2
Wend
Print "2!+4!+…+10!="; SUM '显示计算结果
End S
思考与练习
1.填空题
(1)算法是 。常见算法的描述方法有 、 和 。
98 中文 Visual Basic 6.0 实用教程—结构化程序设计
(2)算法具有 、 、 、 和 5 个重要特性。
(3)算法的控制结构有 、 和 三种。
(4)选择结构中的“条件”是指 、 、 和 四种表达式。
(5)循环语句的嵌套需注意 、 和 。
(6)流程图是一种用 来表示算法的描述方法。
(7)N-S 图是一种描述算法的 方法。N-S 图形方法完全去掉了 ,全部
算法写在一个 内。
(8)PAD 是英文 Problem Analysis Diagram 的缩写,其原意是 。它是近年来在软
件开发中被推广使用的一种描述算法的 方法。它是一种 图形,从 各
框功能顺序执行,从左到右表示 关系。这种算法的优点是: 和 ,
以及 。
(9)当型 Do Loop 语句和直到型 Do Loop 语句的区别是 。
2.下面程序运行后的结果是什么?
(1)程序如下:
Private Sub Form_Activate()
If "AC">="ABC" Then Print "1" Else Print "2"
If 7 Mod 2=1 And Int(18/2)= 18/2 Then Print "1" Else Print "2"
If 7 Mod 3-Int(7/5) Then Print "1" Else Print "2"
If 5>=5 Then Print "1" Else Print "2"
If "0" Then Print "1" Else Print "2"
End Sub
(2)程序如下:
Private Sub Form_Activate()
Dim FS As Integer
FS = InputBox("请输入物体重量的公斤数:")
If FS >= 30 Then
Print "超重!超重部分需补交运费"
Else
Print "没超重!不用补交交运费!"
End If
End Sub
(3)程序如下,分别写出各小题程序的运行结果。
第3章 基本算法和控制结构 99
Rem 第 5 小题 Rem 第 8 小题
For K=1 To 5 I=3:SUM=0
Print Tab(30-K); While I<=10
For L=1 TO 2*K-1 I=I+2
Print "*"; SUM = SUM + I
Next L:Print Print I,
Next K Wend
Rem 第 6 小题 Print "I=";I
Rem 第 9 小题
For K=1 To 7
K=1:L=1
Print Tab(30+K);
While K<=6
For L=1 TO 2*(6-K)-1
While L<=K
Print Chr(64+K);
Print K,L:L=L+2
Next L
Wend
Print
K=K+2
Next K
Wend
Rem 第 7 小题 Print K,L
For N1=1 To 10 Step 2 Rem 第 10 小题
For N2 = 6 TO 1 Step -2 A=1:B=3:I=5
If N1=N2 Then Exit For Do
Print N1,N2 C=A:A=B:B=C:Print A,B,C
Next N2 I=I-2
Print Loop Until I<=0
Next N1 Print A,B,C
(4)程序如下:
Private Sub Command3_Click()
Dim N, A, B, C As Integer
N = Val(InputBox("输入数:")): Label1.Caption = N
A = 10: B = 20: C = 30:Cls
Select Case N
Case 1 + 2 To 10 - 2
Print "1"
Case 5, 7, 9
Print "2"
Case Val("A") + 10
Print "3"
Case A, B, C, C + B - A
Print "4"
Case A To B
Print "5"
Case Is > 100
Print "6"
Case A + 5, C - 5, 70 To 80, Is <= 0
Print "7"
Case Else
第3章 基本算法和控制结构 101
Print "无符合的数据!"
End Select
End Sub
3.输入一个学生成绩,当该数大于或等于 90 时,显示“优秀! ”再换行显示“您的成
绩很优秀,请您来学校领取奖状”;当该数大于或等于 60 且小于 90 时,显示“及格!
”再换
行显示“您的成绩是”和分数;当该数小于 60 时,显示“不及格!”再换行显示“请您在开
学后来学校补考!”
4.由键盘输入 A、B、C 三个数,然后将其中最大和最小的数显示出来。
5.由键盘输入 A、B、C 三个数,然后将它们按照从小到大的顺序显示出来。
6.由键盘输入一个数 X,求下面分段函数的值。采用两种以上的方法。
⎧2 X − 1 (X<−10)
⎪ 2
⎪3 X + 5 X − 1 (−10≤X<0)
⎪
Y = ⎨ X 2 − 100 (0≤X≤5)
⎪ (5<X<10)
⎪sin(5 X + 7)
⎪3 X 3 − 2 X 2 − X + 1 (X≥10)
⎩
7.将度、分、秒的角度值换算为弧度值。设度、分、秒分别用变量 A、B、C 表示,则
其弧度值 D=(A+B/60+C/3600)*3.1415926/180。输入的度、分、秒的角度值应是小数形式。例
如,68 度 32 分 45 秒输入的数据是 68.3245。
8.由键盘输入 A、B、C 三个正数,如果以 A、B、C 为边长可以构成一个三角形,则
显示“可以组成一个三角形”文字,并显示它的周长和面积,否则显示“不可以构成一个三
角形”文字。如果是直角三角形,需显示“这是一个直角三角形” 。三条边只要符合任两边之
和大于第三边的条件,就可以构成一个三角形。如果三角形三边符合勾股定理,则是直角三
角形。
9.在一个文本框中输入英文字母(有大写和小写的英文字母)。然后,单击“小写”按
钮,即可在另一个文本框中复制第 1 个文本框中输入的英文字母,同时将大写英文字母全部
转换为小写英文字母。单击“大写”按钮,可将第 1 个文本框中输入的英文字母移到另一个
文本框中,同时将小写英文字母全部转换为大写英文字母。
10.显示 1 到 1000 之间的所有偶数的和,以及显示 1 到 1 000 之间的所有奇数的和。
11.编写程序,计算 1!+(1!+2!)+…+(1!+2!+…+7!)的值。
12.编写程序,计算 1!+(1!+3!)+…+(1!+3!+…+9!)的值。
13.编写程序,计算 1!−2!+3!−4!+…+9!–10!的值。
14.求 3+33+333+…+333333333 的值。
15.显示 32 个随机数,按照一行 8 个数字来显示,同时显示数字出现的序号。然后,
将这组数字中最大和最小的数字显示出来,并显示它们第一次出现的序号。
16.以每行显示 6 个数的形式显示裴波纳契数列中前 40 个数以及它们的和。
17.以每行显示 5 个数的形式显示裴波纳契数列中前 40 个数以及它们的和。
18.使用 While Wend 语句和 Do Loop 语句编写“九九乘法表”程序。
19.使用 For Next 语句编写“连续自然数的和”程序。
102 中文 Visual Basic 6.0 实用教程—结构化程序设计
4.1.1 算法分析
程序设计人员总希望能够设计出一个好的算法。一个好的算法应具有正确性、可读性、
键壮性、易测试性、可移植性和运行效率高等性能。在一个算法编出来之后,主要应从以下
几个方面进行算法性能的评估。
1.算法的正确性和可读性
(1)算法的正确性:被评估的算法首先应该是正确的。正确的算法应该能够完成预定的
任务,达到设计的要求。当输入一组合理的数据时,能够在有限的时间内得到正确的结果。
算法的正确性是算法评估的前提,是评估算法中最基本和最重要的特性。
对于一些算法,只能够验证算法是否有错,不能证明算法是否无错,也就是说只要找出
一组数据使算法的计算结果不正确,就能证明该算法是错误的。但要验证算法的正确性,应
当对所有合法的输入数据都能得到应该得到的结果。要想验证这一点有时是很困难的,输入
所有不同数据的数量是非常大的,逐一验证所有的数据有时很难现实。因此,即使算法有错
误,也不一定能在短时间内发现。
(2)算法的可读性:算法不仅能够保证计算机的正确运行,而且还要供其他人阅读和进
行交流。因此,算法应具有可读性好的特点,这样有助于人们对算法的理解。可读性差的程
序难以测试和修改,同时容易隐藏较多的错误。
2.算法的易测试性和健壮性
(1)算法的易测试性:为了验证算法的正确性,需要用若干组数据进行调试。测试用的
数据应是典型的和有代表性的输入数据,从而可以保证算法对“所有的”数据的正确性。有
时,可以通过验证程序来替代人工的数据输入,完成算法正确性的验证。对于一种算法,还
应该考虑在进行测试时,它的测试数据应比较好输入,相应的测试程序应比较容易制作。
(2)算法的健壮性:当输入的数据是非法时,算法也能作出相应的反应或进行相应的处
理,而不会产生莫明其妙的输出结果。
3.算法的运行效率
一个算法的运行效率同样包括运行时间、存储器效率和输入/输出效率 3 个方面,一般
算法的运行效率主要是指其对时间和空间的需求,也就是要估计一下按算法编制的程序在
计算机上执行所耗费时间和所占用的内存空间。一个好的算法应尽量少占用存储空间,同
第4章 优化算法和程序设计方法 103
时又具有尽量快的数据处理速度。对于同一个问题如果有多个算法可以解决,执行速度快
的算法时间效率高,占用空间少的算法空间效率高。当然二者都与问题的规模有关,对于
在 10 个数据中进行选择和在 1000 个数据中进行选择,执行程序所用的时间和占用的内存
空间显然是不一样的。
在上述的几个方面中,评价算法性能最主要的是算法的正确性和算法的运行效率。而在
实际进行算法分析时,分析算法的运行效率一般只讨论算法的时间效率。
4.1.2 算法的时间复杂度和空间复杂度
1.算法的时间复杂度
算法的执行时间是通过依据该算法所编制的程序在计算机上运行所消耗的时间来度量
的。一个用高级程序语言编写的程序在计算机上运行时所消耗的时间与下列要素有关。
① 问题的规模,显示 100 以内的裴波纳契数列数和显示 10 000 以内的裴波纳契数列数,
显然问题的规模是不一样的,所用的算法的执行时间是不一样的。
② 程序中语句的执行次数。
③ 所用程序设计语言的执行效率。
④ 编译程序所产生的机器代码质量,计算机执行指令的速度。
显然,同一个算法用不同语言来实现,或者使用不同的编译系统,或者在不同的计算机
上运行,所用时间均不相同。这表明用绝对的时间单位衡量算法的效率是不合适的。因而,
不应考虑第 3 和第 4 这两个与计算机系统的软件和硬件有关的因素,应只考虑第 1 和第 2 这
两个要素。
通常的作法是把算法中语句的执行次数作为算法时间多少的量度,因为比较同一问题间
两个不同算法中语句的执行次数,就可得到两个算法的运行时间长短的一个相对的数量概念。
显然,相同的语句执行次数较少的算法是时间效率较好的算法。
如果将算法中某一条语句的执行次数设定为该语句的频度,那么整个算法的频度是指算
法中所有语句频度的和。这种把语句执行次数的多少作为算法时间量度的分析方法称为频度
统计法。语句的执行次数还与问题的规模有关,例如,计算 100 个数的和,还是计算 10 000
个数的和,累加的语句则分别执行了 100 次和 10 000 次。所以,算法中基本操作的重复执行
次数是问题规模 n 的某个函数 F(n),算法的时间量度表示为:T(n)=O(F(n))。
随着问题规模 n 的增大,算法执行时间的增长情况与 F(n)的增长情况相同。这时称 T(n)
为算法时间复杂度。例如,在下面的三段程序中,执行 SUM=SUM+X 语句的次数分别是 1
次、n 次和 n2 次,它们的的时间复杂度分别为 O(1)、O(n)和 O(n2)。
Rem 程序 1
SUM=SUM+X
Rem 程序 2
For X=1 To n
SUM=SUM+X
Next X
Rem 程序 3
For I=1 To n
For X=1 To n
104 中文 Visual Basic 6.0 实用教程—结构化程序设计
SUM=SUM+X
Next X
Next I
根据算法的时间复杂度,可以大致预期算法的运算效率。通常,时间复杂度与问题规模
n 的几次方成正比,其算法的运算时间还可以忍受。如果时间复杂度与问题规模 n 的指数成
正比,其算法的运行时间将会极大地增加,甚至长得无法忍受,此时的算法可视为无法实现。
2.算法的空间复杂度
空间复杂度的概念类似于算法的时间复杂度,它是指在算法中所需的辅助存储空间,不
包括问题原始数据所占用的内存空间。空间复杂度可表示为:S(n)=O(F(n))
其中 n 为问题规模的大小,F(n)表示该算法处理的数据所需的存储空间与算法操作所需
的辅助存储空间用量之和。在设计算法时,有时为了节省时间而多使用一些辅助变量(主要
是数组)。这种做法实质是“牺牲空间,换取时间”。
在进行算法分析时,一般只讨论算法的时间效率。
4.1.3 项目实现
A1 = A: B1 = B: C1 = C: D1 = D: S = A + B + C + D
End If
BT: Next D
Next C
Next B
Next A
Print: Print A1,B1,C1,D1, A1+B1+C1+D1 '显示符合条件的 4 个自然数,以及它们的和
End Sub
程序的运行结果如图 4-1-1 所示。
2.程序2
为了提高算法的效率,可以按照如下方法改
图 4-1-1 程序的运行结果
进程序,这样可以大大缩小程序运行的时间,使
算法的时间复杂度大大减小。仍然采用 4 个循环来分别产生 4 个自然数,只是循环变量的
初值和终止进行了改变。考虑到 4 个自然数相互不相等,所以最外层的循环变量的初值为 1,
终止为 10(已经足够了),其他循环变量的终止分别为 14、22 和 41。考虑到 4 个自然数两
两的和为偶数,则 4 个自然数肯定同时为奇数或为偶数,因此内层的 3 个循环的步长值为 2,
初值是相邻的外循环变量加 2。修改后的程序如下。
Dim A, B, C, D, S As Integer
Dim A1, B1, C1, D1, S1 As Integer
Private Sub Form_Activate()
S = 50
For A = 1 To 10
For B = A + 2 To 14 Step 2
For C = B + 2 To 22 Step 2
For D = C + 2 To 41 Step 2
Rem 自然数的和小于 50
If A + B + C + D > 50 Then GoTo BT
Rem 各自然数之间都互不相等
If A = B Or A = C Or A = D Or B = C Or B = D Or C = D Then GoTo BT
Rem 各自然数中任意两个自然数的和为偶数
If (A + B) Mod 2 = 1 Or (A + C) Mod 2 = 1 Or (A + D) Mod 2 = 1 Then GoTo BT
If (B + C) Mod 2 = 1 Or (B + D) Mod 2 = 1 Or (C + D) Mod 2 = 1 Then GoTo BT
Rem 任意 3 个自然数之和可以被 3 整除
If (A+B+C) Mod 3 <> 0 Or (A+B+D) Mod 3 <> 0 Or (B+C+D) Mod 3 <> 0 Then GoTo BT
Rem 将最小的一组符合条件的自然数和它们的和保存在相应的变量中
If A + B + C + D < S Then
A1 = A: B1 = B: C1 = C: D1 = D: S = A + B + C + D
End If
BT: Next D
Next C
Next B
Next A
Print: Print A1,B1,C1,D1,A1+B1+C1+D1 '显示符合条件的 4 个自然数,以及它们的和
End Sub
106 中文 Visual Basic 6.0 实用教程—结构化程序设计
运行这两个程序,会发现,后一个程序的运行时间大大小于第一个程序的运行时间。如
果将该题目中的“各自然数的和小于 50”改为“各自然数的和小于 100”,则上述两个程序的
运行时间会相差更大了。从而可以体会出不同算法具有不同的运行效率。
3.程序设计的工作流程
当用计算机解决一个具体问题时,通常采用如下的工作流程。
① 首先分析具体的问题,建立对该问题的数学模型;
② 然后根据具体的问题,利用数学模型设计相应的算法;
③ 再编写程序,调试程序和运行程序,有时需要反复进行,直到解决问题。
建立数学模型是非常重要的工作,通过分析问题,从中了解问题的规律,找出解决问题
的关键要素,找出这些要素之间的关系,用数学语言加以描述。一个数学模型建立的正确与
否和质量的高低,是编写解题程序的重要的前提。
4.1.4 项目拓展
1.获取自然数中每位数字的方法
在程序设计当中,常需要将一个自然数中的个位、百位、千位和万位的数字提取出来。
可以采用下述两种方法。
(1)用多层循环分别创建每位数字,最外层循环变量的取值范围为 1~9(产生自然数的
最高位数),其他内循环变量的取值范围为 0~9。再由这些数字组成一个多位的自然数。例
如,创建个位数赋给变量 D,十位数赋给变量 C,百位数赋给变量 B,千位数赋给变量 A,
然后由它们合成四位自然数并赋给变量 S,可以使用如下程序。
For A = 1 To 9
For B = 0 To 9
For C = 0 To 9
For D = 0 To 9
S = A * 1000 + B * 100 + C * 10 + D '合成四位自然数
Next D
Next C
Next B
Next A
(2)使用一个循环来产生自然数,然后再从中截取出各位数字。例如,创建各种四位
自然数并赋给变量 S,同时将该自然数的个位数取出来并赋给变量 D,十位数取出来并赋
给变量 C,百位数取出来并赋给变量 B,千位数取出来并赋给变量 A,可以使用如下程序。
For S = 1000 To 9999
A = Int(S / 1000) '截取四位自然数的千位数
B = Int((S - A * 1000) / 100) '截取四位自然数的百位数
C = Int((S - A * 1000 - B * 100) / 10) '截取四位自然数的十位数
D = S - A * 1000 - B * 100 - C * 10 '截取四位自然数的个位数
Print S, A, B, C, D
Next S
截取各位数字还可以使用语句:D = S - Int(S / 10) * 10 。
2.“求特殊的三位数”程序
第4章 优化算法和程序设计方法 107
【实例】 编写程序,找出等于它的每位数立方和的三
位自然数。按照上面所述方法,可以编写以下两种解决问
图 4-1-2 程序的运行结果
题的程序。程序的运行结果如图 4-1-2 所示。
(1)程序 1 如下。该程序采用一个循环来产生自然数,然后再从中截取出各位数字。变
量 A 保存百位数,变量 B 保存十位数,变量 C 保存个位数,变量 S 保存三位自然数。
Dim S, A, B, C As Integer
Private Sub Form_Activate()
For S = 100 To 999
A = Int(S / 100): B = Int((S - A * 100) / 10): C = S - A * 100 - B * 10
If A * A * A + B * B * B + C * C * C = S Then
Print S,
End If
Next S
End Sub
(2)程序 2 如下。该程序采用三层循环分别创建每位数字,变量 A 保存百位数,变量 B
保存十位数,变量 C 保存个位数。然后由它们合成三位自然数并赋给变量 S。
Dim S, A, B, C As Integer
Private Sub Form_Activate()
For A = 1 To 9
For B = 0 To 9
For C = 0 To 9
S = A * 100 + B * 10 + C '合成三位自然数
If A * A * A + B * B * B + C * C * C = S Then
Print S,
End If
Next C
Next B
Next A
End Sub
3.求特殊的四位数
编写程序,找出前两位数与后两位数的和的平方正好等于
该四位自然数。例如,2025,20+25=45,45 的平方等于 2025。
程序的运行结果如图 4-1-3 所示。
利用一个循环产生 32~99 之间的所有自然数,求出它的平 图 4-1-3 程序的运行结果
4.2 解不定方程式
本节将通过大量的实例,使读者能够正确使用穷举法求解问题,并学会优化算法,提高
算法的效率。
4.2.1 利用计算机解决问题的几个阶段
利用计算机解决问题时,可以按照如下几个阶段来进行。最关键的是寻找适合的解题方
法,即解决问题的算法,因此设计算法是利用计算机解决问题的关键性阶段。
(1)分析问题,了解需求;
(2)建立数学模型,用表达式清楚地描述各种数量之间的相互关系;
(3)设计算法,选择最适于解决问题的方法,如穷举法、递推法和递归法等;
(4)进行算法正确性的分析;
(5)进行算法效率分析,尤其是进行时间复杂度分析;
(6)算法的实现,选择一种效率好的程序设计语言,编写相应的程序;
(7)进行程序的调试和测试,排除程序中的错误;
(8)编写相应的文档资料,为算法的完善和修改作准备。
本书中已经介绍过一些常用的算法设计方法,以后还将不断介绍各种常用的算法设计方法。
4.2.2 穷举法
1.什么是穷举法
穷举法也叫穷举搜索法或叫枚举法,它是最基础的算法设计方法,具有很广泛的通用性。
其基本思想是对可能是解的众多候选解,根据问题所要求的条件,按某种顺序逐一判断每一
个候选解,并从中找出那些符合要求的候选解作为问题的正确解。这种方法的特点是最大限
度地考虑了各种情况,从而为求出解创造了条件。
这种列举所有可能性的方式,对于人工求解过程是不适当的,但对于计算机来说,因为
计算机运算速度快,所以是可行的。在穷举过程中,通常需要使用循环和判断的操作。
在前面介绍的一些实例中已经采用过穷举法编写程序,例如上一节中的各个实例。
2.缩小穷举范围
尽管计算机速度很快,但还是有必要优化算法,以便最大限度地降低算法的时间复杂
度,提高算法的效率。通常,可以从如下几个方面对算法的操作进行优化处理,缩小穷举
范围。
① 减少循环嵌套的层数,能用一重循环完成的操用,就不用二重循环;
② 缩短每次循环的起止范围,减少循环体的执行次数;
第4章 优化算法和程序设计方法 109
③ 将循环体内的与循环控制变量无关的计算,提到循环体之前完成;
④ 采用变步长技术,减少循环体执行的次数,减少判断次数;
⑤ 根据问题的要求,正确选择数据的类型,这样可以在减少内存占用量的同时,还能
减少计算机的运行时间。
3.穷举法常用的列举方法
使用穷举法解决问题时,正确解(即答案)所在的范围应是有限的。如何才能不重复、
一个不漏、一个不增地逐一列举出可行解,这需要确定列举方法。通常采用的列举方法有顺
序列举方法、排列列举方法和组合列举方法。
(1)顺序列举方法:它是指穷举范围内的各种可行解很容易与自然数一一对应,甚至就是
自然数。因此可以按照自然数的变化顺序一一列举。例如:将两位正整数中的偶数显示出来。
(2)排列列举方法:它是指穷举范围内的各种可行解的数据形式是一组元素的排列,排
列是区分前后次序的。例如,显示出由 1、2、3 三个数字组成的每位数字均不相同的三位数,
有 123、132、213、231、312、321 六种排列。
(3)组合列举方法:它是指穷举范围内的各种可行解的数据形式是一些元素的组合,列
举所有可行解所在范围内的组合。从 n 个不同元素中取出 m(m<=n)个元素组成的一组,就叫
从 n 个不同元素中取出 m 个元素的组合。注意,组合是无序的,它与元素的排列次序无关。
例如,显示出由 1、2、3 三个数字组成的每位数字均不相同的组合只有一个 123。再例如,
从 A、B、C 三个字母中选出两个字母的组合有 AB、AC、BC 三组。
4.2.3 项目实现
⎧5 * A + 3 * B + C / 3 = 100
⎨
⎩A + B + C = 100
1.程序1
由不定方程中的第 2 个式子可以看出,变量 A、B、C 的取值范围均可以是 1 到 100 之
间的正整数。由不定方程中的第 1 个式子可以看出,变量 A 的取值为是 1~19 之间的正整数,
变量 B 的取值为是 1~32 之间的正整数,变量 C 的取值为是 1~99 之间的正整数。使用 3 个
循环来产生变量 A、B、C 的可能取值,带到不定方程的两个式子中进行检验,可以使两个
110 中文 Visual Basic 6.0 实用教程—结构化程序设计
式子均成立的即为不定方程的解。设计的程序如下。程序的
图 4-2-1 程序的运行结果 运行结果如图 4-2-1 所示。
Dim A, B, C, N As Integer
Private Sub Form_Activate()
For A = 1 To 19
For B = 1 To 32
For C = 1 To 99
If 5 * A + 3 * B + C / 3 = 100 And A + B + C = 100 Then
N=N+1
Print "第"; N; "组解:"; "公鸡:";A;"只", "母鸡:";B;"只", "小鸡:";C;"只"
End If
Next C
Next B
Next A
End Sub
2.程序2
变量 C 的取值不再使用循环语句,改为 C=100−A−B。采用这种方法编写的程序,可以
减少一层循环,使算法的运行效率提高,运行时间减少。程序如下。
Dim A, B, N As Integer
Private Sub Form_Activate()
For A = 1 To 19
For B = 1 To 32
C = 100 - A - B
If 5 * A + 3 * B + C / 3 = 100 And A + B + C = 100 Then
N=N+1
Print "第"; N; "组解:"; "公鸡:";A;"只", "母鸡:";B;"只", "小鸡:";C;"只"
End If
Next B
Next A
End Sub
3.程序3
根据题意,还可以获得:B=(100−7*A)/4,因此可以只是用一个循环语句来列举变量 A
的取值可能性,再由 B=(100−7*A)/4 和 C=100−A−B 来产生变量 B 和 C 的取值可能性。但是,
这时需要检验变量 B 和 C 是否是正整数。程序如下。
Dim A, B, N As Integer
Private Sub Form_Activate()
For A = 1 To 19
B = (100 - 7 * A) / 4
C = 100 - A - B
If 5*A+3*B+C/3=100 And A+B+C=100 And Int(B)=B And Int(C)=C And B>0 And C>0 Then
N=N+1
Print "第"; N;"组解:"; "公鸡:"; A;"只", "母鸡:"; B;"只", "小鸡:"; C;"只"
End If
Next A
第4章 优化算法和程序设计方法 111
End Sub
4.2.4 项目拓展
1.
“选出特殊学号的学生”程序
【实例】 某校初三(1)班有学生 48 人,学号分别为 1~48,将他们分为 6 个小组,每
组 8 人。将学号是组号整数倍的学生挑选出来。下面介绍两种编写的程序。
(1)程序 1:按组内的编号来列举学生,即
第 1 组第 1 个、第 1 组第 2 个……第 1 组第 8 个。
每个学生的学号可以根据组号和在组内编号获
得,即学号等于“ (组号−1)*8+组内编号” 。设计
图 4-2-2 程序的运行结果
的程序如下。程序的运行结果如图 4-2-2 所示。
Dim K, L, N, S As Integer
Private Sub Form_Activate()
For K = 1 To 6 '变量 K 保存组号
For L = 1 To 8 '变量 L 保存组内编号
N = (K - 1) * 8 + L '变量 N 保存学号
If Int(N / K) = N / K Then '进行条件判断,判断 N 除以 K 是否为整数
Print N, '显示符合条件的学号
S=S+1 '用来控制一行显示 6 个符合条件的学号
If Int(S / 6) = S / 6 Then Print '进行判断
End If
Next L
Next K
End Sub
(2)程序 2:按照学号从 1~48 来列举学生,组号=Int((学号−1)/8)+1,组内编号=学号−(组
号−1)*8。设计的程序如下。
Dim N, S, L As Integer
Private Sub Form_Activate()
For N = 1 To 48 '变量 N 保存学号
L = Int((N - 1) / 8) + 1 '变量 L 保存组内编号
If Int(N / L) = N / L Then '进行条件判断,判断 N 除以 K 是否为整数
Print N, '显示符合条件的学号
S=S+1 '用来控制一行显示 6 个符合条件的学号
If Int(S / 6) = S / 6 Then Print '进行判断
End If
Next N
End Sub
2.“列出前三名”程序
【实例】 四名羽毛球运动员争夺单打前三名(没有并列)的可能性有哪些种?设四名羽
毛球运动员分别为 A、B、C、D,夺取单打前三名的一种可能是 ABC,即 A 运动员获冠军,
B 运动员获亚军,C 运动员获第三名。
该题目是一个排列问题,应采用排列列举方法,注意它是有序的。程序中,变量 I、J、
112 中文 Visual Basic 6.0 实用教程—结构化程序设计
Dim I, J, K, S As Integer
Private Sub Form_Activate()
For I = 1 To 4
For J = I + 1 To 5
For K = J + 1 To 6
If I <> J And I <> K And J <> K And K <> L Then
Print Chr$(64 + I); "-"; Chr$(64 + J); "-"; Chr$(64 + K),
S=S+1
If Int(S / 5) = S / 5 Then Print
End If
第4章 优化算法和程序设计方法 113
Next K
Next J
Next I
End Sub
4.3.1 素数特点和有关的定律
1.素数特点
素数也叫质数,所谓素数就是除了 1 和该数本身之外,再不能被其他任何整数整除的自
然数。求素数的算法很多,最简单的方法是根据素数的定义来求:对于自然数 N,用大于 1
且小于 N 的各个自然数一一去除 N,若都除不尽,则可判定 N 是素数。
2.素数的数学定律
求素数还可根据数学定律,提高求素数的速度。素数的数学定律如下:
(1)自然数中只有一个偶数 2 是素数;
(2)不能被从 2 至 N−1 的各自然数整除,也一定不能被从 2 至 N 的平方根的各自然数整
除的数。
3.哥德巴赫猜想的有关命题
(1)哥德巴赫猜想的一个命题是:任何一个大于 2 的偶数都是两个素数的和。例如:
4=2+2,8=3+5,10=3+7。
(2)哥德巴赫猜想的另一个命题是:任何一个大于 7 的奇数都是三个素数的和。例如:
9=3+3+3,15=3+5+7,21=3+5+13。
4.素数因数
任意一个大于 1 的正整数都可以表示为几个素数的乘积(这些素数就叫素因数),如果
不考虑各素数因数的顺序,则这种表示是惟一的。数学上,通常将一个大于 1 的正整数分解
为若干素数的乘积所采用的方法如下。
(1)以 140 为例:将 140 分解素数因数的方法是用 140 除以最小的素数 2,可以整除;
再用其商 70 除以最小的素数 2,可以整除;再用其商 35 除以最小的素数 2,不能整除,
再用其商 35 除以稍大的素数 3,也不能整除,再用其商 35 除以稍大的素数 5,可以整除,
商 7 。如此不断计算,直到商为 1 时为止,如图 4-3-1 所示。 140 分解为素因数后,
140=2*2*5*7。
图 4-3-2 45 分解素数因数的方法
4.3.2 项目实现
4.3.3 项目拓展
1.求素数和程序的优化
根据素数的数学定律,可以将上边的程序进行优化,使其运行所用的时间大大减少。优
化的方法,就是改变两个循环的终值。修改的程序如下。
For N = 3 To 300 Step 2 '产生 3 到 300 之间的所有奇数,赋给变量 N
For S = 2 To Sqr(N) '依次用 N 除以 2 到 N 的平方根之间的自然数
2.“哥德巴赫猜想命题 1 的验证”程序
【实例】 编写可以验证哥德巴赫猜想的第一个命题(任何一个大于 2 的偶数都是两个素数
的和,例如:4=2+2,8=3+5)
。编程思路:将键盘输入一个大于 2 的偶数赋给变量 N,选择最
小的素数 2 作为第一个加数 A,再判断第二个加数 K=N−A 是否为素数,如果 K 是素数则显示
结果;如果 K 不是素数,则再继续选择稍大的素数作为第一个加数 A, 再判断第二个加数 K=N−A
是否为素数……直到找出两个符合要求的素数为止。该程序如下。程序运行结果如图 4-3-4 所示。
图 4-3-4 程序的运行结果
4.4 两个数的最大公约数与最小公倍数
4.4.1 最大公约数的求解方法
约数也叫因数,最大公约数也叫最大公因数。最大公约数的定义是:设 A 与 B 是不为零
的整数,若 C 是 A 与 B 的约数,则 C 叫 A 与 B 的公约数,公约数中最大的叫最大公约数。
对于多个数的最大公约数,如果公约 C 是它们所有公约数中最大的一个,则 C 就是它们的最
大公约数。
1.求两个数的最大公约数的方法
求两个数的最大公约数的方法有如下两种。
(1)方法一(根据定义的求法):找到两个数 A、B 中最小的数(假定是 A),用 A、A−1、
A−2……等数依次去除 A、B 两数,当能同时整除 A 与 B 时,则该除数就是 A、B 两数的最
大公约数。
(2)方法二(辗转相除法):设两个数为 A、B,则用 A 除以 B(可以 A>B 或 A<B),以
后按下述步骤进行:A/B→商 S1,余 R1
B/R1→商 S2,余 R2
R1/R2→商 S3,余 R3
…………
Rn/Rn+1→商 S3,余 0
当余数为 0 时,则这次的除数 Rn+1 为最大公约数。
例如:求 1024 与 160 的最大公约数可按照下述步骤进行:
160/1024→商 0,余 160
第4章 优化算法和程序设计方法 117
1024/160→商 6,余 64
160/64→商 2,余 32
64/32→商 2,余 0
则 32 就是 1024 与 160 的最大公约数。
2.求多个数的最大公约数的方法
求多个数的最大公约数有如下两种方法。
(1)方法一(根据定义的求法):找到这些数中最小的数(假定是 A),用 A、A−1、A−2……
等数依次去除各个数,当能同时整除所有数时,则该除数就是这些数的最大公约数。
(2)方法二:先求两个数的最大公约数 C1,再求 C1 与下一个数的最大公约数 C2,如
此继续下去,则最后一次求出的最大公约数就是所有数的最大公约数。
4.4.2 最小公倍数的求解方法
若干数均能被某个数整除,则该数是这若干数的公倍数,所有公倍数中最小的公倍数,
是这若干数的最小公倍数。
1.求两个数的最小公倍数的方法
(1)方法一(根据定义的方法):找出两个数中最大的一个数赋给变量 L,用 L 的 1 倍、
2 倍……的数分别除以另一个数,如果 N 倍的 L 能整除另外一个数,则 N 倍的 L 就是这两个
数的最小公倍数。
(2)方法二:两个数 A、B 的最小公倍数等于这两个数的乘积 A*B,再除以这两个数的
最大公约数 Q,即最小公倍数等于 A*B/Q。
2.求多个数的最小公倍数的方法
(1)方法一(根据定义的方法):找出多个数中最大的一个数赋给变量 L,用 L 的 1 倍、
2 倍……的数分别除以其他数,如果 N 倍的 L 能整除所有数,则 N 倍的 L 就是这若干数的最
小公倍数。
(2)方法二:对于 n 个数,可先求其中两个数的最小公倍数 S1,再求 S1 与第三个数的
最小公倍数 S2,再求 S2 与第四个数的最小公倍数 S3……直至求 Sn-2 与第 n 个数的最小公
倍数 S。则 S 就是这 n 个数的最小公倍数。
4.4.3 项目实现
图 4-4-1 “求两个数的最大公约数和最小公倍数”程序的运行结果
4.4.4 项目拓展
1.使用定义的方法编写程序
【实例】 使用定义的方法编写“两个数的最大公约数和最小公倍数”程序。该程序运行
后的画面如图 4-4-1 所示。设计的程序如下。
Private Sub Command1_Click()
Dim A, B, R, P, Q As Integer, S As Long
A = Val(Text1.Text)
B = Val(Text2.Text)
Rem 求 A 和 B 的最大公约数 Q
If A > B Then H = A: A = B: B = H '使变量 A 的值小于变量 B 的值
For I = A To 1 Step -1
Rem '如果 A 和 B 都可以整除以 I,则 I 的值为 A 和 B 的最大公约数 Q
If Int(A / I) = A / I And Int(B / I) = B / I Then Q = I: Exit For
Next I
Rem 求 A 和 B 的最小公倍数 S
For I = B To A * B
Rem 如果 I 可以同时整除以 B 和 A,则 I 的值为 A 和 B 的最小公倍数 S
If Int(I / B) = I / B And Int(I / A) = I / A Then S = I: Exit For
Next I
Label5.Caption = Q '最大公因数赋标签 Label5
第4章 优化算法和程序设计方法 119
2.“求三个数的最大公约数和最小公倍数”程序
【实例】 “三个数的最大公约数和最小公倍数”程序运行后的画面如图 4-4-2 左图所示。
在三个文本框中输入三个数字后,单击“计算”按钮,即可算出这三个数的最大公约数和最
小公倍数,如图 4-4-2 右图所示。
图 4-4-2 “三个数的最大公约数和最小公倍数”程序运行结果
4.5 字符三角形图案
1.Str函数
【格式】Str(number)或 Str$(number)
【功能】计算数值表达式 number 的值,再将 number 的数值转换为字符串。当一数字转
成字符串时,总会在前头保留一空位来表示正负(正数时,数字前边有一个前导空格,表示
有 一 正 号 ), 如 果 number>0 , 则 返 回 的 字 符 串 中 包 含 一 个 前 导 空 格 。 例 如 :
Str$(−12345)="−12345",Str(12345)=" 12345" 。
注意:Str 函数只视句点(.)为有效的小数点。如果使用不同的小数点(例如:国际性的应
用程序),可使用 CStr 将数字转成字符串。
2.Format函数
【格式】Format (number)或 Format $(number)
【功能】计算数值表达式 number 的值,再将 number 的数值转换为字符串。使用 Format
函数可将数值转成必要的格式,如日期、时间、货币或其他用户自定义格式。与 Str 函数不
同之处是,Format 函数不包含数值的前导空格或负号。
4.5.2 项目实现
图 4-5-1 程序运行后的起始画面
1.窗体内对象的设置
“字符三角形图案”程序的窗体中有 1 个窗体和 3 个按钮对象控件,读者可以参考图 4-5-1
所示,自行设计各个对象控件的属性。注意:各按钮的名称均采用默认值,“输入行数”按钮
的名称为 Command1;“字符三角形图案”按钮的名称为 Command2,它的 Enabled 属性设置
为 False,使该按钮一开始呈无效状态;“退出”按钮的名称为 Command3。
2.“字符三角形图案”程序的代码程序
“字符三角形图案”程序的代码程序如下。
Dim N, H As Integer
Private Sub Command1_Click()
TS$ = "请输入三角形的行数" + Chr(13) + Chr(10) + "3 到 17 之间的奇数"
H = Val(InputBox(TS$, "输入行数", 17, 5000, 1600)) '调出“输入”对话框
Command2.Enabled = True '使“字符三角形图案”按钮有效
End Sub
Rem 显示字符三角形图案
Private Sub Command2_Click()
Cls '清窗体
For N = 1 To H
Print Tab(30-N);String$(N*2-1, "*") '在指定位置开始显示给定的奇数个字符“*”
Next N
End Sub
Private Sub Command3_Click()
122 中文 Visual Basic 6.0 实用教程—结构化程序设计
End
End Sub
程序中,循环的初值为 1 ,终值的取值用来控制三角形图案的行数, Print 语句中的
Tab(30-N)用来确定每行的字符从哪一列开始显示,String$(N*2−1, "*")用来控制每行显示几个
字符,显示的字符为“*”,“N*2−1”是为了保证每行均为奇数个字符“*”。
4.5.3 项目拓展
1.
“字符平行四边形图案”程序
【实例】 “字符平行四边形图案”程序运行后的画面与图 4-5-4 所示相似。单击“输入
行数”按钮后,弹出一个“输入行数”对话框,该对话框的提示信息是“请输入平行四边形
的行数 3 到 17 之间的自然数”,输入文本框中的默认值为 17,与图 4-5-2 所示相似。不改变
该对话框中文本框内的数值,单击“确定”按钮,又调出“输入每行的个数”对话框,该对
话框的提示信息是“请输入平行四边形每行的个数(3 到 20 之间的自然数) ”,输入文本框中
的默认值为 20,与图 4-5-2 所示相似。不改变该对话框中文本框内的数值,单击“确定”按
钮,又回到窗体,此时各个按钮均变为有效。单击“字符平行四边形图案”按钮,可在窗体
中显示出由“*”组成的平行四边形图案,如图 4-5-4 所示。
该程序窗体内对象的设置方法与“字符三角形图案”程序窗体内对象的设置方法基本一
样。它的程序如下。该程序比较简单,由读者自己解读。
Dim N, HS1, GS1 As Integer
Private Sub Command1_Click()
HS$ = "请输入平行四边形的行数" + Chr(13) + Chr(10) + "3 到 17 之间的自然数"
HS1 = Val(InputBox(HS$, "输入行数", 17, 5000, 1600)) '调出“输入”对话框
GS$ = "请输入平行四边形每行的个数" + Chr(13) + Chr(10) + "2 到 30 之间的自然数"
GS1 = Val(InputBox(GS$, "输入每行的个数", 20, 5000, 1600)) '调出“输入”对话框
Command2.Enabled = True '使"字符平行四边形图案"按钮有效
End Sub
Rem 显示字符平行四边形图案
Private Sub Command2_Click()
Cls '清窗体
For N = 1 To HS1
Print Tab(30 - N); String$(GS1, "*") '在指定位置开始显示给定数 GS1 个字符“*”
Next N
End Sub
Private Sub Command3_Click()
End
End Sub
2.“字符菱形图案”程序
【实例】 “字符菱形图案”程序运行后的画面如图 4-5-5 所示相似。单击“输入行数”
按钮后,弹出一个“输入行数”对话框,该对话框的提示信息是“请输入菱形的行数(3 到
17 之间的奇数)”,输入文本框中的默认值为 17,与图 4-5-2 所示相似。不改变该对话框中文
本框内的数值,单击“确定”按钮,又回到窗体,此时各个按钮均变为有效。
第4章 优化算法和程序设计方法 123
单击“显示字符菱形图案”按钮,即可在窗体中显示出由“*”组成的菱形图案,如图
4-5-5 所示。
5 3 1 2 2 22
5 3 2 1 1 21
124 中文 Visual Basic 6.0 实用教程—结构化程序设计
续表
5 3 3 0 0 20
5 3 4 −1 1 21
5 3 5 −2 2 22
String$((H1−Abs(H1−N))*2−1,"*")表达式保证菱形图案的上一半部分显示的字符串按奇
数个字符“*”逐渐增加,下一半部分显示的字符串按奇数个字符“*”逐渐减少。为了分析
该表达式的作用,假设有 5 行,即 H=5,H1=3,其作用如表 4-5-2 所示。
表 4-5-2 String$((H1 Abs(H1 N))*2 1,"*")表达式的作用分析
N1 Abs(H1−N) (H1−Abs(H1−N))*2−1 String$((H1−Abs(H1− N))*2−1,"*")
1 2 (3−2)*2−1=1*2−1=1 *
2 1 (3−1)*2−1=2*2−1=3 ***
3 0 (3−0)*2−1=3*2−1=5 *****
4 1 (3−1)*2−1=2*2−1=3 ***
5 2 (3−2)*2−1=1*2−1=1 *
3.“数字菱形图案 1”程序
【实例】 “数字菱形图案 1”程序运行后的画面如图 4-5-6 所示相似。单击“输入行数”
按钮后,弹出一个“输入行数”对话框,该对话框的提示信息是“请输入菱形的行数(3 到
17 之间的奇数)”,输入文本框中的默认值为 17,与图 4-5-2 所示相似。在该对话框中的文本
框内输入数值 9,单击“确定”按钮,又回到窗体,此时各个按钮均变为有效。再单击“显
示数字菱形图案”按钮,即可在窗体中显示出由数字组成的 9 行菱形图案,如图 4-5-6 左图
所示。不改变“输入行数”对话框中文本框内的数值,单击“确定”按钮,又回到窗体,此
时各个按钮均变为有效。再单击“显示数字菱形图案”按钮,即可在窗体中显示出由数字组
成的 17 行菱形图案,如图 4-5-6 右图所示。
“数字菱形图案 1”程序窗体中各对象控件的属性设置与“字符菱形图案”程序的设置方
法基本一样。“数字菱形图案 1”程序的代码程序与“字符菱形图案”程序基本一样,只是将
显示每行字符的语句修改如下。
Print Tab(20+Abs(H1-N));String$((H1-Abs(H1-N))*2-1,Format(H1-Abs(H1-N)))
4.“数字菱形图案 2”程序
第4章 优化算法和程序设计方法 125
“数字菱形图案 2”程序窗体中各对象控件的属性设置与“字符菱形图案”程序的设置方
法基本一样。“数字菱形图案 2”程序的代码程序与“字符菱形图案”程序基本一样,只是将
单击“显示数字菱形图案”按钮后的程序修改如下。
Rem 显示数字菱形图案
Private Sub 数字菱形_Click()
Cls '清窗体
SZ$ = "12345678987654321 "
For N = 1 To H
Print Tab(20 + Abs(H1-N));Left$(SZ$,H1-Abs(H1-N))+Right$(SZ$,H1-Abs(H1-N))
Next N
End Sub
程序中,Left$(SZ$,H1−Abs(H1−N))+Right$(SZ$,H1−Abs(H1−N))字符串表达式保证了菱
形图案的上半部分显示的字符串按奇数个对称数字逐渐增加,菱形图案的下半部分显示的字
符串按奇数个对称数字逐渐减少。为了分析该表达式的作用,假设有 5 行,即 H=5,H1=3,
SZ$="12345678987654321",特别要注意,SZ$字符串中最后一个字符为一个空格。字符串表
达式 Left$(SZ$,H1−Abs(H1−N))+Right$(SZ$,H1−Abs(H1−N))的作用分析如表 4-5-3 所示。
表 4-5-3 Left$(SZ$,H1 Abs(H1 N))+Right$(SZ$,H1 Abs(H1 N))表达式的作用分析
N1 Abs(H1−N) H1−Abs(H1−N) Left$(SZ$,H1−Abs(H1−N)) Right$(SZ$,H1−Abs(H1−N))
1 2 3−2=1 1 一个空格
2 1 3−1=2 12 1 加一个空格
3 0 3−0=3 123 21 加一个空格
4 1 3−1=2 12 1 加一个空格
5 2 3−2=1 1 一个空格
5.
“字母菱形图案”程序
126 中文 Visual Basic 6.0 实用教程—结构化程序设计
图 4-5-8 “字母菱形图案”程序运行后显示的图案
“字母菱形图案”程序窗体中各对象控件的属性设置与“数字菱形图案 1”程序的设置方
法基本一样。“字母菱形图案”程序的代码程序与“数字菱形图案 1”程序基本一样,只是将
显示每行字符的语句修改如下。Chr$函数可以将数值转换为相应的字母。
Print Tab(20 + Abs(H1-N));String$((H1-Abs(H1-N))*2-1,Chr$(64+(H1-Abs(H1-N))))
4.6 逻辑推理——谁是跳水运动员
4.6.1 逻辑推理的算法
1.逻辑推理的算法分析
计算机的特点之一就是能进行逻辑判断,灵活地使用关系表达式与逻辑表达式,可以用
VB 程序解决许多逻辑判断与推理的实际问题。
在 VB 中,真值为 True(−1),假值为 False(0),它们可以进行加减运算。例如:如果 A=1、
B=1、C=1,则 A=B 和 A=C 关系表达式的值均为 True,而 A<>B 关系表达式的值为 False,
(A=B)−(A=C)的值为 0,(A=B)−(A<>B) 的值为−1,(A<>B)−(A=B)的值为 1。
下面列举两个实例来说明逻辑推理的算法设计方法。
2.逻辑推理的算法举例
(1)【问题】“猜年龄”程序解决的问题:甲、乙、丙三人的年龄不一样,他们在议论各
自的年龄,他们分别说了下述六句话。
甲说:“乙比我大三岁。丙比我小四岁。”
乙说:“甲的年龄是 6 的倍数。丙比甲年龄大。 ”
丙说:“我比甲大一岁。甲的年龄是 7 的倍数。”
他们讲的六句话中,有三句是真话,三句是假话。而且还知道,其中年龄最大的一个最
第4章 优化算法和程序设计方法 127
诚实,说的两句话都是真话;而年龄最小的人说的两句话都是假话;另一人讲的两句话中,
一句是真话,一句是假话。现已知他们的年龄在 31 到 40 岁(不含 31、40 岁)之间。请编程
推理判断出这三个人的年龄。
【算法分析】设甲、乙、丙分别用 A、B、C 表示。根据他们说的话可得到下述表达式。
甲说:“乙比我大三岁。丙比我小四岁。”即 B−A=3、A−C=4
乙说:“甲的年龄是 6 的倍数。丙比甲年龄大。 ”即 A Mod 6=0、C>A
丙说:“我比甲大一岁。甲的年龄是 7 的倍数。 ”即 C−A=1、A Mod 7=0
根据题意,可获得下述几个式子。
(A=B)+(B=C)+(C=A)=0
(B−A=3)+(A−C=4)−(A>B)−(A>C)=0
(A Mod 6=0)+(C>A)−(B>A)−(B>C)=0
(C−A=1)+(A Mod 7=0)−(C>A)−(C>B)=0
(2)【问题】“谁第一”程序解决的问题:某班有甲、乙、丙、丁 4 名学生参加一次数学
比赛。已知这 4 名学生中有一人获得了第一名。当同学们问他们谁获得第一名时,他们分别
作了如下的回答。
甲说:“乙不是第一名,丁是第一名。 ” 乙说:“我不是第一名,丙是第一名。”
丙说:“甲不是第一名,乙是第一名。 ” 丁说:“我不是第一名。”
这 4 名学生中每个人说的话不是全对就是全错。请根据上述条件,编程判断谁获得数学
比赛的第一名。
【算法分析】在本实例中,用 A、B、C、D 分别表示甲、乙、丙、丁 4 个同学。再设 1
表示获得第一名,0 表示没获得第一名。故可根据上述条件,得出的表达式如下。
4 名同学中有一人是第一名:A+B+C+D=1
A 说的话:B=0,D=1 B 说的话:B=0,C=1
C 说的话:A=0,B=1 D 说的话:D=0
这 4 个人的话不是全对就是全错,因此可得如下几个式子。
(B=0)−(D=1)=0
(B=0)−(C=1)=0
(A=0)−(B=1)=0
4.6.2 项目实现
1.题目和算法分析
“谁是跳水运动员”程序是用来完成下面所述的逻辑推理:有 A、B、C、D、E 五个人要
么是女跳水运动员,要么是女游泳运动员。虽然她们自己都知道相互间的身份,但其他人不
知道。在一次联欢晚会上,她们请大家根据她们说的话来推理判断谁是女跳水运动员,谁是
女游泳运动员。她们说的话如下。
A 对 B 说:“你是女跳水运动员。 ”
B 对 C 说:“你和 D 都是女跳水运动员。”
C 对 D 说:“你和 B 都是女游泳运动员。”
D 对 E 说:“你和 B 都是女跳水运动员。”
128 中文 Visual Basic 6.0 实用教程—结构化程序设计
E 对 A 说:“你和 C 都不是女跳水运动员。”
教练说:“规定同队的人(即女跳水运动员对女跳水运动员、女游泳运动员对女游泳运
动员)说的是真话,对异队的人说的是假话”。请大家根据她们说的话来猜谁是女跳水运动员,
谁是女游泳运动员。该问题的算法分析如下。
设 5 个运动员分别为 A、B、C、D、E,女跳水运动员为 1,女游泳运动员为 0。根据她
们说的话可以列出如下几个逻辑式子。
第一句话可以表示为 B=1,第二句话可以表示为(C=0)+(D=0)=2,第三句话可以表示为
(D=1)+(B=1)=2,第四句话可以表示为(E=1)+(B=1)=2,第五句话可以表示为(A=0)+(C=0)=2。
再根据教练的话,可以写出如下逻辑式子。
X1=(A=B)−(B=1)=0
X2=(B=C)−((C=0)+(D=0)=2)=0
X3=(C=D)−((D=1)+(B=1)=2)=0
X4=(D=E)−((E=1)+(B=1)=2)=0
X5=(E=A)−((A=0)+(C=0)=2)=0
2.程序代码
“谁是跳水运动员”程序的程序代码如
下,程序的运行结果如图 4-6-1 所示。其结
果是:A、B 和 D 是女跳水运动员,C 和 E
图 4-6-1 “谁是跳水运动员”程序运行后的显示结果 是女游泳运动员。
Private Sub Form_Activate()
Dim A, B, C, D, E, X1, X2, X3, X4, X5 As Integer
FontSize = 12
ForeColor = RGB(0, 0, 255)
For A = 0 To 1
For B = 0 To 1
For C = 0 To 1
For D = 0 To 1
For E = 0 To 1
X1 = (A = B) - (B = 1)
X2 = (B = C) - ((C = 0) + (D = 0) = 2)
X3 = (C = D) - ((D = 1) + (B = 1) = 2)
X4 = (D = E) - ((E = 1) + (B = 1) = 2)
X5 = (E = A) - ((A = 0) + (C = 0) = 2)
If X1 = 0 And X2 = 0 And X3 = 0 And X4 = 0 And X5 = 0 Then
Print "说明:1 是女跳水运动员,0 是女游泳运动员。": Print
Print "A 是"; A, "B 是"; B, "C 是"; C, "D 是"; D, "E 是"; E
End If
Next E
Next D
Next C
Next B
Next A
End Sub
第4章 优化算法和程序设计方法 129
4.6.3 项目拓展
1.
“猜年龄”程序
【实例】 根据 4.6.1 的分析,编写的“猜年龄”程序如下。程序的运行结果如图 4-6-2 所示。
Private Sub Form_Activate()
Dim A, B, C, A1, B1, C1 As Integer
FontSize = 12:ForeColor = RGB(0, 0, 255)
For A = 32 To 39
For B = 32 To 39
For C = 32 To 39
If (A = B) + (B = C) + (C = A) = 0 Then
A1 = (B - A = 3) + (A - C = 4) - (A > B) - (A > C)
B1 = (A Mod 6 = 0) + (C > A) - (B > A) - (B > C)
C1 = (C - A = 1) + (A Mod 7 = 0) - (C > A) - (C > B)
If A1 = 0 And B1 = 0 And C1 = 0 Then
Print Tab(5); "甲的年龄是"; A
Print Tab(5); "乙的年龄是"; B
Print Tab(5); "丙的年龄是"; C
End If
End If
Next C
Next B
Next A
End Sub
2.“谁第一”程序
【实例】 根据 4.6.1 的分析,编写的“谁第一”程序如下。程序的运行结果如图 4-6-3 所示。
Private Sub Form_Activate()
Dim A, B, C, D, A1, B1, C1 As Integer, N$
N$ = "是第一名 不是第一名"
FontSize = 16
For A = 0 To 1
For B = 0 To 1
For C = 0 To 1
For D = 0 To 1
If A + B + C + D = 1 Then
A1 = (B = 0) - (D = 1): B1 = (B = 0) - (C = 1)
C1 = (A = 0) - (B = 1)
If A1 + B1 + C1 = 0 Then
ForeColor = RGB(255 * A, 0, 0)
Print Tab(5); "甲"; Mid$(N$, 6 - A * 5, 5)
ForeColor = RGB(255 * B, 0, 0)
Print Tab(5); "乙"; Mid$(N$, 6 - B * 5, 5)
ForeColor = RGB(255 * C, 0, 0)
Print Tab(5); "丙"; Mid$(N$, 6 - C * 5, 5)
ForeColor = RGB(255 * D, 0, 0)
130 中文 Visual Basic 6.0 实用教程—结构化程序设计
4.7 不同进制数之间的转换
4.7.1 不同进制数之间的相互转换原理
1.进位计数制
10 进制数由 0,1,2,…,9 十个数字组成,计数时逢 10 进 1,它的一般表达式为:
An−1×10n−1+An−2×10n−2+…+ A0×100+An−1×10n−l+An−2×10n−2…
十进制数的每位的数值等于该位数字乘以该位的权值。第 i 位的权值等于 10i,i 取值 0,
1,2,(小数点左边)…,−1,−2,−3…(小数点右边)。例如:
543.21=5×102+4×101+3×100+2×10−1+1×10−2
权的底数叫基数,10 进制数的权是 10i ,基数为 10。
由此可推出 N 进制数由 0,1,2,…,8,9,A,B,C,…,N 个字符组成,计数时逢
N 进 1,它的权的基数为 N。它的一般表达式为:
An−1×Nn−1+An−2×Nn−2+…+ A0×N0+An−1×Nn−l+An−2×Nn−2…
例如,16 进制数由 0,1,…,8,9,A,B,C,…,F16 个数字组成,逢 16 进 1,其
权的基数为 16,一般表达式为:
An−1×16n−1+An−2×16n−2+…+ A0×160+An−1×16n−l+An−2×16n−2…
2.进位计数制间的换算
(1)N 进制数转换为十进制数:按上面提到的一般表达式展开相加,即按权展开再相加。
例 如 , (1101.01)=1×23+1×22+0×21+1×20+0×2−1+1×2−2=8+4+1+0.25=(13.25)10 。 再 例 如 ,
(AB.8)16=10×161+1l×l60+8×16−1=160+11+0.5=(171.5)10。
(2)10 进制数转换为 N 进制数:分为整数部分和小数部分分别进行。整数部分除以基数,
取其余数,倒排序。小数部分乘以基数,取其整数,顺排序。
例如, 将 10 进制数 215 转换为 2 进制数, 转换过程如图 4-7-1 所示。 所以, (215)10=(11010111)2。
例 如 , 将 10 进 数 0.6875 转 换 为 2 进 制 数 , 转 换 过 程 如 图 4-7-2 所 示 。 所 以
(0.6875)10=(0.1011)2 。
第4章 优化算法和程序设计方法 131
2 215 余数 右(低位)
2 107 1
2 53 1 0.6875
×) 2 整数 右(高位)
2 26 1
1.3750 1
2 13 0 ×) 2
2 6 1 0.750 0
×) 2
2 3 0
1.50 1
2 1 1 ×) 2
0 1 左(高位) 1.0 1 左(低位)
4.7.2 项目实现
1.程序运行结果和分析
“不同进制数之间的转换”程序运行后,可以实现不同进位计数制的数值之间的相互转
换。程序运行后的画面如图 4-7-3 左图所示。输入 N 和 M 进制数的数,再输入要转换的 N 进
制数原数值,然后单击“转换”按钮,即可将输入的 N 进制数原数值转换为 M 进制数值,
如图 4-7-3 右图所示。
图 4-7-3 “不同进制数之间的转换”程序运行结果
4.7.3 项目拓展
1.
“最大素数的后 8 位数”程序
【实例】 1984 年时已知的最大素数是 2 的 86243 次方减 1。编写程序求该数的最后 8 位
数字,同时判断这 8 位数字是否是素数。286243−1 超出计算机允许的精确数值的范围,为了显
示 286243−1 的最后 8 位数字,就不能直接计算 286243 数值,可以创建一个循环,乘 86243 次 2,
第4章 优化算法和程序设计方法 133
2.“挑出最大的数和最小的数”程序
【实例】 “挑出最大的数和最小的数”程序运行后,会产生 40 个随机的两位数字,同
时在屏幕上按照一行 8 个数字显示出来,每个数字的左边还标出它出现的位置号码。最后,
显示出这 40 个数字中最大和最小的数字,以及它们第一次出现的位置。“挑出最大的数和最
小的数”程序如下。程序运行后的画面如图 4-7-5 所示。
Text4.Text = ""
Text1.SetFocus
End Sub
Private Sub Form_Activate()
Text1.SetFocus '将光标定位在文本框 Text1 中
End Sub
Private Sub Command3_Click()
End
End Sub
思考与练习
1.编写程序,找出满足下述条件的四位自然数
(1)该自然数是 11 的倍数;
(2)十位数和百位数的和等于千位数;
(3)百位数和十位数组成的两位自然数是一个完全平方数,例如,百位数为 2,十位数
为 5,则 25 是 5 的平方,25 是一个完全平方数;
(4)四位自然数的个位数字互不相同。
2.编写程序,找出满足下述条件的四位自然数
(1)它是一个完全平方数;
(2)它减去一个每位数字均相同的四位自然数(例如:6666)后,仍然是一个完全平方数。
3.整数 1 用了一个数字,整数 10 用了 1 和 0 两个数字。那么从整数 1 到整数 1000,一
共要用多少个数字 1 和多少个数字 0。编写程序解决该问题。
4.我国古代有一道经典数学题:“今有物,不知其数,三三数之,剩二,五五数之,
剩三,七七数之,剩二,问物几何”。根据此题给出的条件,设某物数量为 N,用 3 除商 A,
用 3 除商 B,用 3 除商 C,可以列出 N=3*A+2=5*B+3=7*C+2 式子。由上面的式子可列出不
定方程式如下。编写程序来解这个不定方程的最小解。编写程序解决该问题。
⎧3 ∗ A + 2 = 5 ∗ B + 3 ⎧B = (3 ∗ A − 1) / 5
⎨ 或 ⎨
⎩3 ∗ A + 2 = 7 ∗ C + 2 ⎩C = 3 ∗ A / 7
5.有布 7 丈 5 尺,裁剪成人与小孩的衣料。成人每件用布 7 尺 2 寸,小孩用布 3 尺。
问这些布料刚好能裁剪多少件成人衣料和多少件小孩衣料?要求小孩衣料件数比成人的衣料
件数多,且至少裁剪一件成人衣料。根据题意可列出下面的不定方程式:72*A+30*B=750。
编写程序解决该问题。
6.某学校有三名同学参加数学竞赛,共 10 道题,答对一道得 10 分,答错一道题扣 3
分。这三名同学都回答了所有的题,小明得了 87 分,王红得了 74 分,张凯得了 48 分,他们
三人共答对了多少道题? 编写程序解决该问题。
7.教师把一些苹果分给几个小朋友,如果每人分 1 个则多 3 个苹果;如果每人分 2 个,
则少 2 个苹果,一共有多少个小朋友?有多少个苹果? 编写程序解决该问题。
8.哥德巴赫猜想的另一个命题是:任何一个大于 7 的奇数都是三个素数的和。例如:
138 中文 Visual Basic 6.0 实用教程—结构化程序设计
24.编写一个能求 4 个数的最大公约数与最小公倍数的程序。
25.如果一个数从左边读和从右边读都是同一个数,则该数叫回文数,例如 787 是一个
回文数。编程显示出 1000 以内所有既是回文数又是素数的自然数。
26.可以将文本框中的英文大写字母改成小写字母,将英文小写字母改成大写字母,并
在另一个文本框中显示出来的程序。
27.由用户输入行数,然后显示由字符组成的等腰梯形图案。编写程序解决该问题。
28.编写一个可以显示 4 种不同的字母菱形图案的程序。程序运行后,单击“输入行数”
按钮,可调出“输入行数”对话框,在该对话框内的文本框中输入行数后,再单击不同的按
钮,可以显示不同类型的字母菱形图案。几种字母组成的字母菱形图案如图 4-1 所示。
28 题图 1 28 题图 2
图 4-1 28 题图
图 4-2 29 题图 1 图 4-3 29 题图 2
30.有张海燕(A)、沈芳麟(B)、郭海(C)、杜金(D)、边红(E)、刘峰(F)和李超
宏(G)7 个人争论今天是星期几:
A:后天是星期三。
B:不对,今天是星期三。
C:你们都错了,明天是星期三。
D:不对!今天既不是星期一,也不是星期二,更不是星期三。
E:我确信今天是星期四。
F:不对!你弄颠倒了,明天是星期四。
140 中文 Visual Basic 6.0 实用教程—结构化程序设计
G:不管怎样,昨天不是星期六。
他们之中只有一人讲对了,是哪一个?到底今天是星期几?
31.有 1、2、3、4 号码的四个运动员,在一项比赛中获得了前四名,现在知道的情况
如下:
(1)每个运动员的名次都与自己的号码不符;
(2)第四名运动员的号码是某一运动员的名次,而这个运动员的号码又是 2 号运动员的
名次;
(3)3 号运动员不是第一名。
推断出这四名运动员各是第几名。
32.有红、绿、蓝、黄、紫色的珠子分别放在 5 个盒子里。有 4 个人说了以下的话。
甲说:第二个盒子里是紫珠子,第四个盒子里是黄珠子。
乙说:第一个盒子里是红珠子,第五个盒子里是绿珠子。
丙说:第三个盒子里是绿珠子,第四个盒子里是蓝珠子。
丁说:第二个盒子里是黄珠子,第五个盒子里是紫珠子。
他们每个人都说对了一半,说错了一半。请根据上述情况编写程序,判断这几个盒子里
各放着什么颜色的珠子。要求用汉字显示结果。
33.平面上有五个点,任三点不在同一直线上,连接每两个点的线段有几条? 编写程序
解决该问题。
34.某个自然数 N 的所有素因数的平方和等于 N,当 N 为一位或两位自然数时,编写程
序,显示所有符合上述要求的数字 N。
35.编写一个账号和密码输入程序,账号为 6 位数字,密码为 8 位字母和数字,输入它
们时,文本框中显示一串“*”,只有在输入正确后才可以进入下一个画面。如果 4 次输入均
不正确,则退出程序的运行。
36.编写一个可以显示 5 个字符菱形图案(水平排列)的程序。
37.求可使 1989m 和 1989n 的最后三位数字相等的最小的正整数 M、N(0<N<M)。
38.在“不同进制数之间的转换”程序中,如果输入时不是分别在两个文本框中输入
N 制式的整数部分和小数部分,而是在一个文本框中输入 N 制式的整数和小数,应如何修
改程序?
39.显示 60 个随机数,按照一行 10 个数字来显示,同时显示数字出现的序号。然后,
将这组数字中最大和最小的数字显示出来,并显示它们最后一次出现的序号。
40.参考“50 位精确加法计算”程序,编写一个可以进行 50 位精确减法计算的程序。
41.编写一个猜数字游戏程序,要求计算机产生 0~100 范围内的随机整数,让玩者猜。
当你用键盘输入的数小于或大于计算机产生的数时,屏幕显示“数太大!”或“数太小!”提
示信息,玩者根据提示可再输入所猜的数。如果 5 次或小于 5 次猜中,屏幕显示“你很聪明!”
如果大于 5 次小于 10 次猜中,屏幕显示“你还可以!”如果 10 次或 10 次以上才猜中,屏幕
显示“你要努力了!”
数组和数据结构基础
第 5章
5.1 选 举 程 序
5.1.1 数组和数组元素
1.数组
在实际应用中,经常需要处理一批相互有联系、有一定顺序、同一类型和具有相同性
质的数据(例如:某单位若干职工的工资,各候选人的选票数等)。通常把这样的数据或变
量叫数组。数组是一组具有相同数据结构的元素组成的数据集合。构成数组的各个数据或
变量叫数组元素。数组在 Visual Basic 程序设计中相当重要,它可以使程序设计得更有条理
和更简单。
2.数组元素
组成数组的元素统称为数组元素。若干职工的工资构成一个数组,每个职工的工资叫数
组元素;所有候选人的选票数据构成一个数组,每一个候选人的选票数就是一个数组元素。
数组用一个统一的名称来标识这些元素,这个名称就是数组名。数组中,对数组元素的区分
用数组下标来实现,数组下标的个数称为数组的维数。有了数组,就可以用同一个变量名来
表示一系列的数据,并用一个序号(下标)来表示同一数组中的不同数组元素。例如:数组
N 有 11 个数组元素,则可表示为 N(0),N(1),…,N(10),它由数组名称和括号内的下标组
成,下标可以是常量、变量和数值型表达式。因此,数组元素也叫下标变量。
一般情况下,数组应具有相同的数据类型,但当数组元素的数据类型为变体型(Variant)
类型时,各个数组元素可以是不同类型的数据。为了区分各个不同的数组,必须给每个数组
取一个名字。数组名的命名规则与简单变量的命名规则一样。
3.下标变量和简单变量之间的区别
下标变量和简单变量之间的重要区别就是简单变量是没有序的,数组中的数组元素是有
排列顺序的。使用循环语句,使下标变量的下标不断变化,即可获取数组中的所有变量,采
用这种方法,可以很方便地给下标变量赋值和使用下标变量的数据。例如:100 个职工的工
资进行总金额统计,如果使用简单变量,需要使用 100 个变量(F1,F2,F3,…,F100)来
分别表示各职工工资,则总金额为 F=F1+F2+F3+…+F100。如果使用数组,只需要一个有 100
个数组元素的数组 F,它有 100 个下标变量 F(1),F(2),F(3),…,F(100),使用循环语句,
可以很容易地给它们赋值和进行累加。再例如,对 100 个候选人选票进行统计,如果使用简
单变量,程序会很复杂;如果使用数组,程序会变得非常简单。
142 中文 Visual Basic 6.0 实用教程—结构化程序设计
5.1.2 定义常规数组
态数组不占用内存,可以将这部分存储空间移作他用。当不需要动态数组时,还可以用 Erase
语句删除它,收回分配给它的存储空间,还可以用 Redim(或 Dim)语句再次分配存储空间。
动态数组是用变量作为下标定维的数组,在程序运行的过程中完成数组的定义,动态数组可
以在任何时候改变大小。
【格式】ReDim [Preserve] 数组名 [(维数定义)][As 数据类型]……
【功能】创建动态数组。
【说明】
① 创建动态数组时,上界和下界可以是常量和变量(有确定值)。
② 可使用 ReDim 语句多次改变数组的数组元素个数和维数,但不能改变它的数据类型。
③ 如果重新定义数组,则会删除它原有数组元素中的数据,并将数值型数组元素全部
赋 0,将字符型数组元素全部赋空串。如果要想在数组重定义后不删除原有数据,应在定义
数组时增加 Preserve 关键字,但是使用 Preserve 关键字后,只能改变最后一维的上界,不可
以改变数组的维数。例如:
ReDim N(30) As Double '定义了一个有 31 个数组元素的整型动态数组 N
ReDim Preserve N(40) As Double '将动态数组 N 的上界改为 40
④ 可以使用带空圆括号的 Dim 语句来定义动态数组。在定义动态数组后,可以在过程
内使用 ReDim 语句来定义该数组的维数和元素。如果试图在 Private、Public 或者 Dim 语句
中重新定义一个已定义了大小的数组时,就会发生错误。
5.1.3 项目实现
1.“选举程序”程序运行效果
“选举程序”程序运行后,会弹出一个“输入”对话框,如图 5-1-1 所示,要求输入候
选人的个数。输入数据(例如:20)后,按回车键或单击“确定”按钮,又弹出一个“输入”
对话框,如图 5-1-2 所示,要求输入候选人的选号。
输入选号后,按回车键或单击“确定”
按钮,又弹出该对话框,再输入候选人的选
号,按回车键或单击“确定”按钮,如此不
断。选举完成后,输入小于等于 0 或大于候
选人个数的数值,按回车键或单击“确定”
图 5-1-3 票数统计结果 按钮,即可显示所有候选人的票数,如图
5-1-3 所示。
2.“选举程序”程序代码
“选举程序”程序代码中,使用了数组 P 来保存各候选人的选票数,一共有 N 个候选
144 中文 Visual Basic 6.0 实用教程—结构化程序设计
5.1.4 项目拓展
1.
“创建和显示一维数组”程序
【实例】 “创建和显示一维数组”程序是一个用来创建一维数组和显示该一维数组中
数组元素的程序。在程序代码中,变量 N 是数组元素的个数,它由用户通过键盘输入获得的。
使用了数组 P 来保存各输入的数据,一共有 N 个数据。因此定义一个数组 P(1 To N),它有 N
个下标变量 P(1),P(2),…,P(N),分别用来保存输入的数据。定义数组 P(N)使用的语句是:
ReDim P(1 N) As Integer,它的数据类型是整型数据。
程序运行后,显示如图 5-1-4 所示的“数组元素的个数”对话框,用来输入数组元素个
数,输入数据(例如:10)后,按回车键或单击“确定”按钮,即可调出如图 5-1-5 所示的
“输入数据”对话框,利用该对话框输入第 1 个数据,按回车键或单击“确定”按钮后,再
依次输入其他各个数据。当输入完所有数据后,即可显示如图 5-1-6 所示的所有数组元素数
据。“创建和显示一维数组”程序代码如下。
图 5-1-6 显示一维数组数据
2.“创建和显示二维数组”程序
【实例】 “创建和显示二维数组”程序是一个用来创建二维数组和显示该二维数组中
数组元素的程序。在程序代码中,变量 H 是数组元素的行数,变量 L 是数组元素的列数,它
们是由用户通过键盘输入获得的。使用了数组 P 来保存输入的数据,一共有 H×L 个数据。因
此定义一个数组 P(1 To H,1 To L),它有 H×L 个下标变量 P(1,1),P(1,2),…,P(1,L),P(2,1),
P(2,2),…,P(2,L),P(H,1),P(H,2),…,P(H,L),分别用来保存输入的数据。定义数组 P
使用的语句是:ReDim P(1 To H,1 To L) As Integer,它的数据类型是整型数据。
程序运行后,显示如图 5-1-7 所示的“数组的行数”对话框,用来输入数组的行数,输
入数据(例如:5)后,按回车键或单击“确定”按钮,调出如图 5-1-8 所示的“数组的列数”
对话框,用来输入数组的列数,输入数据(例如:5)后,按回车键或单击“确定”按钮,调
出如图 5-1-9 所示的“输入数据”对话框,利用该对话框输入第 1 个数据,按回车键或单击
“确定”按钮后,再依次输入其他各个数据。当输入完所有数据后,即可显示如图 5-1-10 所
示的所有数组元素数据。 “创建和显示二维数组”程序代码如下。
5.2 改变二维数组
2.数组函数
(1)Array 函数
【格式】Array(元素列表)
【功能】将元素列表中的数据赋给一个 Variant 型数组的数组元素。
【说明】元素列表由各种类型数据组成,这些数据用逗号分隔。如果元素列表中不包含
任何元素,则该函数创建一个元素个数为 0 的空数组。没有被声明为数组的 Variant 型变量也
可以表示数组。除了定长字符串以及用户自定义类型数据之外,Variant 变量可以表示任何类
型的数组。例如:
Dim N1,N2 '定义了两个 Variant 型变量 N1 和 N2
N1=Array("A","B","C","D","E","1","100") '将一个数组赋给变量 N1
N2=N1(6) '将数组 N1 的第 7 个元素(下标从 0 开始)的值赋给变量 N2
(2)下界函数(Lbound)
【格式】Lbound(数组名[,维数])
【功能】求数组指定维数的最小下标。函数值为 Long 型数据。
【说明】“数组名”参数为数组变量名。维数是可选参数,可以是任何有效的数值表达式,
表示求哪一维的下界。1 表示第一维,2 表示第二维,依此类推。如果省略该参数,则默认
为 1。
例如:声明数组 N,即 Dim N(100,−10 To 100,1 To 10),则 LBound(N,1)=0,LBound(N,
2)=−10,LBound(N,3)=1。
(3)上界函数(Ubound)
【格式】UBound(数组名[,维数])
【功能】求数组指定维数的最大下标。函数值为 Long 型数据。
例如:声明了数组 N,即 Dim N(20,1 To 10),则 UBound(N,1)=20,UBound(N,2)=10。通常
将 UBound 函数与 LBound 函数一起使用,以确定一个数组的大小。
例如:
ReDim N(30) As Double '定义了一个有 31 个数组元素的整型动态数组 N
ReDim Preserve N(Ubound(N)+10) '利用 Ubound 函数将动态数组 N 的上界加 10
(4)IsArray 函数
【格式】IsArray(变量名)
【功能】判断一个变量是否为数组变量。函数值为 Boolean 型。
【说明】如果参数是数组变量,则该函数的值为 True,否则为 False。
例如:声明了 Dim N1(10) As Long : Dim L Integer,则 IsArray(N1)= False, IsArray(N1)=True。
5.2.2 项目实现
“改变二维数组”程序是用来介绍如何创建二维数组、如何给二维数组元素赋值、如何
改变二维数组大小并保留原数据以及如何改变数组的维数。程序运行后,单击“显示数组”
按钮后,会在窗体内上边显示一个 4×2 的矩阵,如图 5-2-1 所示。
单击“改变数组”按钮后,窗体内会显示一个 4×4 的矩阵,可以看出,数组第二维的上
界增加到了 4,同时数组原来的数据没有消失,如图 5-2-2 所示。单击“清除数组”按钮后,
148 中文 Visual Basic 6.0 实用教程—结构化程序设计
图 5-2-1 显示二维数组
图 5-2-2 改变二维数组
5.2.3 项目拓展
1.
“矩阵行列变换”程序
【实例】 “矩阵行列变换”程序运行后的画面如图 5-2-3 左图所示,在窗体内显示了一
个 5×5 矩阵,矩阵中的元素都是两位整数,十位数表示行号,个位数表示列号。
单击“矩阵行列变换”按钮后,可以在窗体内显示出矩阵行数据变为列数据(即第 1 行
数据变为第 1 列数据,第 2 行数据变为第 2 列数据……第 5 行数据变为第 5 列数据)的变换
效果,如图 5-2-3 右图所示。“矩阵行列变换”程序的界面有一个窗体对象、一个标题控件对
象和两个按钮控件对象,对象的属性设置由读者来完成。程序代码如下。
图 5-2-3 “矩阵行列变换”程序运行后的画面
150 中文 Visual Basic 6.0 实用教程—结构化程序设计
Dim A, B As Integer
Dim N(5, 5) As String '声明一个空整型数组 S
Private Sub Form_Activate( )
Rem 给数组 N 赋值,并显示矩阵
Print: Print: Print
FontSize = 12
ForeColor = RGB(0, 0, 255)
For A = 1 To 5
For B = 1 To 5
N(A, B) = Mid(Str$(A), 2, 1) + Mid(Str$(B), 2, 1)
Print N(A, B) + Space(3);
Next B
Print
Next A
End Sub
Private Sub Command1_Click( )
Rem 行列互换
Print
FontSize = 12
ForeColor = RGB(255, 0, 0)
For A = 1 To 5
For B = 1 To 5
Print N(B, A) + Space(3);
Next B
Print
Next A
End Sub
Private Sub Command2_Click(Index As Integer)
End
End Sub
注意:行列矩阵变换的关键是显示矩阵时,使用的是 Print N(A, B)语句;显示行列变换
后的矩阵时,使用的是 Print N(B, A)语句。
2.“矩阵行颠倒”程序
【实例】 “矩阵行颠倒”程序运行后的画面如图
5-2-3 左图所示。
单击“矩阵行颠倒”按钮后,可以在窗体内显示
出矩阵行颠倒后的数据(即第 1 行数据变为第 5 行数
据,第 2 行数据变为第 4 行数据……第 5 行数据变为
第 1 行数据)的变换效果,如图 5-2-4 所示。“矩阵行
颠倒”程序代码如下。注意:矩阵行颠倒的关键是显
示矩阵时,使用的是 Print N(A, B)语句;显示行颠倒
图 5-2-4 “矩阵行颠倒”程序运行后的画面 后的矩阵时,使用的是 Print N(6 - A, B)语句。
Dim A, B As Integer
Dim N(5, 5) As String '声明一个空整型数组 S
第5章 数组和数据结构基础 151
Dim A, B As Integer
Dim N(5, 5) As String '声明一个空整型数组 S
Private Sub Form_Activate( )
Rem 给数组 N$赋值,并显示矩阵
Print: Print: Print
FontSize = 12
152 中文 Visual Basic 6.0 实用教程—结构化程序设计
5.3 线性表的插入和删除
5.3.1 数据结构的基础知识
1.什么是数据结构
早期的计算机主要用于解决数值计算问题,例如,计算函数值、解不定方程式、解代数
方程和求一元多次方程的解等。随着计算机应用的不断发展,计算机的应用领域除了用于科
学计算外,还更大范围地应用于数据处理和数据管理等非数值计算工作,如文献检索、金融
管理、商业系统数据处理、计算机辅助设计和制造以及图像模式识别等。因此,计算机的加
工处理对象除了纯粹的数值外,更多的是字符、表格、图像、音频及视频等信息编码的具有
一定结构的数据,解决非数值性问题越来越引起人们的关注。
这类问题重点在于数据处理,即对数据集合中的各元素以各种方式进行运算,如插入、
删除、查找和更新等。针对这些处理对象,要编写高质量的程序,就必须研究如何有效地组
织数据和处理数据,根据问题的要求及数据元素之间的特性,来确定相应的算法和存储结构
等,这些正是数据结构要研究的内容。
计算机是通过执行人们所编制的程序来完成预定任务的。从广义上说,计算机按照程序
所描述的算法对某种结构的数据进行加工处理。因此,有人给程序下了一个定义,
“程序=算
法+数据结构”。
第5章 数组和数据结构基础 153
对于许多非数值问题,通常是无法用数学方程来描述的,这些问题所求的不是某个数值,
而是某种检索的结果,某种排列的状态,某种转换后的形式,某种设计的表示等,这些问题
的数学模型是通过一种数据结构来描述数据以及数据之间的相互关系。下面通过一个“用计
算机处理电话号码查询”问题来了解数据结构。
该问题是要求用户输入姓名,如果存储有该人的电话号码,则会给出对应输入姓名的
电话号码;否则,显示没有该人电话号码的信息。有两种方法可以选择,一是按照用户在
电信局中申请的电话号码的顺序建立电话号码表,存储到计算机中,如表 5-3-1 所示。这种
情况下,由于电话号码没有任何规律,查找时只能从第一个号码开始逐一进行。二是根据
每个用户姓名的第一个拼音字母,按照 26 个英文字母的顺序进行排列,如表 5-3-2 所示。
这种情况下,根据姓名的第一个字母就可以迅速地进行查找,从而大大减少了查找所需的
时间。
表 5-3-1 无规律的电话号码表 表 5-3-2 按姓名排序的电话号码表
王 强(wangqiang) 63390843 安辉乔(anhuiqiao) 85432341
…… …… …… ……
在这个例子中,为了提高查找效率,必须了解待处理对象之间的关系,以及如何存储和
表示这些数据。表 5-3-1 和表 5-3-2 就是为了解此问题而建立的不同的数学模型,在表 5-3-2
中,各对象(姓名)之间存在一种有效的最简单的线性关系,即按姓名顺序排列,这类数学
模型可称为线性表数据结构。
这个例子中的问题是一个非数值计算问题,不能用数学方程描述这类问题,而是使用了
表这个数据结构来进行描述。
在数据处理领域中,数据类型比较复杂,而且数据元素之间具有各种特定的联系,因
此,了解数据集合中元素之间的关系以及如何组织和表示这些数据,可以提高处理数据的
效率。
数据结构是一门研究非数值计算问题中,计算机处理对象,对象之间关系及对这些对象
进行相关操作等的一门学科。计算机完成这类工作的效率和被处理的数据的组织形式有着密
切的关系,这就是说存在一个数据结构问题。
2.数据结构的基本概念
(1)数据:数据(data)是对客观事物的名称、数量、特征和性质等属性的描述形式(即
编码),是计算机所能处理的一切符号(例如:数、字符、图像符号、声音符号和视频符号等)
的集合。数据是信息的载体,它可以用计算机来加工处理。
(2)数据元素:数据元素(data element)是数据集合中的一个个体,是数据的基本单位。
数据元素也称为结点(node)或记录(record)。例如,数据集合 N={l,2,3,4,5,6}中整
数 1~6 均为数据元素。一个数据元素可以是简单的只有一个数据项,例如一个数值、一个符
号或一个名称等,也可以是由若干个数据项组成的。表 5-3-3 是一个通讯录表,其中每一个
人的全部信息组成一个数据元素,它由编号、姓名、性别、电话号码、手机号码、邮编和地
154 中文 Visual Basic 6.0 实用教程—结构化程序设计
址 7 个数据项组成。
表 5-3-3 通讯录表
编 号 姓 名 性 别 电 话 号 码 手 机 号 码 邮 编 地 址
…… …… …… …… …… …… ……
一般情况下,一组数据元素并不是杂乱无章的,而是具有某种结构形式。这里,结构形
式是指数据元素间的相互关系,这种相互关系可以用对数据元素的一些运算来表示。
(3)数据对象:具有相同性质的数据元素的集合称为数据对象(data oject)。
(4)关键数据项:在数据结构中,通常一个数据结点由用来描述一个独立事物的多种
属性的多个信息组成,例如在通讯录表中,每个人是一个结点,该结点可以包括人的编号、
姓名、性别、电话号码……等信息。在数据处理中,称这样的数据元素(结点)为记录。
如果在所有的记录中,存在这样的数据项,它的值在所有记录中都不同,可以用这个数据
项的值标识和区分每一个结点,则称这个数据项为记录的关键数据项,简称关键项。关键
项的每一个值称为所在记录的关键字,比如在上述问题中,可以使用编号这个数据项作为
关键项。
在一些问题中,能作为关键项的数据项可能不存在,可能只有一个,也可能多于一个。
当没有时,可以把多个有关的数据项结合起来,构成一个组合关键项,用组合关键项中的每
一个组合值来惟一地标识一个记录。在研究数据结构问题的时候,通常只是抽象出记录的关
键项来考虑问题,因为关键项决定了其所在的记录。
(5)数据结构:数据结构是指数据及其之间的联系。数据结构是描述一组数据元素及元
素间的相互关系的。可以用集合论的方法给出数据结构的定义。数据结构 S 是一个二元组:
S=(D,R)
其中,D 是一个数据元素的非空的有限集合,R 是定义 D 中各数据之间关系的非空的有限集
合;即 D 是由有限个数据元素构成的集合,R 是有限个结点间关系的集合。这种抽象的定义
可用来描述广泛的数据结构问题。
(6)数据的逻辑结构和存储结构:在计算机中存储数据时,不仅要存储数据本身,而且
还要存储它们之间的联系。数据之间的相互关系,被称为数据的逻辑结构,它是指数据元素
之间的逻辑关系,与数据的存储无关,它独立于计算机。一种数据结构在存储器中的存储方
式被称为数据的物理结构或存储结构。由于存储方式有顺序、链接、索引和散列等多种形式,
所以,一种数据结构可以根据应用的需要表示成一种或几种存储结构。因为数据结构着重于
数据的逻辑结构,所以也就经常把数据的逻辑结构称为数据结构。
除此之外,为了解决实际问题,通常在算法中还要指出对一种数据结构可以施加哪些运
算,它主要包括插入、删除、查找和排序等操作。总之,数据结构一般包括 3 个方面的内容,
即数据的逻辑结构、数据的存储结构和数据的运算。
(7)数据类型:数据类型(data type)是指程序设计语言中允许的变量类型。程序中出
第5章 数组和数据结构基础 155
现的每一个变量必须与一个且仅与一个数据类型相联系,它不仅规定了该变量可以设定的值
的集合,而且规定了这个集合上的一组运算。各种语言都规定了它所允许的数据类型。
数据类型分为基本数据类型和结构数据类型两类。基本数据类型如整型、实型、布尔型
等,它们变量的值是不可再分的;而结构类型如数组、结构体等,它们变量的值是可再分的,
或者说它们是带结构的数据。
3.数据结构分类
数据结构可分为数据的逻辑结构和存储结构。基本的数据逻辑结构有 4 种,包括集合、线
性表、树和图,其他种类的数据结构多是由这 4 种基本结构派生的。逻辑结构分类简介如下。
① 集合:数据元素之间除了“同属于一个集合”的关系之外,没有其他任何关系,这
是最简单的一类逻辑结构。
② 线性表结构:线性表的数据元素只按先后次序连接,数据元素之间存在一个对一个
的关系。
③ 树形结构:树的数据元素是分层次的纵向连接,数据元素之间存在一个对多个的关系。
④ 图状结构或网状结构:图的数据元素则有各种各样的复杂连接,数据元素之间存在
多个对多个的关系。
基本的数据存储结构有 4 种,包括顺序存储结构、链接存储结构、索引存储结构和散列
存储结构。应根据实际条件选用不同的存储结构,这些存储结构也可以组合使用。顺序存储
结构和链接存储结构是各种数据结构中最常用的存储结构。顺序存储结构是将数据结构的数
据元素按某种顺序存放在计算机存储器的连续存储单元中。
5.3.2 线性表
1.线性表的定义
线性表是数据元素的有限序列,是一种最常用和最简单的数据结构,在日常生活中可以
找到很多例子,例如,100 以内的自然数(1,2,3,…,100),其中每一个自然数均为一个
数据元素;表 5-3-3 所示通讯录中的每一个人的姓名就是一个数据元素。
现实中客观存在的实体经过数学抽象后都可用线性表的一般表示形式来表示如下。
L=(a1, a2, …, an)
其中,L 为线性表;ai(i=1,2, …, n)是属于某数据对象的数据元素;n(n≥0)是元素个数,称为
表长,n=0 时为空表。
线性表的结构特点是:数据元素之间是线性关系,即在线性表中必存在惟一的一个“第
一个”元素;必存在惟一的一个“最后一个”元素;除第一个元素外,每个元素都有且只有
一个前趋元素;除最后一个元素外,每个元素都有且只有一个后继元素。由此可以得出线性
表的定义如下:
L=(D,R)
其中,D={a1, a2, …, an}, R={(<a1, a2>, <a2, a3>, …, <an−1, an>)
如果线性表中的数据元素相互之间可以比较,且 ai>ai−1(i=2,3,4,…,n),则将该线性表称
为有序表,否则将该线性表称为无序表。
2.线性表的基本运算
数据的运算是定义在数据的逻辑结构上的,运算的具体实现要在存储结构上进行,数据
156 中文 Visual Basic 6.0 实用教程—结构化程序设计
的各种逻辑结构有其相应的各种运算,每种逻辑结构都有一个运算的集合。线性表的基本运
算主要有以下几种。
(1)插入:在线性表中的指定位置上(两个确定元素之间)增添新的数据元素;
(2)删除:删除线性表中某个指定的数据元素;
(3)更新:改变线性表中的某个数据元素的值;
(4)查找:在线性表中查找满足某个符合要求的数据元素的位置或数值;
(5)排序:按给定要求对线性表中的数据元素重新排序,使之按照由小到大或由大到小
的顺序排列。
在不同问题或不同存储结构的线性表中,需要进行的运算也不同,在实际应用中还会涉
及到建立线性表、读取数据元素数值、求线性表的长度(即线性表中数据元素的个数)和清
除线性表等运算,但基本上可以由上述 5 种运算组成。
3.线性表的顺序存储结构
线性表的存储结构有两种,即顺序存储结构和链接存储结构。顺序存储结构是一种最常
b 用也是最简单的线性表结构,它是用一组地址连续的存储
1
单元存放线性表的数据元素,也称为向量式存储结构,可
……
b+1 用高级语言中一维数组类型表示。数组中的分量下标即为
元素在线性表中的序号。例如用一维数组 A(1,2)来存
b+(i–1)1
ai 储线性表(a1,a2,…,an),它在内存中的存放形式如图 5-3-1
……
5.3.3 项目实现
1.线性表插入和删除运算的算法
(1)插入算法
在排队购物时,如果有一个人插到队伍中,他后面的人们就不得不后退一步,以保持正
常的队形,在线性表中插入一个数据元素的情形类似。
设长度为 n 的线性表(a1,a2,…,an),要在第 i−1 与第 i 个数据元素之间插入一个新
元素 X。首先应指明插入的位置在第 i 个数据元素之前,再确定插入新的数据元素 X。然
后,必须从第 i 个元素开始到最后一个元素 an 为止,把数据元素依次向后移动一个位置,
移动从最后一个位置的数据元素开始,依次向后移动,最终将长度为 n 的线性表(a1,
a2,…,an)变成长度为 n+1 的线性表(a1,a2,ai −1,X,ai,…,an)。插入过程如图 5-3-2
所示。
图 5-3-3 显示了在长度为 9 的线性表(11,22,33,44,55,66,77,88,99)中的第 5
个位置前插入数据元素 00 的过程。
第5章 数组和数据结构基础 157
a1 a2 … ai–1 ai … an–1 an
a1 a2 … ai–1 X ai … an–1 an
图 5-3-2 插入过程
插入前 n=9 00
11 22 33 44 55 66 77 88 99
插入后 n=10
11 22 33 44 55 00 66 77 88 99
(2)删除算法
如果要在长度为 n 的线性表中删除第 i 个元素,相当于将表(a1,a2,…,an)中的 ai 删除。
在删除第 i 个元素后,要使它后面的所有元素向前依次移动一个位置,以保证线性表中元素
的连续排列,即将 ai 以后的元素 ai+1……an,依次向前移动一个位置,表长由 n 改为 n−l。对
于长度为 n 的线性表(a1,a2,…,ai−1,ai,ai+1,…,an),删除第 i 个元素后变成长度为 n−1
的线性表(a1,a2,…,ai−1,ai+1,…,an)。删除过程如图 5-3-4 所示。
a1 a2 … ai–1 ai … an–1 an
11 22 33 44 55 66 77 88 99
11 22 33 44 66 77 88 99
2.“线性表插入数据”程序设计
“线性表插入数据”程序运行后的画面如图 5-3-6 所示,可以看到在窗体内显示出线性
表(11,22,33,44,55,66,77,88,99)。单击“插入数据”按钮后,即可调出“确定位
158 中文 Visual Basic 6.0 实用教程—结构化程序设计
置”对话框,输入要插入数据的位置号(此处输入 5)后,单击“确定”按钮,又可调出“确
定数据”对话框,输入要插入的数据(此处为 00),再单击“确定”按钮,即可在原数据的
下边显示插入数据后的线性表效果,如图 5-3-7 所示。
单击“删除数据”按钮后,即可调出“确定位置”对话框,输入要删除数据的位置号(此
处输入 5)后,单击“确定”按钮,即可在原数据的下边显示删除数据后的线性表效果,如
图 5-3-10 所示。
重复上述操作,分别再将第 1 号位置处的“AA”,将第 10 号位置处的“LL”,将第 11
号位置处的“NN”删除,最终效果如图 5-3-11 所示。
“线性表删除数据”程序代码如下。
Dim I, N As Integer
Dim P( ) As String '定义一个空数组 P
Private Sub Form_Activate( )
ReDim P(1 To 16) As String '定义一个动态数组 P,数组元素个数为 9
160 中文 Visual Basic 6.0 实用教程—结构化程序设计
FontSize = 12
ForeColor = RGB(0, 0, 255)
Print: Print: Print: Print
For N = 1 To 16
If N < 10 Then
Print LTrim$(Str(N)); " ";
Else
Print LTrim$(Str(N)); " ";
End If
Next N
Print
For N = 1 To 16
P(N) = Chr$(64 + N) + Chr$(64 + N)
Print P(N) + " ";
Next N
Print
End Sub
Rem 在线性表中删除数据
Private Sub Command1_Click( )
I = Val(InputBox("请输入要删除数据的位置", "位置数是:", 5))
Rem 移动线性表中的数据元素,将第 I 到最后的数据元素向左移动
For N = I To UBound(P, 1) - 1
P(N) = P(N + 1)
Next N
ReDim Preserve P(1 To UBound(P, 1) - 1) As String '将数组元素个数减少 1
For N = 1 To UBound(P, 1)
Print P(N) + " ";
Next N
Print
End Sub
Private Sub Command2_Click( )
End
End Sub
5.3.4 项目拓展
1.
“线性表数据的删除和添加”程序
【实例】 “线性表数据的删除和添加”程序运行后,随机产生一组互不相同的两位随
机整数,然后通过键盘输入任意一个两位整数,如果该数据与数组中的数据相同,则删除数
组中的这个数据,如果该数据与数组中的所有数据均不相同,则在数组的最后插入该数据。
程序运行后的画面如图 5-3-12 所示,单击“开始”按钮,即可在窗体内显示 30 个互不
相同的两位整数,如图 5-3-13 所示。然后单击“删除/添加”按钮,调出“删除或添加的数据”
对话框,在文本框中输入要删除或添加的数据(此处输入 11),如图 5-3-14 所示。单击“确
定”按钮或按回车键,即可根据输入的数据是否与线性表内的数据相同,而决定是在线性表
中添加数据,还是删除线性表中与输入数据相同的数据。最后,将处理好的数据在窗体中显
第5章 数组和数据结构基础 161
图 5-3-14 “删除或添加的数据”对话框
For I = 1 To UBound(N, 1)
N(I) = Int(Rnd * 90) + 10
Rem 将新产生的随机数与以前成生的随机数进行比较,如果有相同的,则重新产生
For J = 1 To I - 1
If N(I) = N(J) Then I = I - 1: Exit For
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
FontSize = 12
ForeColor = RGB(0, 0, 255)
For I = 1 To UBound(N, 1)
Print LTrim$(Str(N(I))) + " ";
If I Mod 15 = 0 Then Print
Next I
Print: Print
End Sub
Private Sub Command2_Click( )
A = Val(InputBox("请输入要删除或添加的数据", "删除或添加的数据", 0))
Rem 如果 A 与数组中的数相等,则删除数组中的这个数
FontSize = 12
ForeColor = RGB(255, 0, 0)
BJ = 0
For I = 1 To UBound(N, 1)
If N(I) = A Then
For J = I To UBound(N, 1) - 1
N(J) = N(J + 1)
Next J
BJ = 1
End If
Next I
Rem 如果 A 与数组中的数不相等,则在数组末尾添加这个数
If BJ = 0 Then
ReDim Preserve N(1 To UBound(N, 1) + 1) As Integer '将数组 N 的元素个数增加 1
N(UBound(N, 1)) = A
Else
ReDim Preserve N(1 To UBound(N, 1) - 1) As Integer '将数组 N 的元素个数减少 1
End If
Rem 显示处理后的随机两位整数
For I = 1 To UBound(N, 1)
Print LTrim$(Str(N(I))) + " ";
If I Mod 15 = 0 Then Print '一行显示 15 个数据后换行
Next I
Print: Print
End Sub
Private Sub Command3_Click( )
End
End Sub
第5章 数组和数据结构基础 163
2.“显示杨辉三角形”程序
【实例】 “显示杨辉三角形”程序运行后,自动调出一个“输入行数”对话框,在该
对话框的文本框中输入要显示的杨辉三角形的行数,然后按回车键或单击“确定”按钮,即
可按输入的数值显示杨辉三角形,如图 5-3-17 所示。
图 5-3-17 “显示杨辉三角形”程序运行结果
For J = 1 To I
Print Tab(65 - 4 * I + 8 * (J - 1)); LTrim$(Str$(A(I, J)));
Next J
Print
Next I
End Sub
Private Sub Command1_Click( )
End
End Sub
5.4 数据的排序
5.4.1 什么是排序
排序是数据处理中经常使用的一种重要运算,其功能是按照数据元素中的关键字的值,
将一组任意排列的数据元素重新排列,成为一个按关键字值增加(或减少)排列的升序序列(或
降序序列)。排序的目的是便于以后在已排序的集合中查找(检索)出某一个或多个符合要求
的数据。日常生活中通过排序以便于检索的例子很多,例如:学生成绩表、通讯录、工资报
表、电话号码簿、图书查阅表、新华字典、货物库存表和运动员名次表等。
在计算机数据库系统中,查找(即检索)也同样是使用次数最多的操作。无序的数据序
列,只能采用顺序查找方式进行检索,其效率极低。对于经过排序的有序序列进行检索,可
以大大提高工作效率。
在现今的计算机系统中,花费在排序和查找上的时间占系统 CPU 的运行时间的比重是非
常大的,几乎占用的 CPU 的运行时间的 70%,因此为了提高计算机的工作效率,学习与研
究数据元素的各种排序方法是非常重要的。
1.排序运算的定义
假设含有 n 个数据元素的线性表为{R1,R2, …, Rn},其相应的关键字线性表为{K1,K2, …,
Kn}。这样一些数据元素重新排列后的线性表为{Ri1,Ri2, …, Rin},使得相应的关键字序列满
足条件 Ki1<=Ki2<=…Kin-1<=Kin 或 Ki1>=Ki2>=… Kin−1>=Kin。这样的一种运算称为排序。
由于数据元素的形式、数量和所存放的存储设备不同,排序所采用的方法也不同。按照
排序过程涉及的存储设备的不同,排序可分为内部排序和外部排序两大类。内部排序是指在
排序的整个过程中,数据全部存放在计算机的内存储器中,并且在内存储器中调整数据元素
间的相对位置,它适用于数据元素个数不太多的较小的文件;外部排序是指在排序过程中,
数据的主要部分存放在外存储器中,借助内存储器逐步调整记录元素间的相对位置,适用于
数据元素个数比较多的,不能一次将其全部记录都放入内存的较大的文件。下面主要讨论内
部排序的一些方法。
2.排序方法简介
排序的方法很多,主要有选择排序法(也叫比较换位排序法)、一次换位排序法、冒泡
排序法、穿梭排序法、顺序找序排序法和选大排序法等。各种排序方法的优劣主要取决于其
排序的效率,即算法的时间复杂度及算法的空间复杂度。
第5章 数组和数据结构基础 165
在下面的讨论中,使用一维数组待排序的线性表,并且将排序完成后的数据元素仍然
保存在一维数组中。每种排序方法中都有升序(递增,由小到大)和降序(递减,由大到
小)两种方法,升序排序方法与降序排序方法几乎完全相同,只是改变算法中比较的大小
关系。为了讨论方便,下面讨论中使用的参与排序的是一维数组中的数据元素,数据元素
的个数为 5。
5.4.2 排序运算的算法
1.选择排序法
选择排序法也叫比较换位法或最大元素法(或最小元素法),它比较简单,第一轮从 n
个数据元素中找出最大的那一个,让这个最大的数据元素与第 1 个数据元素互换。这时,最
大的数据元素处于第 1 的位置上。第二轮从剩下的 n-1 个数据元素中找出最大的一个,将它
与第 2 个位置处的数据元素互换。经过 n-1 轮的选择排序后,原来无序的序列就成为一个降
序的序列。
例如:有一个数组 N,它有 5 个数据元素,将它们进行选择排序的过程是:将 N(1)与
N(2)到 N(5)中各数据逐一进行比较,若前者小于后者,则两个下标变量的值互换。全部比较
完后,N(1)中存放的是最大的数。然后,再将 N(2)与 N(3)到 N(5)中各数据逐一进行比较,若
前者小于后者,则两个下标变量的值互换。全部比较完后,N(2)中存放的是第 2 大的数。如
此进行下去,直到将 N(4)与 N(5)的数据进行比较和更换后为止。
可以采用一个外循环,循环变量为 I,让 I 取值从 1 到 4;再利用一个内循环,循环变量
为 J,让 J 取值从 I 到 4;将 N(I)与 N(I+1)到 N(5)中各数据逐一进行比较,完成上述的比较换位,
就可以实现从大到小的排序了。
例如,在 N 数组中有 5 个下标变量,这些变量的值是:N(1)=18、N(2)=29、N(3)=52、
N(4)=36,N(5)=40。5 个数据排序的过程如表 5-4-1 所示。
表 5-4-1 比较换位排序过程(从大到小降序排序)
轮 次 I J N(1) N(2) N(3) N(4) N(5) 注 释
开始 0 0 18 29 52 36 40 没排序前情况
l 2 29 18 52 36 40 N(1)、N(2)互换
1 3 52 18 29 36 40 N(1)、N(3)互换
第一轮
1 4 52 18 29 36 40 N(1)与 N(4)比较
1 5 52 18 29 36 40 N(1)与 N(5)比较
2 3 52 29 18 36 40 N(2)、N(3)互换
2 5 52 40 18 29 36 N(2)、N(5)互换
3 4 52 40 29 18 36 N(3)、N(4)互换
第三轮
3 5 52 40 36 18 29 N(3)、N(5)互换
第四轮 4 5 52 40 36 29 18 N(4)、N(5)互换
2.一次换位排序法
一次换位排序法与比较换位排序法基本一样,只是在每一轮中,前一个数 N(I)与其后的
166 中文 Visual Basic 6.0 实用教程—结构化程序设计
4.穿梭排序法
穿梭排序是一种冒泡排序法的变形。假设要排序的数据存放在数组 N 中,共有 N(1)=28、
N(2)=19、N(3)=52、N(4)=36,N(5)=49 个数据元素。这种排序方法(降序排序)的排序过程如下。
(1)第一轮,N(2)与 N(1)比较换位,如果 N(2)>N(1),则互换数据,大的存于 N(1)中。
(2)第二轮,N(3)与 N(2)比较,如果 N(3)>N(2),则互换数据,大的存于 N(2)中;再将
N(2)与 N(1)比较,大的存于 N(1)中。
(3)第三轮,N(4)与 N(3)比较,大的存于 N(3)中;将 N(3)和 N(2)比较,大的存于 N(2)
中;将 N(2)与 N(1)比较,大的存于 N(1)中。
(4)第四轮,N(5)与 N(6)比较,大的存于 N(4)中;将 N(4)与 N(3)比较,大的存于 N(3)
中;将 N(3)和 N(2)比较,大的存于 N(2)中;将 N(2)与 N(1)比较,大的存于 N(1)中。上述过
程如表 5-4-3 所示。
表 5-4-3 穿梭排序法(从大到小降序排序)
第一轮 第二轮 第三轮 第四轮
次数
开 1 2 3 4 5 6 7 8 9 10
I=2 I=3 I=3 I=4 I=4 I=4 I=5 I=5 I=5 I=5
变量
始 J=3 J=2 J=4 J=3 J=2 J=5 J=4 J=3 J=2
N(1) 28 28 28 52 52 52 52 52 52 52 52
N(2) 19 19 52 28 28 36 36 36 36 49 49
N(3) 52 52 19 19 36 28 28 28 49 36 36
N(4) 36 36 36 36 19 19 19 49 28 28 28
N(5) 49 49 49 49 49 49 49 19 19 19 19
注:外循环变量为 I,其初值为 2,内循环变量为 J,其初值也为 I。外循环变量 I 用来确定每一轮中变量 J 取值的初值 I,
每次比较后变量 J 取值减 1,直到 I 为 2;每轮过后,变量 I 取值加 1,直到变量 I 取值为 5。在各轮比较中,都是进行 N(J)和 N(J−1)
两项的比较。当 I=2 时,只进行 N(2)与 N(1)两项比较。
5.顺序找序排序法
顺序找序排序法是对于数组 N 中的各个数据元素,依次检查它们在整个数组数据中有多
少个数据元素大于它,则它就排第几位的后一位。此方法对于有相同的数据时,相同数据的
排号一样。排序后的数可存入另一个数组 M 中。
6.选大排序法
选大排序法与一次换位排序法基本相同,不同的是,它是将选出的最大的数据赋给数组
M 的下标变量,而一次换位排序法是与每轮排序中最大的下标变量进行数据交换。
选大排序法的排序过程是:从数组 N 中选出最大的,将其赋值给数组 M 的下标变量 M(1),
再将其赋值一个最小的数。然后,再从数组 N 中选最大的数,将其赋值给数组 M 的下标变
量 M(2)……以后重复上述的操作。对于 n 个数应进行 n 轮操作,每轮进行 n−1 次比较。在相
应的程序中,需要使用一个变量(例如:MAXS)来保存比 N(I)大的数据元素,以及使用一
个变量(例如:MAXH)来保存比 N(I)大的数据元素的序号。
5.4.3 项目实现
1.“选择排序”程序
【实例】 “选择排序”程序运行后,单击窗体中的“创建线性表”按钮,即可创建一
168 中文 Visual Basic 6.0 实用教程—结构化程序设计
个有 30 个互不相同的两位整数的线性表(数组 N),同时在窗体中分三行显示这个线性表的
30 个数据元素。单击“升序排序”按钮,
即可按从小到大升序排序线性表中的 30
个数据元素,同时分三行显示。单击“降
序排序”按钮,即可按从大到小降序排序
线性表中的 30 个数据元素,同时分三行显
示。依次单击 3 个按钮后的窗体显示效果
如图 5-4-1 所示。
图 5-4-1 “选择排序”程序运行后的画面
窗体中的按钮从上到下,其名称分别
为 Command1,Command2,
…,Command4。
“选择排序”程序代码如下。
Dim N( ) As Integer
Dim I, J, Q As Integer
Rem 创建并显示 30 个互不相同的随机两位数
Private Sub Command1_Click( )
ReDim Preserve N(1 To 30) As Integer
Cls '将窗体清干净
Print: Print: Print
Rem 创建 30 个互不相同的随机两位数
Randomize
For I = 1 To 30
N(I) = Int(Rnd * 90) + 10
Rem 将新产生的随机数与以前成生的随机数进行比较,如果有相同的,则重新产生
For J = 1 To I - 1
If N(I) = N(J) Then I = I - 1: Exit For
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
FontSize = 12
ForeColor = RGB(0, 0, 255)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从小到大升序排序
Private Sub Command2_Click( )
For I = 1 To 29
For J = I + 1 To 30
If N(I) > N(J) Then '如果 N(I) > N(J),则将它们的数据互换
Q = N(I): N(I) = N(J): N(J) = Q
End If
Next J
第5章 数组和数据结构基础 169
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 1 To 29
For J = I + 1 To 30
If N(I) < N(J) Then '如果 N(I) < N(J),则将它们的数据互换
Q = N(I): N(I) = N(J): N(J) = Q
End If
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Private Sub Command4_Click( )
End
End Sub
2.“一次换位排序”程序
【实例】 “一次换位排序”程序运行后,单击窗体中的“创建线性表”按钮,即可创建
一个有 30 个互不相同的两位整数的线性表
(数组 N) ,同时在窗体中分三行显示这个线
性表的 30 个数据元素。单击“升序排序”按
钮,即可按从小到大升序排序线性表中的 30
个数据元素,同时分三行显示。单击“降序排
序”按钮,即可按从大到小降序排序线性表中
的 30 个数据元素,同时分三行显示。依次单
图 5-4-2 “一次换位排序”程序运行后的画面
击 3 个按钮后的窗体显示效果如图 5-4-2 所示。
窗体中的按钮名称采用默认值。“一次换位排序”程序代码如下。
Dim N(1 To 30) As Integer
Dim I, J, Q, MINS, MAXS, MINH, MAXH As Integer
Rem 创建并显示 30 个互不相同的随机两位数
Private Sub Command1_Click( )
170 中文 Visual Basic 6.0 实用教程—结构化程序设计
Cls '将窗体清干净
Print: Print: Print
Rem 创建 30 个互不相同的随机两位数
Randomize
For I = 1 To 30
N(I) = Int(Rnd * 90) + 10
Rem 将新产生的随机数与以前成生的随机数进行比较,如果有相同的,则重新产生
For J = 1 To I - 1
If N(I) = N(J) Then I = I - 1: Exit For
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
FontSize = 12
ForeColor = RGB(0, 0, 255)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从小到大升序排序
Private Sub Command2_Click( )
For I = 1 To 29
MINS = N(I): MINH = I
For J = I + 1 To 30
If MINS > N(J) Then '如果 MINS > N(J),则将它们的数据互换
MINS = N(J): MINH = J
End If
Next J
N(MINH) = N(I): N(I) = MINS
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 1 To 29
MAXS = N(I): MAXH = I
For J = I + 1 To 30
If MAXS < N(J) Then '如果 MINS < N(J),则将它们的数据互换
MAXS = N(J): MAXH = J
End If
第5章 数组和数据结构基础 171
5.4.4 项目拓展
1.
“穿梭排序”程序
【实例】 “穿梭排序”程序运行后,依次单击窗体中的按钮后,即可在窗体中分三行
第5章 数组和数据结构基础 173
图 5-4-4 “穿梭排序”程序运行后的画面
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 2 To 30
For J = I To 2 Step -1
If N(J) > N(J - 1) Then '如果 N(J) > N(J-1),则将它们的数据互换
Q = N(J - 1): N(J - 1) = N(J): N(J) = Q
End If
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Private Sub Command4_Click( )
End
End Sub
2.“顺序找序排序”程序
【实例】 “顺序找序排序”程序运行后,依次单击窗体中的按钮后,即可在窗体中分
三行显示一个线性表的 30 个数据元素,再
分三行按从小到大升序排序显示线性表中
的 30 个数据元素,分三行按从大到小降序
排序显示线性表中的 30 个数据元素,如图
5-4-5 所示。
窗体中的按钮从上到下,其名称分别
为 Command1 到 Command4。“穿梭排序”
图 5-4-5 “顺序找序排序”程序运行后的画面 程序代码如下。
Dim N(1 To 30), M(1 To 30) As Integer
Dim I, J, Q, MAXS, MINS As Integer
Rem 创建并显示 30 个互不相同的随机两位数
Private Sub Command1_Click( )
第5章 数组和数据结构基础 175
M(Q) = N(I)
Next I
Rem 显示 30 个互不相同的随机两位数
ForeColor = RGB(255, 0, 0)
For I = 1 To 30
Print RTrim$(Str(M(I))); " ";
If I Mod 10 = 0 Then Print
Next I
Print
End Sub
Private Sub Command4_Click( )
End
End Sub
3.“选大排序”程序
【实例】 “选大排序”程序运行后,
依次单击窗体中的按钮后,即可在窗体中
分三行显示一个线性表的 30 个数据元素,
再分三行按从小到大升序排序显示线性
表中的 30 个数据元素,分三行按从大到
小降序排序显示线性表中的 30 个数据元
素,如图 5-4-6 所示。
窗体中的按钮从上到下,其名称分别
图 5-4-6 “选大排序”程序运行后的画面 为 Command1 到 Command4。“穿梭排序”
程序代码如下。
Dim N(1 To 30), S(1 To 30), M(1 To 30) As Integer
Dim I, J, Q, MINS, MAXS, MINH, MAXH As Integer
Rem 创建并显示 30 个互不相同的随机两位数
Private Sub Command1_Click( )
Cls '将窗体清干净
Print: Print: Print
Rem 创建 30 个互不相同的随机两位数
Randomize
For I = 1 To 30
N(I) = Int(Rnd * 90) + 10: S(I) = N(I)
Rem 将新产生的随机数与以前成生的随机数进行比较,如果有相同的,则重新产生
For J = 1 To I - 1
If N(I) = N(J) Then I = I - 1: Exit For
Next J
Next I
Rem 显示 30 个互不相同的随机两位数
FontSize = 12
ForeColor = RGB(0, 0, 255)
For I = 1 To 30
Print RTrim$(Str(N(I))); " ";
第5章 数组和数据结构基础 177
思考与练习
1.填空题
(1)数组是 ,数组元素是 。
(2)数组可分为 和 两种。
(3)常规数组是 的数组,动态数组是 的数组。常规数组中包含的数组
元素个数是 的,它总保持同样的 ,占有的存储空间也保持 。
(4)数组的下标变量一定要在 后才可以使用。
(5)数组用一个统一的名称来标识 ,这个名称就是 。组成数组的元素
统称为 ,也叫 ,它由 和括号内的 组成的。
(6)数组名的命名规则与 的命名规则一样。
(7)在数组中,对数组元素的区分用 来实现,数组下标的个数称为数组的维数。
有了数组,就可以用 来表示一系列的数据。
(8)下表变量中的下标可以是 、 和 。
2.分析下面 Visual Basic 程序的运行结果
(1)程序 1
Dim N(1 To 10) As Integer
Dim I As Integer
Private Sub Form_Activate( )
For I = 1 To 10
N(I) = (I + 9) * 2
Next I
For I = 1 To 10
Print Str(N(I)); " ";
If I Mod 5 = 0 Then Print
Next I
End Sub
(2)程序 2
Dim N(1 To 5, 1 To 5) As String
Dim I, J As Integer
Private Sub Form_Activate( )
For I = 1 To 5
For J = 1 To 5
N(I, J) = LTrim$(Str$(I)) + LTrim$(Str$(J))
Print N(I, J); " ";
Next J
Print
Next I
Print: Print
For I = 1 To 5
For J = 1 To 5
Print N(I, J); " ";
第5章 数组和数据结构基础 179
Next J
Print
Next I
End Sub
(3)程序 3
Dim N(1 To 5, 1 To 5) As String
Dim I, J As Integer
Private Sub Form_Activate( )
For I = 1 To 5
For J = 1 To 5
N(I, J) = LTrim$(Str$(I)) + LTrim$(Str$(J))
Print N(I, J); " ";
Next J
Print
Next I
Print: Print
For I = 5 To 1 Step -1
For J = 5 To 1 Step -1
Print N(I, J); " ";
Next J
Print
Next I
End Sub
(4)程序 4
Dim N(1 To 5, 1 To 5) As String
Dim I, J As Integer
Private Sub Form_Activate( )
For I = 1 To 5
For J = 1 To 5
N(I, J) = LTrim$(Str$(I)) + LTrim$(Str$(J))
Print N(I, J); " ";
Next J
Print
Next I
Print: Print
For I = 1 To 5
For J = 5 To 1 Step -1
Print N(6 - I, 6 - J); " ";
Next J
Print
Next I
End Sub
(5)程序 5
Dim N(1 To 5, 1 To 5) As String
Dim I, J As Integer
180 中文 Visual Basic 6.0 实用教程—结构化程序设计
(4)编写一个程序,该程序运行后,随机产生一组互不相同的两位随机整数,然后两次
通过键盘输入两个两位整数,如果输入的数据与数组中的数据相同,则删除数组中的相应数
据,如果输入的数据与数组中的所有数据均不相同,则在数组的最后插入不相等的数据。
(5)某班第 1 小组学生的期末考试成绩如下表所示。编写程序,输入学生的学号、姓名
和各科成绩,并保存在二维数组 N 中。然后,统计每个学生的总分和平均分,再按照总分从
大到小排序显示出每个学生的学号、姓名、各科成绩、总分和平均分。
学 习 成 绩
学 号 姓 名
数 学 语 文 外 语 物 理
001 张颖 70 68 89 93
005 池尚萌 86 76 89 69
006 姜昆跃 66 87 86 69
007 周小华 88 89 87 99
008 毛岸麟 82 76 83 99
(6)编写一个程序,该程序运行后,可以根据输入的数据(1 到 15)显示由输入数据确
定的行数的倒杨辉三角形。
(7)编写一个程序,该程序运行后,产生 10 个两位的随机奇数,将它们显示出来,然
后按从大到小的顺序排列,显示排序后的结果,并显示它们原来的位置号。
(8)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵元素是随机的互不相同的
两位正整数。然后,将该矩阵的两个对角线上的数据元素保留原数值,其他数据元素改为 0。
(9)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵元素是随机的互不相同
的两位正整数。找出其中最大的数和最小的数,并显示它们和它们的行号和列号。
(10)编写一个程序,该程序运行后,创建一个有 30 个数据元素的一维数组 N,数组元
素是随机的互不相同的两位正整数,显示该数组中的所有数组元素。然后,将该数组中的奇
数按照升序序列排在前面,将该数组中的偶数按照降序序列排在后面,同时显示重新处理过
的数组元素。
(11)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵元素是随机的互不相
同的两位正整数。其中矩阵对角线上的数据元素是偶数,其他数据元素是奇数。
(12)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵两条对角线上的数据
元素是零,其他元素是随机的互不相同的两位正整数。
(13)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵一条对角线(右上角
到左下角)上的数据元素是零。由零数据元素分割出的两部分,其中上边的数据元素是偶数,
下边的数据元素是奇数。
(14)编写一个程序,该程序运行后,创建一个 10×10 矩阵,矩阵元素是随机的互不相
同的两位正整数。找出既是该行最大的,同时又是该列最小的数,并显示它们的行号和列号。
该元素所在的点叫“鞍点” 。
182 中文 Visual Basic 6.0 实用教程—结构化程序设计
(15)编写一个程序,该程序运行后,产生 10 个随机的互不相同的两位正整数。假设这
10 个数字排成一圈,将它们每个数与周围的两个数相加,得到 10 个数,显示这 10 个数,同
时显示这 10 个数中最大和最小的两个数。
(16)幼儿园有 20 个小朋友坐成一圆圈,玩数学游戏。方法是按号由 1 到 20 坐好,从
第一个小朋友开始报数,报到 5 时,这个小朋友就退出圆圈外,并且不再参加报数。别的朋
友继续报数,再报到 5 时,这个小朋友也退出,如此继续,直到 20 个小朋友全部退出。编写
一程序,显示每次退出圆圈的小朋友的原始序号。
过程和自定义数据类型
第 6章
6.1 求 组 合 数
6.1.1 过程
1.什么是过程和过程的分类
在设计一个规模较大、功能较复杂的 Visual Basic 程序时,常常需要完成许多功能,这
些功能相互之间是彼此独立的,因此可以按照功能将程序分解成若干相对独立的部件,可以
用不同的程序段来实现不同的功能,Visual Basic 称这些程序段部件为过程。对每个过程分别
编写程序,可以简化程序设计任务。Visual Basic 语言的程序设计,就如同搭积木一样,是由
若干个程序段按照一定的方式有机组合而成的,这就是结构化程序设计的方法。其中的每一
个程序段都称为一个过程,每个过程都有一个名字,每个过程既可以调用其他过程,也可以
被其他过程调用。过程的程序段特点主要体现在过程与过程之间的数据输入、输出,即与其
他程序之间的数据传递。使用过程的好处是使程序简练,便于调试和维护。
Visual Basic 中有两类过程,一类是系统提供的过程,主要有内部函数过程和事件过
程,事件过程是构成 Visual Basic 应用程序的主体,前面已大量介绍过了;另一类是由用
户自己定义、可供事件过程多次调用的自定义过程。在 Visual Basic 中,自定义过程分为
以下几种。
① 以“Sub”保留字开始的子过程(Sub Procedure):该过程不返回值。
② 以“Function”保留字开始的函数过程(Function Procedure):该过程返回一个值。
③ 以“Property”保留字开始的属性过程(Property Procedure)
:该过程可以返回和设置
窗体、标准模块以及类模块,也可以设置对象的属性。
此外,还有以“Event”保留字开始的事件过程(Event Procedure)。
本章主要介绍用户自定义过程的子过程和函数过程,它们又可称为通用过程。通用过程
是指必须由其他过程调用的程序代码段,它是由用户自己创建的。因为通用过程可以被其他
过程调用,所以可提高程序代码的利用率和可读性。
所有的可执行代码都必须属于某个过程。过程的定义是平行的,不能在别的 Sub,Function
或 Property 过程中定义其他过程。
2.Sub过程
Visual Basic 中有两种 Sub 过程,即系统提供的事件过程和用户自己定义子过程。Sub 过
程可以放在标准模块和窗体模块中,过程的定义语句如下:
184 中文 Visual Basic 6.0 实用教程—结构化程序设计
[Private|Public][Static]Sub 过程名([参数列表])
[局部变量和常数声明]
[程序段]
End Sub
Sub 和 End Sub 之间的程序段(包括局部变量和常数声明语句)是每次调用过程执行的
程序部分。
3.事件过程
Visual Basic 是事件驱动的。所谓事件是指能被对象(窗体和其他控件)识别的动作。例
如:对象的事件有单击(Click)、双击(DblClick)、内容改变(Change)和定时事件(Timer)
等。为一个事件所编写的程序代码,称为事件过程。当 Visual Basic 对象中的某个事件发生
时,会自动调用相应的事件过程。
另外,Sub 事件过程还可以为同一模块中的其他过程中使用调用语句(一个独立的语句)
调用。调用 Sub 过程有两种方式,使用 Call 语句或直接用 Sub 过程名。这种适用语句的调用
方法与自定义的 Sub 子过程的调用方法一样。
事件过程分为窗体事件过程和控件事件过程。事件过程前面的声明都是 Private。
(1)窗体事件过程的语法格式如下:
Private Sub Form_事件名称([参数列表])
[局部变量和常数声明]
[程序段]
End Sub
注意:不管窗体是什么名字,在事件过程中的只能使用“Form_事件名称”,而在程序中
对窗体进行引用才会用到窗体名字。例如,单击窗体事件发生后,将该窗体隐藏而显示“Form1
窗体”的程序代码如下:
Private Sub Form_Click( )
Form1.Show '显示 Form1 窗体,即使它为活动窗体
End Sub
(2)控件事件过程的语法格式如下:
Private Sub 控件名_事件名([参数列表]]
[局部变量和常数声明]
[程序段]
End Sub
例如,第 1 章“选择窗体”程序中,单击“窗体 1”按钮(按钮名称为 Commandl)事件
发生后,将原来显示的窗体隐藏而显示“Form1 窗体”的程序代码如下:
Private Sub Command1_Click( )
Form1.Show '显示 Form1 窗体,即使它为活动窗体
End Sub
6.1.2 通用过程的定义
通用过程是指必须由其他过程调用的程序代码段,它是由用户自己创建的,主要包括 Sub
第6章 过程和自定义数据类型 185
子过程和函数过程,它们都是一个独立的过程。当几个不同的事件过程需要执行同样的动作
时,为了不重复编写代码,可以采用通用过程来实现,由事件过程调用通用过程。通用过程
可以保存在窗体模块(.rrm)和标准模块(.bas)两种模块中。通常,一个通用过程并不与用
户界面中的对象联系,通用过程直到被调用时才起作用。因此,事件过程是必要的,但通用
过程不是必要的,只是为了程序员方便而单独建立的。
Sub 子过程和函数过程的共同点是都完成某种特定功能的一组程序代码;不同之处是函
数过程可以返回一个值到调用它的过程,它是带有返回值的特殊过程,所以函数过程定义时
有返回值的类型说明。Sub 子过程和函数过程都不能嵌套定义,即不能在别的 Sub,Function
或 Property 过程中定义 Sub 过程和函数过程,但它们可以嵌套调用。
Sub 定义子过程和函数过程有以下两种方法。
1.利用代码窗口直接定义
在窗体模块(.frm)或标准模块(.bas)的“代码”窗口中,把光标定位在所有现有过程
之外,然后输入 Sub 子过程或者 Function 函数过程的程序。两种过程的定义格式和格式中各
选项的含义如下。
(1)自定义子过程的格式和格式中各选项的含义如下:
[Static][Public|Private] Sub 子过程名([形参列表])
[局部变量和常数声明]
[程序段]
[Exit Sub]
[程序段]
End Sub
例如:如图 6-1-1 所示,在代码编辑器中输入的程序代码是用来添加一个 Sub 子过程。
图 6-1-2 在代码编辑器中输入的程序代码用来添加一个自定义函数过程
• As 数据类型:用来定义函数返回值的数据类型。它与变量一样,如果没有 As 子句,
缺省的数据类型为变体类型(Variant)。
• Exit Function 语句:用来提前从 Function 过程中退出,程序接着从调用该 Function 过
程的语句的下一条语句继续执行。在 Function 过程的任何位置都可以有 Exit Function 语句。
但用户退出函数之前,必须保证为函数赋值,否则会出错。
• 函数名=表达式:函数名是函数过程的名称,它遵循标准的变量命名约定。表达式的
值是函数过程的返回值,通过赋值号将其值赋给函数名。如果在 Function 过程中省略该语句,
则该 Function 过程的返回值为数据类型的缺省值。例如,数值函数返回值为 0,字符串函数
返回值为空字符串。在函数体内至少对函数名赋值一次。
• 程序段:描述过程的操作,称为子函数体或函数体。它是 Visual Basic 的语句序列,
程序中可以用 Exit Function 语句从函数过程中退出。
• Exit Function:表示退出函数过程。
(3)形参列表:形参表中的参数称为形参,它类似于变量声明,列出从调用过程的主程
序传递来的参数值,称为形式参数(简称形参),多个形参之间用逗号隔开。
第6章 过程和自定义数据类型 187
形参列表用于接受调用过程时传递过来的值,指明了传送给过程的变量个数和类型。形
参列表中的形参可以是除定长字符串之外的合法变量,还可以是后面带括号的数组名(若括
号内有数字,则一般表示数组的维数)。参数的默认值为变体(Variant)数据类型。
形参不能用定长字符串变量或定长字符串数组作为形式参数。不过可以在 Call 语句
中用简单定长字符串变量作为实际参数,在调用 Sub 过程之前,把它转换为变长字符串
变量。定义 Sub 子过程和函数过程时,可以没有参数,但定义无参数的函数过程时,必
须有括号。
形参列表的格式如下:
[ByVal|ByRef ][ParamArray] 变量名 [( )][As 类型][,……]
形参列表中各选项的含义简介如下。
• ByVal:表示该过程被调用时,参数是按值传递,简称传值。
• ByRef:表示该参数按址传递,简称传址。ByRef 是 Visual Basic 的默认选项。
• ParamArray:使用它可以提供任意数目的参数。ParamArray 关键字不能与 ByVal 或
ByRef 一起使用。
• 变量名:它代表参数的变量名称,遵循标准的变量命名约定。
• As 类型:函数返回值的类型,若省略它,则返回变体类型(Variant)数据。
2.使用菜单命令的方法
(1)打开要编写函数和子过程的窗体或标准模块的“代码”窗口。
(2)单击“工具”→“添加过程”菜单命令,调出“添
加过程”对话框,如图 6-1-3 所示。
(3)在“添加过程”对话框的“名称”文本框中输入
过程的名称(不允许有空格) 。
(4)在“类型”栏中,单击选中“子程序”单选钮,
可以定义 Sub 子过程;单击选中“函数”单选钮,可以定
义函数过程。
(5)在“范围”栏中,单击选中“公有的”单选钮, 图 6-1-3 “添加过程”对话框
可以定义一个公共级的全局过程;单击选中“私有的”单选钮,可以定义一个标准模块级或
窗体级的局部过程。
(6)单击“确定”按钮,Visual Basic 会自动在“代码”窗口中创建一个函数过程或 Sub
子过程的模板,即过程的开始和结束语句。
例如:在“添加过程”对话框中输入的过程名称为“My_Program”,如果选中“子程序”
和“公有的”单选钮,则“代码”窗口如图 6-1-4 所示。如果选中“函数”单选钮,选中“私
有的”单选钮,则“代码”窗口如图 6-1-5 所示。
(7)在开始和结束语句之间输入程序代码。
6.1.3 通用过程的调用
1.Sub子过程的调用
因为 Sub 子过程不能返回一个值,所以 Sub 子过程不可以在表达式中调用。调用子过程
是利用了一个独立的语句。调用 Sub 子过程有如下两种方法:
Sub 子过程名[实参列表]
Call Sub 子过程名(实参列表)
其中,实参列表是传送给 Sub 子过程的变量或常量的列表,各参数之间应用逗号分隔。
实参还可以是数组和表达式。用数组名称时,其后应有空括号,用来指定数组参数。例如,
调用一个名称为 MyProgram 的子过程(a 和 b 是实参数)
,可采用如下两种方式:
MyProgram a,b
Call MyProgram(a,b)
注意:用过程名调用,没有参数时必须省略参数两边的( )。使用 Call 语句调用时,参数
必须在括号内,当被调用过程没有参数时,则( )也可省略。
调用 Sub 子过程的语法与调用 Sub 事件过程的语法相同。不同的是,Sub 子过程只有被
调用时才起作用,否则不会被执行。
2.函数过程的调用
调用函数过程的方法与调用 Visual Basic 系统内部函数(例如:Abs(X))的方法一样,
在语句中直接使用函数名称,函数过程可以返回一个值到调用的过程。由于函数过程可返回
一个值,故函数过程不能作为单独的语句加以调用,被调用的函数必须作为表达式或表达式
中的一部分,再配以其他的语法成分构成语句。
函数过程名([实参列表])
例如,有自定义函数 Hsjl,它的形参有两个,可以有如下一些调用方法。
Print Hsjl(5,8) '在窗体中显示函数值
N= Hsjl(4,8)*5 '在赋值语句中使用函数过程
If Hsjl(2,6)*5=10 Then N=Hsjl(5,8) '在分支语句中使用函数过程
N=Abs(Hsjl(3,9)) '在系统函数中使用函数过程
另外,还可以采用调用 Sub 子过程的方法来调用函数过程,但是采用这种方法调用函数
过程后,会放弃函数过程的返回值。
3.过程调用时应注意的几点
(1)实参表中的参数称为实参,实参可由常量、变量和表达式以及数组名(其后有括号)
组成,实参之间用逗号分隔。它必须与形参保持个数相同,位置与类型一一对应。但是,它
们的名字可以不相同。
(2)调用时把实参的值传递给形参称为参数传递,这种传递是按次序一一对应的。参数
传递有两种方式,一是按值传递(形参前有 ByVal 说明),实参的值不随形参的值变化而改变;
二是按址传递,实参的值随形参值的改变而改变。
(3)过程不能嵌套定义,即不允许在一个过程中再定义另外的过程,但可以在一个过程
中调用另外的过程,即可以嵌套调用。
第6章 过程和自定义数据类型 189
6.1.4 项目实现
1.
“调子过程求组合数”程序
m N!
【实例】 设计一个求公式 C n = 的程序。其中,N 和 M 由键盘输入。
M !( N − M )!
在“调子过程求组合数”程序中,把求阶乘的程序内容定义为 Sub 子过程,然后通过多
次调用 Sub 子过程来计算出结果。程序运行的画面如图 6-1-6 所示,输入 N 和 M 的数值之后,
单击“调子程序计算”按钮,即可显示计算结果,如图 6-1-7 所示。
“调子过程求组合数”程序的窗口设计可参看图 6-1-6,文本框和标签的名称采用默认值,
用于输出数据的标签的名称属性为“Label6”,“调子程序计算”按钮的名称为“调子程序”,
“退出”按钮的名称为“退出”,其他属性设置由读者自行完成。
“调子过程求组合数”程序代码如下。
Rem 调用子过程的主过程
Private Sub 调子程序_Click( )
Dim N, M, NM As Integer, S As String, ZJC As Long
N = Text1.Text
M = Text2.Text
N1 = N: Call ZQJC(N1, ZJC): N1 = ZJC '求 N 的阶乘,并赋给 N1
M1 = M: Call ZQJC(M1, ZJC): M1 = ZJC '求 M 的阶乘,并赋给 M1
NM = N - M: Call ZQJC(NM, ZJC): NM = ZJC '求 N-M 的阶乘,并赋给 NM
S = "C(" + Str$(N) + "," + Str$(M) + ")=" + Str$(N1 / (M1 * NM))
Label6.Caption = S
End Sub
Rem 求阶乘的子过程
Public Sub ZQJC(ByVal K As Integer, JC As Long)
Dim I As Integer
JC = 1
For I = 1 To K
JC = JC * I
Next I
End Sub
Private Sub 退出_Click( )
End
End Sub
190 中文 Visual Basic 6.0 实用教程—结构化程序设计
“调函数求组合数”程序的窗口设计可参看图 6-1-8,文本框和标签的名称采用默认值,
用于输出数据的标签的名称属性为“Label6”,“调函数计算”按钮的名称为“调函数”,“退
出”按钮的名称为“退出”,其他属性设置由读者自行完成。
“调函数求组合数”程序代码如下。
Rem 调用函数过程的主过程
Private Sub 调函数_Click( )
Dim N, M As Integer, S As String
N = Text1.Text '将文本框 Text1 中的数字赋给变量 N
M = Text2.Text '将文本框 Text2 中的数字赋给变量 M
S = "C(" + Str$(N) + "," + Str$(M) + ")=" + Str$(HQZH(N, M))
Label6.Caption = S
End Sub
Public Function HQZH(ByVal N As Integer, ByVal M As Integer) '求组合数的函数过程
HQZH = HQJC(N) / (HQJC(M) * HQJC(N - M)) '将计算结果赋函数 HQZH
End Function
Rem 求阶乘的函数过程
Public Function HQJC(ByVal K As Integer)
Dim I As Integer, JC As Long
JC = 1
For I = 1 To K
JC = JC * I
Next I
HQJC = JC
End Function
Private Sub 退出_Click( )
End
End Sub
6.1.5 项目拓展
1.
“两个自然数的最大公约数和最小公倍数”程序
【实例】 根据第 4 章第 4.4 节介绍的辗转相除法可以求出两个自然数 A 和 B 的最大公约
数 Q,两个数 A、B 的最小公倍数等于这两个数的乘积 A*B,再除以这两个数的最大公约数
Q,即最小公倍数 S=A*B/Q。辗转相除法的算法再简介如下。
(1)计算输入的自然数 M 除以输入的自然数 N 的余数 R,R=M Mod N。
(2)用自然数 N 替换自然数 M,N=M;用 R 替换 N,N=R。
(3)如果 R<>0,则重复步骤(1)和(2)。
程序运行后的窗体画面如图 6-1-10 所示,单击“调子程序计算”按钮或“调函数计算”
按钮,即可显示计算结果,如图 6-1-11 所示。
程序的窗口设计可参看图 6-1-10 进行,文本框和标签的名称采用默认值,用于输出最大
公约数的标签的名称属性为“Label6”,用于输出最小公倍数的标签的名称属性为“Label7” ,
“调子程序计算”按钮的名称为“调子程序” ,“调函数计算”按钮的名称为“调函数”,“退出”
按钮的名称为“退出”,其他属性设置由读者自行完成。
程序的窗口设计可参看图 6-1-12,用于输入数据的文本框名称为“Text1”,用于显示结
果的标签名称为“Label4”,“函数计算”按钮的名称为“调函数”,“子程序计算”按钮的名
称为“调子程序”,“退出”按钮的名称为“退出”,其他属性设置由读者自行完成。
程序代码如下。
em 调用函数过程的主过程
Private Sub 调函数_Click( )
Dim I, S, N As Integer
N = Text1.Text '将文本框中的数字赋给变量 N
For I = 3 To N Step 2 '产生 3 到 N 中间的奇数
S=I '将变量 I 的值赋给变量 S
If HSSS(S) = 1 Then '如果函数值为 1,则说明 I 是素数
S=N-I '将 N-I 的值赋给变量 S
If HSSS(S) = 1 Then Exit For '如果函数值为 1,则脱离循环
End If
Next I
S = XSHSJG(I, N) '调用显示函数程序
If N = 4 Then Label4.Caption = "4=2+2" '如果 N=4,重新显示结果
End Sub
Rem 判断是否为素数的函数过程
Public Function HSSS(ByVal S1 As Integer)
Dim J As Integer
K1 = 1 '变量 K1 为 1 时,是素数,否则不是
For J = 2 To Sqr(S1) '进行素数判断
If S1 / J = Int(S1 / J) Then K1 = 0: Exit For '如果可以整除,则不为素数,退出循环
Next J
HSSS = K1 '将判断结果赋函数
End Function
Rem 显示函数
Public Function XSHSJG(ByVal I As Integer, ByVal N As Integer)
Label4.Caption = Str$(N) + "=" + Str$(I) + "+" + Str$(N - I)
End Function
Rem 调用子过程的主过程
Private Sub 调子程序_Click( )
Dim I, S, N, K As Integer
N = Text1.Text
For I = 3 To N Step 2
S=I
Call ZCHSS(S, K) '调判素数子程序
If K = 1 Then
S=N-I
Call ZCHSS(S, K) '调判素数子程序
If K = 1 Then Exit For
End If
Next I
Call XSZCHJG(I, N) '调显示子程序
If N = 4 Then Label4.Caption = "4=2+2"
194 中文 Visual Basic 6.0 实用教程—结构化程序设计
End Sub
Rem 判断是否为素数的子过程
Public Sub ZCHSS(ByVal S1 As Integer, K1 As Integer)
Dim J As Integer
K1 = 1
For J = 2 To Sqr(S1)
If S1 / J = Int(S1 / J) Then K1 = 0: Exit For
Next J
End Sub
Rem 显示子程序
Public Sub XSZCHJG(ByVal I As Integer, ByVal N As Integer)
Label4.Caption = Str$(N) + "=" + Str$(I) + "+" + Str$(N - I)
End Sub
Private Sub 退出_Click( )
End
End Sub
程序代码中,自定义的函数名称为“HSSS”,自定义的 Sub 子过程名称为“ZCHSS”,
显示结果的函数名称为“XSHSJG”,显示结果的 Sub 子程序名称为“XSZCHJG”。
6.2 计算阶乘和
6.2.1 形参和实参
在调用一个有参数的过程时,参数是在本过程有效的局部变量,通过形参和实参来传
递信息,实现调用过程的实参与被调过程的形参之间的数据传递,即将调用过程的实参传
递给被调的子过程或函数中的形参,完成实参与形参数据的传送,然后执行被调过程中的
程序。
在 Visual Basic 中,实参与形参的数据传送有传址和传值两种方法,其中传址是默认的
方法。两种方法的区分标志是关键字 ByVal,形参前加 ByVal 关键字时,是传值;形参前不
加 ByVal 关键字或加 ByRef 关键字时,是传址。
1.形参
被调过程中的参数是形参,它出现在 Sub 子过程和函数过程中。在过程被调用之前,形
参未被分配内存,只是说明形参的类型和在过程中的作用。形参列表中的各参数之间用逗号
“,”分隔,形参可以是变量名和数组名,不可以是定长字符串变量。
2.实参
实参是在主调过程(主过程)中的参数,在过程调用时,实参将数据传递给形参。
形参列表和实参列表中的对应变量名可以不相同,但实参和形参的个数、顺序以及数据
类型必须相同。第一个实参与第一个形参对应,第二个实参与第二个形参对应,依此
类推。
例如,在本章的“两个自然数的最大公约数和最小公倍数”实例的主调过程(主过程)
和函数过程中,形参与实参的结合对应关系(数据传递关系)如图 6-2-1 所示。
第6章 过程和自定义数据类型 195
…… 返回函数值
Q=HSGS(A, B) '调求 M 和 N 最大公约数的函数过程,并赋给 Q
……
End Sub
实参 A 和 B 将数据
传递给形参 N 和 M
Rem 求最大公约数的函数过程 HSGS
Public Function HSGS(ByVal N As Integer, ByVal M As Integer)
……
HSGS=N
End Function
图 6-2-1 实参与形参的数据传递关系
如果传递的参数个数不匹配(例如:主调过程中的实参只
有一个,Q=HSGS(A)),则会产生错误,显示出错信息提示框,
如图 6-2-2 所示。
3.形参的数据类型
在创建过程时,如果没有声明形参的数据类型,则缺省为
Variant 型。例如,将本章的“两个自然数的最大公约数和最小 图 6-2-2 出错信息提示框
公倍数”实例的函数过程中改为 Variant 型,M 为 Integer 型。
Rem 求最大公约数的函数过程 HSGS
Public Function HSGS(ByVal N, ByVal M As Integer)
……
End Function
对于实参数据类型与形参定义的数据类型不一致时,Visual Basic 会按要求对实参进行数
据类型转换,然后将转换值传递给形参。
例如,将本章的“两个自然数的最大公约数和最小公倍数”实例的主调过程的实参 A 的
数据类型改为 Single 型,修改后的主过程如下。
Rem 调用函数过程 HSGS 的主过程
Private Sub 调函数_Click( ) '调用函数过程的主过程
Dim B, Q As Integer, A As Single, S As Long
A = Text1.Text '将文本框 Text1 中的数字赋给变量 N
B = Text2.Text '将文本框 Text2 中的数字赋给变量 M
Q = HSGS(A, B) '调求 M 和 N 最大公约数的函数过程,并赋给 Q
……
End Sub
运行上述程序,在 Text1 文本框内输入 4.3(赋给实参变量 A),在 Text1 文本框内输入 6
(赋给实参变量 B)。当执行 Q = HSGS(A, B)语句时,先将 Single 类型的 A 转换成整型(Integer)
数据 4,然后将数据 4 传递给函数过程中的形参 N,将数据 6 传递给函数过程中的形参 M。
运行结果为:4.3 和 6 的最大公约数是 2,最小公倍数为 12。
4.使用可选的参数
在参数列表中,可以在变量名的左边增加一个关键字 Optional,它表示参数不是必需。
196 中文 Visual Basic 6.0 实用教程—结构化程序设计
如果形参列表中的某个形参变量使用了该关键字 Optional,则该形参后续的参数都必须加关
键字 Optional,设置为可选的。如果使用了 ParamArray,则任何参数都不能使用 Optional。
例如,将本章的“两个自然数的最大公约数和最小公倍数”实例的函数过程中改为:
Rem 求最大公约数的函数过程 HSGS
Public Function HSGS( Optional ByVal N As Integer, Optional ByVal M As Integer)
……
HSGS = N
End Function
如果“两个自然数的最大公约数和最小公倍数”实例主调过程中的实参个数缺少时(如
下所示,缺少实参 B),则实参 B 将作为变体类型(Variant)数据,取值 Empty。运行程序后
不会出现如图 6-2-2 所示的错误信息框,但是也不会得到计算结果。
Rem 调用函数过程 HSGS 的主过程
Private Sub 调函数_Click( ) '调用函数过程的主过程
……
Q = HSGS(A)
……
End Sub
6.2.2 参数的传址与传值
按地址传递参数可在被调过程中改变实参的值。
当参数是字符串或数组时,使用传址传递直接将实参的地址传递给过程,会使程序的效
率提高。使用传址方式时,对应的实参不能是表达式和常数,只可以是变量。
为了使程序可靠和便于调试程序,减少各过程间的关联,一般采用传值方式。当希望实
参的值随着被调过程中形参的变化而改变时,可采用传址方式。
3.数组参数传递
在定义过程时,Visual Basic 允许过程的形参列表中的形参是数组,数组只能通过传址方
式进行传递,形参与实参共有同一段内存单元。在传递数组时须注意以下事项:
(1)在实参列表中,与形参数组对应的实参必须也是数组,数据类型应与形参的数据
一样;
(2)实参列表中的数组的圆括号“( )”不能省略,忽略维数的定义;
(3)如果被调过程不知道实参数数组的上下界,可用 Lbound 和 Ubound 函数来确定实参
数组的下界和上界。Lbound 和 Ubound 函数的形式如下:
Lbound|Ubound(数组名[,维数])
其中:维数指明要测试的是第几维的下标值,默认是一维数组。
4.命名传递
上面讲述的传值和传址方式,都是按照形参和实参在参数列表中的位置一一对应传递
的。有时需要在调用过程语句的实参列表中所写的实参和在过程定义语句的形参表中所写的
形参位置并不一一对应,这时就需要使用命名传递。
使用命名传递,在调用过程语句的实参表中的参数格式为:
<形参>:=<实参>
其含义为:将右边实参的值,传递给左边的形参。
命名传递是采用传值方式还是采用传址方式,应遵从常量和表达式默认采用按值传递,
变量默认采用按址传递。
6.2.3 项目实现
1.
“按传值传递计算阶乘和”程序
【实例】 按照按值参数传递的方法编写计算 6!+5!+4!+3!+ 2!+1!的程序,程序代
码如下。程序运行后,单击窗体,即可显示如图 6-2-3 所示的效果。
图 6-2-3 程序运行后单击窗体产生的效果
FontSize = 12 '设置文字大小
ForeColor = RGB(0, 0, 255) '设置文字颜色为蓝色
For Q = 6 To 1 Step -1
Sum = Sum + HSJC(Q) '进行阶乘的累加
Print Str$(Q) + "!=" & HSJC(Q) '显示各阶乘的值
Next Q
Print "6!+5!+4+3!+2!+1!="; Sum '显示各阶乘和的值
End Sub
Rem 声明函数过程 HSJC
Private Function HSJC(ByVal N As Integer) As Integer
Rem 计算阶乘
HSJC = 1
Do While N > 0
HSJC = HSJC * N '计算累积
N=N-1
Loop
End Function
2.“按传址传递计算阶乘和”程序
【实例】 按照按址参数传递的方法编写计算 6!+5!+4!+3!+2!+1 的程序,它的主程
序不变,只是将程序中的 ByVal 关键字改为 ByRef,或取消 ByVal 关键字。该程序代码如下。
Rem 调函数过程 HSJC 的主程序(单击窗体后产生事件)
Private Sub Form_Click( )
Dim Sum,Q As Integer
For Q=6 To 1 Step -1
Sum=Sun+HSJC(Q)
Next Q
Print “6!+5!+4+3!+2!+1!=”;Sum
End Sub
Rem 函数过程 HSJC
Private Function HSJC(ByRef N As Integer) As Integer
HSJC=1
Do While N>0
HSJC= HSJC*N
N=N-1
End Function
运行该程序后单击窗体,窗体内显示运行的结果如图 6-2-4 所示。显然是错误的,正确
的现实结果应如图 6-2-3 所示。
产生错误的原因是因为本程序只计算了 6!=720。因为
形参 N 是按地址传递的,在第一次调用 HSJC 函数后形参
N 的值为 0;由于实参与形参共享地址单元,所以实参 Q
图 6-2-4 程序运行后单击窗体产生的效果
的值也是 0。当执行循环语句“For Q=5 To 1 Step -1”时就
退出 For 循环。For 循环只执行了一次,求出了 6!的值。为了解决这个问题,可将实参 Q 改
为表达式,因为表达式是按值传递的。把变量改为表达式的最简单的方法是用“( )”将变量
第6章 过程和自定义数据类型 199
括起来。此时的调用函数过程语句改为:HSJC((Q))。相应的两条语句修改如下。
Sum = Sum + HSJC((Q)) '进行阶乘的累加
Print Str$((Q)) + "!=" & HSJC((Q)) '显示各阶乘的值
6.2.4 项目拓展
1.
“传值与传址方式的差异”程序
【实例】 设计一个“传值与传址方式的差
异”程序。编写两个交换变量数据的子过程。
其中,子过程 CZ1 采用传值方式,子过程 CZ2
采用传址方式。再编写一个主过程程序,利用
它分别调用两个子过程。通过这个小实例,可
以帮助读者进一步了解传递数据的传值方式与
传址方式的差异。程序运行后,单击“比较”
按钮后,显示的结果如图 6-2-5 所示。
图 6-2-5 程序运行结果
“传值与传址方式的差异”程序代码如下。
Rem 单击“比较”按钮后执行主程序过程
Private Sub Command1_Click( )
Dim A As String, B As String
FontSize = 11
ForeColor = RGB(255, 0, 0)
A = "Hello": B = "你好"
Print "主过程在调用子过程之前的原变量数据:"; "A="; A; " "; "B="; B
Print "_____________________________________________________________"
CZ1 A, B
Print "主过程调用传值子过程 CZ1 之后的变量数据:"; "A="; A; " "; "B="; B
Print
Print "______________________________________________________________"
A = "Hello": B = "你好"
CZ2 A, B
Print "主过程调用传址子过程 CZ2 之后的变量数据:"; "A="; A; " "; "B="; B
Print
End Sub
Rem 传值子过程 CZ1
Public Sub CZ1(ByVal X As String, ByVal Y As String)
Dim T As String
T = X: X = Y: Y = T
Print "传值子过程 CZ1 中互换变量值后的变量数据:"; "X1="; X; " "; "Y1="; Y
Print
End Sub
Rem 传址子过程 CZ2
Public Sub CZ2(X As String, Y As String)
Dim T As String
T = X: X = Y: Y = T
200 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.3 求 2 的 N 次方精确值
6.3.1 窗体模块和标准模块
成,括号内的是相应的文件名称(例如:Form11.frm),它在存储文件时被确定;括号外的是
该模块的名称(例如:Form11),可以在其“属性”窗口的“名称”栏内修改。
1.窗体模块
每个窗体对应一个窗体模块,在窗体模块内可以包含窗体和其控件对象的属性设置、各
种声明和各种过程等。窗体模块在前面已作过介绍,下面总结有关内容。
(1)添加窗体。单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框,
如图 6-3-2 所示。选中“新建”选项卡,再选中“窗体”图标,然后单击“打开”按钮,即
可在当前工程中创建一个新的窗体模块。也可以双击该对话框中的“窗体”图标来创建窗
体模块。
(2)利用记事本等软件可以打开窗体模块文件(也可以打开工程文件、标准模块和类模
块文件),在窗体模块文件中可看到窗体及其控件对象的有关描述,包括它们的属性设置等。
2.标准模块
简单的应用程序一般只有一个窗体,在较大的应用程序中常需要多个窗体。在多窗体结
构的应用程序中,常常会有多个不同的窗体都使用的过程,为了减少工程的代码量和读写方
便,就需要创建标准模块,在标准模块内创建这些公用的过程。任何窗体或模块中的事件过
程或其他过程,都可以调用标准模块内的过程。
在标准模块的代码窗口内可以创建公用的通用
过程,但不能创建事件过程。默认时,标准模块中
的代码是全局的。从一个模块中调用另一个模块的
全局 Sub 子过程时,要在过程名前加模块名字。
在工程中添加标准模块的方法如下。
(1)单击“工程”→“添加模块”菜单命令,打
开“添加模块”对话框,如图 6-3-3 所示。
(2)选中“添加模块”对话框“新建”选项卡,
选中“模块”图标,再单击“打开”按钮,即可在
图 6-3-3 “添加模块”对话框
当前工程中创建一个新的标准模块,同时打开标准
模块的代码窗口。也可以双击该对话框中的“模块”图标来创建新的标准模块。
(3)模块的默认名称为 Module1,可以在其“属性”窗口的“名称”栏中进行修改。
202 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.3.2 变量的作用域和变量的生存期
被本模块的其他过程存取 不可以 可以 可以
例如:
Dim Number As Integer,Person As Single
Static ABC As Integer
不同的过程中可有相同名称的变量,彼此互不相干。例如:由多个不同的过程,每个过
程都是用了变量 N,只要每个过程中的变量 N 定义为使用过程级变量,则每个过程只识别它
自己的变量 N,改变变量 N 的值也不会影响其他过程中的变量 N 的值。因此,采用过程级变
量有利于程序的调试,更具有通用性。过程级变量通常用于保存临时数据。
(2)模块级变量:也叫私有变量。它是指在一个窗体或模块的任何过程外,即在通用声
明段(它在“代码”窗口的最上边,选择“代码”窗口内“对象”下拉列表框中的“通用”
选项,即可使“代码”窗口进入通用声明段编辑状态)内使用 Dim 或 Private 关键字声明的
变量。使用 Private 或 Dim 关键字的作用相同,但使用 Private 可提高代码的可读性。定义模
块级变量的语句格式如下。
Dim 变量名 As Integer
Private 变量名 As Single
例如:
Private S As String
Dim I As Integer, J As Single
模块级变量在说明它的整个模块中的所有过程中都能使用,但其他模块不能访问该
变量。
(3)全局变量:也叫公有变量。它是指在窗体或标准模块的任何子过程或函数过程外,
即在通用声明段内用 Public 或 Global 关键字声明的变量。定义全局变量的语句格式如下。
Public 变量名 As Integer
Global 变量名 As Single
例如:
Public S As String
Global I As Integer, J As Single
全局变量在所有模块中的所有过程中都能使用。它的作用范围是整个应用程序(包括主
程序和过程),因此公有模块级变量属于全局变量。全局变量的值在整个应用程序中始终不会
消失和重新初始化,只有当整个应用程序执行结束时才会消失。全局变量在子过程中可以任
意改变和调用,当某个子过程执行完后,其值带回主程序。
把变量定义为全局变量虽然很方便,但会给调试程序和读程序带来麻烦,特别是在较大
的程序中使用时,容易出错。另外,定长字符串、数组和自定义类型变量都不可以作为窗体
模块声明的全局变量。
2.变量的生存期
从变量的作用空间来说,变量有作用范围;从变量的作用时间来说,变量有生存期(也
叫存活期)。变量的生存期就是变量能够保持其值的时期。假设子程序内部有一个变量,当程
序运行进入该子程序时,要分配给该变量一定的内存单元,一旦程序退出该过程,变量占有
的内存单元是否释放呢(变量占有的内存单元释放后,变量的值也消失了)?
根据变量的生存期,可以把变量分为静态变量(Static)和动态变量(Dynamic)。静态变
204 中文 Visual Basic 6.0 实用教程—结构化程序设计
量不释放内存单元,动态变量释放内存单元。
(1)动态变量:动态变量仅当本过程执行期间存在,程序运行进入变量所在的子过程时,
系统才分配给该变量一定的内存单元。当一个过程执行完毕,退出该过程后,该变量占用的
内存单元自动释放,该局部变量的值就不存在了。当下一次执行该过程时,所有局部变量需
重新声明和重新初始化。
使用 Dim 关键字在过程中声明的局部变量,就属于动态变量。
(2)静态变量:它是指程序运行进入该变量所在的子程序,修改变量的值后,退出该子
程序,其值仍被保留,即变量所占内存单元没有释放。当以后再次进入该子程序,原来变量
的值可以继续使用。
使用 Static 关键字在过程中声明的局部变量,就属于静态变量。模块级变量和全局变量
的存活期是整个应用程序的运行期间,也属于静态变量。通常 Static 关键字和递归的 Sub 过
程不能在一起使用。
在过程头前加上 Static 关键字时,无论过程中的变量用 Static,Dim 或 Privte 声明的变量
还是隐式声明的变量,都会变成静态变量。例如:下面的函数过
程定义语句是为了使过程中所有的局部变量为静态变量。
Private Static Function Fac(n As Integer)
下面这个程序运行后,每次单击窗体,可以看到动态变量 A
的值是不变的,没有累计效果;而静态变量 B 的值是变化的,有
图 6-3-4 区别动态和静态变量 计数累计效果,如图 6-3-4 所示。程序代码如下。
Private Sub Form_Click( )
Dim A As Integer
Static B As Integer
A=A+ 1
B=B+1
Print "动态变量 A="; A, "静态变量 B="; B
End Sub
6.3.3 过程的作用域和过程的外部调用
1.定义过程作用域的语句格式
与变量的作用范围相同,过程也有其作用范围,即过程的有效范围。Sub 子过程和函数
(Function)过程的作用范围是通过语句声明的。定义过程作用域的语句格式如下。
[Private|Public][Static] Sub 过程名([参数列表])
[Private|Public][Static] Function 函数名([参数列表])[As 数据类型]
Public 表示全局过程(公用过程) ,所有模块的其他过程都可访问这个过程。所有模块中
的子过程缺省为 Public。Private 表示模块级过程(也叫局部过程或私用过程),只有本模块中
的过程才可访问。
如使用 Static(静态)关键字,这些变量的值在整个程序运行期间都存在,即在每次调
用该过程时,各局部变量的值一直存在;如省略该关键字,则当该过程结束时释放其变量的
存储空间。
第6章 过程和自定义数据类型 205
2.模块级过程和全局级过程
可将子过程放入标准模块、类模块和窗体模块中。过程的作用域可分为窗体/模块级作用
域和全局作用域。它们都可被本模块内其他过程调用。
(1)窗体/模块级过程:它是指在某个窗体或标准模块内定义的过程,这种过程只能被所
在窗体或标准模块中的过程调用,不可以被本应用程序中的其他窗体或标准模块内的过程调
用。定义子过程或函数过程时,使用 Private 关键字,即可定义模块级过程。例如:
Private Sub MyProgram(A As Integer)
其中,MyProgram 是窗体或标准模块名称,括号内的是形参表。
(2)全局级过程:它是指在窗体或标准模块中定义的过程,其默认是全局的,也可以加
关键字 Public 进行说明。全局级过程可供该应用程序的所有窗体和所有标准模块中的过程调
用,但根据过程所处的位置不同,其调用方式有所区别。
3.过程的外部调用
过程的外部调用是指调用其他模块中的全局过程。调用其他模块中过程的方法,取决于
该过程所属的模块是窗体模块、标准模块还是类模块。
(1)窗体模块中的过程:外部过程均可以调用窗体中的全局过程,必须以窗体名为调用
的前缀。但在外部过程要调用时,必须在过程名前加该过程所属的窗体名。语句格式如下。
Call 窗体名.全局过程名[(实参列表)]
例如,在窗体 Form1 中定义一个全局过程 QJl,在窗体 Form2 中调用 Form1 中的 QJ1 过
程的语句如下:
Call Form1.QJ1(A As Integer)
其中,Form1 是窗体名称,QJ1 是过程名称,括号内的“A As Integer”是实参表。
(2)标准模块(.bas)中的过程: 外部过程均可调用它,但在外部过程要调用时,过程名必
须是惟一的,否则应加标准模块名。在标准模块中的过程,如果过程名是惟一的,则不必在
调用时加模块名;如果有两个以上的模块包含同名的过程,则调用本模块内过程时不必加模
块名,而调用其他模块的过程时必须以模块名为前缀。语句格式如下。
Call [标准模块名].全局过程名[(实参列表)]
例如,对于 Modulel 和 Module2 中名称为 QJ1 的过程,从 Module2 中调用 Module1 中的
QJl 语句如下:
Call Module1.QJ1(A As Integer)
其中,Module1 是标准模块名称,QJ1 是过程名称,括号内的是实参表。如果不加 Module1
标准模块名时,则调用 Module2 中的 QJ1 过程。
(3)调用类模块的过程:调用类模块中的全局过程,要求用该类的相应实例的名称为前缀。
首先声明类的实例为对象变量,并且以此变量作为过程名前缀,不可直接用类名作为前缀。
Call 变量.过程名([实参表列])
例如,类模块为 Classl,类模块的全局过程为 QJ1,变量名为 EC1,调用过程的语句
如下:
Dim EC1 As New Classl '声明 Classl 类模块的实例为 EC1
Call EC1.QJ1(A AS Integer) '调用类模块 Classl 中的全局过程 QJ1
206 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.3.4 项目实现
1.
“求2的N次方精确值”程序算法
计算机能输出的有效数字的位数是有限的,例如计算 2500,如果用 Print 2^500 语句计算,
就得不到精确的结果。对于这类计算,必须用程序模拟
实际运算过程。编写一个能精确计算 2N(例如:2500)
的程序,要求能显示出计算结果的每位数字。程序运行
后,在文本框中输入 N 的值后,按回车键,即可获得 2N
的精确数值,如图 6-3-5 所示。
分析:计算 2N 的实质是 N 个 2 相乘,可用程序完
成 N 个 2 相乘,并把每位数存放在数组 A 的各下标变量
中,A(1)存放个位数、A(2)存放十位数、A(3)存放百位
图 6-3-5 “求 2 的 N 次方精确值”程序运行结果 数……数组 A 的下标最大值(即 2N 的位数)可由 Int(N
A(1) = 1: K = 1: W = 0 '赋初值
For I = 1 To N
For J = 1 To K
A(J) = A(J) * 2 '给各位数乘 2
If A(J) > 9 Then W = 1 '如果某位数大于 9,则变量 W 赋 1,表示有需要进位的数
Next J
If W=1 Then Call Module1.JWJS(K,W,A( ))'如果有某位数大于 9,则调进位子过程 JWJS
Next I
If N <> O Then '如果已经进行完了计算,则显示结果
L=1 '用来确定何时换行
For T = K To 1 Step -1
FontSize = 12 '给窗体设置字大小为 12
ForeColor = RGB(0, 0, 255) '给窗体设置字颜色蔚蓝色
Print LTrim$(Right$(Str(A(T)), 1)); '在窗体内显示计算结果
If L Mod 40 = 0 Then Print '如果一行显示了 40 个数字,则换行
L=L+1
Next T
Print: Print
ForeColor = RGB(255, 0, 0) '给窗体设置字颜色为红色
Print "2 的" + LTrim$(Str$(N)) + "次方的位数是:"; LTrim$(Str$(K)) '显示位数
End If
End Sub
Private Sub Command2_Click( )
End
End Sub
3.程序中的标准模块程序设计
单击“工程”→“添加模块”菜单命令,打开“添加模块”对话框(与“添加窗体”对
话框类似),选中“新建”选项卡,再选中“模块”图标,然后单击“打开”按钮,即可在当
前工程中创建一个新的标准模块,同时打开标准模块的代码窗口。
然后,在标准模块的代码窗口内输入如下的“求 2 的 N 次方精确值”的窗体模块程序。
在该程序的通用段内定义了一个全局变量 Q,创建了一个 Sub Main 子过程,还创建了一个求
进位的子过程 JWJS。
Public Q As Integer '声明一个全局变量 Q
Rem 创建一个 Sub Main 子过程
Sub Main( )
Q=0 '给变量 Q 赋初值 0
Form1.Show '装载和显示窗体 Form1
End Sub
Rem 求进位的子过程
Public Sub JWJS(K, W, A( ) As Integer)
Dim N As Integer '声明各过程级变量
For H = 1 To K
Rem 进行每一位的进位计算
A(H + 1) = A(H + 1) + Int(A(H) / 10): A(H) = A(H) - Int(A(H) / 10) * 10
208 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.3.5 项目拓展
1.常量的作用域
( 1 )过程级符号常量:指仅在某一个过程内有效的符号常量。在过程内使用关键字
PrivateConst 声明的符号常量就是过程级符号常量。
(2)模块级符号常量:指在模块内有效,而在模块之外无效的符号常量。在该模块顶部
的声明段中使用关键字 Private 声明的符号常量就是模块级符号常量。
(3)全局符号常量:指在整个应用程序中都有效的符号常量。在整个应用程序内标准模
块的顶部的通用段中,使用关键字 Public 或 Global 声明的符号常量就是全局符号常量。在窗
体模块和类模块中是不允许声明全局符号常量的。
2.“发工资方案”程序
【实例】 财务科在发工资时,不能只根据工资总数到银行领回大面额人民币,也不宜领
回大量零钱。试编写一个发工资的程序,它可根据键盘输入的每个职工的实发工资数,计算
出需从银行领回 100 元、50 元、10 元、5 元、2 元、1 元、5 角、2 角、1 角、5 分、2 分和 1
分的人民币各多少,才能保证能将每个职工的工资分开。另外,还计算出全体职工实发工资
的总额。程序运行后,弹出一个“输入人数”对话框,如图 6-3-7 所示,要求输入发工资的
总人数。此时窗体还没有出现。
输入人数(例如:3)后,按回车键或单击“确定”按钮,即可退出输入对话框,调出
窗体,显示图 6-3-8 所示的画面。
输入第 1 个人的工资后,按回车键,再输入下一个人的工资。当所有人员的工资全部输
入完后,“统计”按钮会自动变为有效,文本输入框变为无效,如图 6-3-9 所示(假设,此处
输入的 3 个人的工资数分别为 3000.35、3068.00 和 3000.00)
。然后,单击“统计”按钮,即
可显示出各种票面的人民币的张数,如图 6-3-10 所示。
第6章 过程和自定义数据类型 209
If K = RS + 1 Then '如果个人工资输入完毕,则
Label2.Caption = "" '清 Label2 标签
Command1.Enabled = True '使“统计”按钮有效
Text1.Enabled = False '使文本框 Text1 无效
End If
End Sub
Rem 单击“统计”按钮后的事件过程
Private Sub Command1_Click( )
Dim Y100, Y50, Y10, Y5, Y2, Y1 As Integer
Dim J5, J2, J1, F5, F2, F1, I As Integer
For I = 1 To RS
N = GZ(I) '取每个人的工资数
Y100 = Y100 + Int(N \ 100) '求 100 元票张数
N1 = N / 10: Call TGGZ(N1, A5, B2, C1) '求 50、20、10 元票张数
Y50 = Y50 + A5: Y20 = Y20 + B2: Y10 = Y10 + C1
N1 = N: Call TGGZ(N1, A5, B2, C1) '求 5、2、1 元票张数
Y5 = Y5 + A5: Y2 = Y2 + B2: Y1 = Y1 + C1
N1 = N * 10: Call TGGZ(N1, A5, B2, C1) '求 5、2、1 角票张数
J5 = J5 + A5: J2 = J2 + B2: J1 = J1 + C1
N1 = N * 100: Call TGGZ(N1, A5, B2, C1) '求 5、2、1 分的个数
F5 = F5 + A5: F2 = F2 + B2: F1 = F1 + C1
Next I
Rem 给相应的标签对象的 Caption 属性赋值
LabelB0.Caption = Y100
LabelB1.Caption = Y50: LabelB2.Caption = Y20: LabelB3.Caption = Y10
LabelB4.Caption = Y5: LabelB5.Caption = Y2: LabelB6.Caption = Y1
LabelB7.Caption = J5: LabelB8.Caption = J2: LabelB9.Caption = J1
LabelB10.Caption = F5: LabelB11.Caption = F2: LabelB12.Caption = F1
End Sub
Rem 换算包含 5、2、1 的数目子过程
Public Sub TGGZ(ByVal N1 As Single, A, B, C)
Dim M As Integer
M = Int(N1) - 10 * Int(N1 / 10)
A = Int(M / 5)
B = Int((M - 5 * A) / 2)
C =M- 5*A- 2* B
End Sub
Private Sub Command2_Click( )
End
End Sub
在当前工程中创建一个新的标准模块,同时打开标准模块的代码窗口。然后,在标准模
块的代码窗口内输入如下的“发工资方案”程序中标准模块内的程序代码。在该程序的通用
段内定义了一个全局变量 RS 和一个数组 GZ,创建了一个 Sub Main 子过程。
“发工资方案”程序中标准模块内的程序代码如下。
第6章 过程和自定义数据类型 211
Public RS As Integer
Public GZ( ) As Single
Sub Main( )
RS = Val(InputBox("请输入人数:", "输入人数", 0)) '输入人数
ReDim GZ(1 To RS) As Single '声明一个动态数组 GZ
Form1.Show
End Sub
6.4 统计学生成绩
通常,在数组中各个数组元素的数据类型应该是相同的,但在实际应用中,所处理的对
象往往由一些互相联系的、不同类型的数据项组合而成。虽然可以把数组声明为 Variant 型,
从而使各个数组元素存放不同类型的数据。但是,这会降低应用程序的运行速度。为了既能
够表示和处理不同类型的数据,又不至于降低应用程序的运行速度,可以将这些描述同一对
象的各种类型数据声明为用户自定义数据类型。用户自定义数据类型,又叫记录类型。
6.4.1 自定义数据类型的定义方法
2.自定义数据类型的定义举例
例如:声明一个关于学生信息的自定义类型(记录类型),该自定义类型中包括学生的
学号、姓名、性别、年龄、5 个学科的成绩、总成绩和平均分等数据项。这个自定义型的名
称为:Student。
Private Type Student
XSXH As String * 4 'XSXH(学号)数据项,4 个字符长字符型
XSXM As String * 8 'XSXM(姓名)数据项,8 个字符长字符型
XSXB As String * 1 'XSXB(性别)数据项,1 个字符长字符型
XSCJ(1 To 5) As Integer 'XSCJ(5 科成绩)数据项,整型
XSZF As Integer 'XSZCJ(总分)数据项,整型
XSPJF As Single 'XSPJF(平均分)数据项,单精度型
End Type
6.4.2 自定义数据类型的使用
1.自定义数据类型变量的声明
一旦自定义数据类型(记录类型)定义好后,就可以像基本数据类型那样使用了,可以
在变量的声明中使用这种记录类型,但要注意声明语句所在的位置略有不同:不能在窗体模
块和类模块中声明全局型的记录类型变量,全局型的记录类型变量必须在标准模块中进行声
明。例如在某个过程中声明记录类型变量 XA 的语句是:
Dim XS As Student
其中,XS 是变量名称,Student 是记录类型名称。
2.自定义数据类型变量的使用
一个变量一旦被声明为记录类型,就可以在程序中使用该变量及该变量中任一数据项中
的数据了。要使用变量中的某个数据项,可采用如下格式。
变量名称.数据项名称
例如:表示学生的姓名可以使用 XS.XSXM。
6.4.3 项目实现
1.
“统计学生成绩”程序的运行结果
“统计学生成绩”程序是用来输入学生的学号、姓名、性别和 5 科成绩,然后显示出该
学生的总分和平均分。程序运行后显示一个“输入学号”对话框,如图 6-4-1 所示。输入学
号后按回车键,即可调出“输入姓名”对话框,在其中输入姓名。然后,会依次调出不同的
对话框,用户依次再输入性别和 5 科成绩。输入完后,窗体中会显示学生的学号、姓名、性
别和他的 5 科成绩,以及总分和平均分,如图 6-4-2 所示。
2.程序代码
“统计学生成绩”程序的程序代码如下。程序中首先声明一个关于考生信息的自定义类
型(记录类型),该自定义类型中包括学生的学号、姓名、性别、年龄、5 科成绩、总分和平
均分等数据项。这个自定义型的名称为 Student,然后是各项数据的输入程序,总分统计和平
均分计算程序,最后在相应的标签内显示有关信息。
Rem 定义一个模块级的自定义数据类型 Student
Private Type Student
XSXH As String * 4 'XSXH(学号)数据项,4 个字符长字符型
XSXM As String * 8 'XSXM(姓名)数据项,8 个字符长字符型
XSXB As String * 1 'XSXB(性别)数据项,1 个字符长字符型
XSCJ(1 To 5) As Integer 'XSCJ(5 科成绩)数据项,整型
XSZF As Integer 'XSZCJ(总分)数据项,整型
XSPJF As Single 'XSPJF(平均分)数据项,单精度型
End Type
Rem 输入学生学号、姓名、性别和各科成绩
Private Sub Form_Activate( )
Dim XS As Student, I As Integer
TS$ = "请输入学生的学号" + Chr(13) + Chr(10) + "学号为:"
XS.XSXH = InputBox(TS$, "输入学号", "0001", 5000, 1600) '将输入的学号赋给变量 XSXH
TS$ = "请输入学生的姓名" + Chr(13) + Chr(10) + "姓名为:"
XS.XSXM = InputBox(TS$, "输入姓名", "赵晓红", 5000, 1600) '将输入的姓名赋给变量 XSXH
TS$ = "请输入学生的性别" + Chr(13) + Chr(10) + "性别为:"
XS.XSXB = InputBox(TS$, "输入姓名", "男", 5000, 1600) '将输入的性别赋给变量 XSXH
TS$ = "请输入学生的成绩" + Chr(13) + Chr(10) + "成绩为:"
XS.XSCJ(1)=Val(InputBox(TS$,"输入语文成绩",100,5000,1600)) '语文成绩赋给变量 XSCJ(1)
XS.XSCJ(2)=Val(InputBox(TS$,"输入数学成绩",100,5000,1600)) '数学成绩赋给变量 XSCJ(2)
XS.XSCJ(3)=Val(InputBox(TS$,"输入外语成绩",100,5000,1600)) '外语成绩赋给变量 XSCJ(3)
XS.XSCJ(4 =Val(InputBox(TS$,"输入政治成绩",100,5000,1600)) '政治成绩赋给变量 XSCJ(4)
XS.XSCJ(5)=Val(InputBox(TS$,"输入物理成绩",100,5000,1600)) '物理成绩赋给变量 XSCJ(5)
Rem 统计学生成绩
For I = 1 To 5
XS.XSZF = XS.XSZF + XS.XSCJ(I)
Next I
XS.XSPJF = XS.XSZF / 5
Rem 显示学生成绩
Label12.Caption = XS.XSXH
Label13.Caption = XS.XSXM
Label14.Caption = XS.XSXB
Label15.Caption = XS.XSCJ(1)
Label16.Caption = XS.XSCJ(2)
Label17.Caption = XS.XSCJ(3)
Label18.Caption = XS.XSCJ(4)
Label19.Caption = XS.XSCJ(5)
Label20.Caption = XS.XSZF
Label21.Caption = Str$(XS.XSPJF)
214 中文 Visual Basic 6.0 实用教程—结构化程序设计
End Sub
6.4.4 项目拓展
1.使用同名的变量
在程序设计中,可能会在不同范围的程序中使用相同的变量名,例如:会有几个同名的
局部变量,局部变量与模块变量同名,局部变量、模块变量与全局变量同名等情况。通常应
避免在一个应用程序中使用相同的变量名称,如果使用了相同的变量名称,应注意变量的使
用方法。下面分几种情况进行简要介绍。
(1)不同模块中的全局变量同名
如果不同模块中的全局变量使用同一个变量名称,则应在使用变量名时,在变量名前面
加相应的模块的名称,写成“模块名.变量名”格式。
例如,在一个工程中有两个模块:标准模块 Modulel 和窗体模块 Forml。Forml 窗体有两
个按钮 Commandl 和 Command2,在标准模块 Modulel 中声明全局变量 QJBL1(整型)和 SJBL1
(字符型) ,以及创建一个局部子过程 TESTJBGC;在窗体模块 Forml 中也声明全局变量 QJBL1
和 SJBL1,以及创建一个同名的局部子过程 TESTJBGC。
标准模块文件 Modulel.bas 程序代码如下:
Public QJBL1 As Integer, SJBL1 As String '声明一个标准模块 Modulel 的全局变量 QJBL1
Sub TESTJBGC( ) '声明一个局部过程 TESTJBGC
QJBL1 = 300
SJBL1 = "显示标准模块 Modulel 的全局变量 QJBL1"
End Sub
窗体模块文件 Form1.frm 程序代码如下:
Public QJBL1 As Integer, SJBL1 As String '声明一个窗体模块 Module1 的全局变量 SJBL1
Sub TESTJBGC( ) '声明一个局部过程 TESTJBGC
QJBL1 = 100
SJBL1 = "显示窗体模块 Module1 的全局变量"
End Sub
在窗体中有“标准模块全局变量”和“窗体模块全局变量”两个按钮,它们的名称分别
是 Commandl 和 Command2。窗体模块中单击两个按钮的事件过程(即 Click 事件过程)中
的程序是用来分别调出相应的 TESTJBGC 过程的,同时调出相应的信息框,信息框用来显示
相应的全局变量的值,以证明调用的是哪个全局变量。
程 序 中 , 在 Forml 窗 体 模 块 中 调 用 本 模 块 的 TESTJBGC 过 程 时 不 必 指 定
Forml.TESTJBGC,使用 QJBL1 和 SJBL1 变量时也不必指定 Forml.QJBL1 和 Forml.SJBL1。
在 Forml 模块中调用 Modulel 的 TESTJBGC 过程时必须指定 Modulel.TESTJBGC,使用
QJBL1 和 SJBL1 变量时也必须指定 Forml.QJBL1 和 Forml.SJBL1。
运行上述程序后,窗体的画面如图 6-4-3 左图所示。单击“标准模块全局变量”按钮,
窗体显示如图 6-4-3 中图所示,标准模块 Modulel 内的 QJBL1 变量值为“显示标准模块
Module1 的全局变量 QJBL1”;单击“窗体模块全局变量”按钮,窗体显示如图 6-4-3 右图
所示。
(2)控件对象名称与变量同名
窗体的属性、控件对象、符号常数和过程都被视为窗体模块中的模块级变量。如果窗体
中的控件名与模块级变量名、符号常数和过程名相同是不合法的,因为它们的作用范围相同。
因此,在窗体模块中应当尽量使变量名和窗体中的控件名不一样,养成对不同的变量使用不
同的名称的编程习惯。
在窗体模块内,如果控件对象的名称与它的局部变量名称相同,局部变量名将遮住同名
控件。因此,必须引用窗体名称或 Me 关键字来限定控件
对象,才能设置或得到该控件的属性值。例如,在窗体
(Form1)有一个文本框 Textl,也有一个局部变量 Textl,
则使用文本框 Textl 时应采用:Form1.Textl 或 Me.Textl。例
如下边的程序的运行结果如图 6-4-4 所示。 图 6-4-4 “使用同名变量 2”程序运行结果
(3)全局变量与局部变量同名
当全局变量与局部变量同名时,全局变量和局部变量在不同的范围内有效。在过程内,
局部变量有效;而在过程外,全局变量有效。
216 中文 Visual Basic 6.0 实用教程—结构化程序设计
2.启动时快速显示窗体
如果应用程序在启动时有一个较长的执行过程(从数据库中装入大量数据或者需要装入
一些加大的图像等),可在启动时给出一个快速显示窗体,它通常显示的是应用程序的名称、
设计单位或个人名字、版权信息和一些简单的图像等内容。启动 Visual Basic 程序时开始所
显示的窗口就是一个快速显示窗体。快速显示窗体能吸引用户的注意,造成应用程序装载很
快的错觉。当启动完成并且装入第一个窗体的同时卸载快速显示窗体。快速显示窗体应尽量
设计的简单一些。
Visual Basic 提供了一些常用的窗体模板,其中有一个“展示屏幕”,可在这个模板的基
础上创建快速显示窗体。创建快速显示的方法如下。
(1)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。
(2)在“添加窗体”对话框中选择“展示屏幕”图标,如图 6-4-5 所示。
(3)单击“打开”按钮,创建快速显示窗体的模板,如图 6-4-6 所示。然后,在该窗体
内添加需要的相关信息。
6.5 利用递归算法求阶乘
6.5.1 递归
1.什么是递归
递归是算法设计中最常用的手段,是设计和描述算法的一种有力的工具。递归算法结构
简单清晰,易于阅读和理解。用少量的语句,可实现很多次重复计算,起到事半功倍的作用。
第6章 过程和自定义数据类型 217
能采用递归描述的算法通常有这样的特征:为求解规模为 N 的问题,设法将它分解成一
些规模较小的问题,而且这些规模较小的问题也能采用同样的分解和综合方法,分解成规模
更小的问题,然后从这些小问题的解构造出规模稍大问题的解。特别要注意,问题还必须能
够在 N=1 或其他数据时,直接得到解。因此,可以说递归就是用自身的结构来描述自身。递
归调用就是指一个过程直接或间接地调用它本身。
由于递归引起一系列的函数过程的调用,并且可能会有一系列的重复计算,递归算法的
执行效率相对较低。
2.递归的条件
Visual Basic 允许一个子过程或函数过程在自身定义的内部调用自己,这样的子过程或
函数过程称为递归子过程或递归函数过程。许多问题都具有递归的特性,用递归调用描述
它们是非常方便的。递归调用不可以无限地调用下去,必须在一定的条件满足后,结束递
归调用。
能够实现递归的条件如下。
① 可以用递归形式来表示一个问题;
② 有递归结束的条件,程序的运行可使递归结束条件成立。
使用递归的算法可以解决许多问题,而且可以使问题的解决非常简洁、明了。例如:使
用递归算法求多个数的阶乘、多个数的最大公约数和最小公倍数,显示裴波纳契数列数等。
递归最典型的例子是进行阶乘运算,N!=N×(N−1) ×…×2×1。阶乘可用下面式子来表示:
⎧1 (N = 1)
F(N) = ⎨
⎩ N × F(N − 1) (N>1)
递归算法的执行过程分递推和回归两个阶段。在递推阶段,把较复杂的问题(规模为 N)
的求解分解为比原问题简单一些的问题(规模小于 N)的求解。例如求 6!,利用上面的定义
式子,可将 6!转换为 6×5!,再将 5!转换为 5×4!,4!可转换为 4×3!,3!可转换为 3*2!,2!可转
换为 2*1!。因为已知 1!=1,所以递推阶段可以结束。
在回归阶段,当获得最简单情况的解后,逐级返回,依次获得稍复杂问题的解。当得到
1!为 1 后,返回上一级,获得 2!=2*1!=2 的结果;再返回上一级,获得 3!=3*2!=6 的结果;
再返回上一级,获得 4!=4*3!=24 的结果;再返回上一级,获得 5!=5*4!=120 的结果;再返回
上一级,获得 6!=6*5!=720 的结果。
当 N=5 时,N!递归算法的递推和回归两个阶段如图 6-5-1 所示。
回归阶段
F(5)=5! F(1)=1
递推阶段
图 6-5-1 5!递归算法的递推和回归两个阶段
218 中文 Visual Basic 6.0 实用教程—结构化程序设计
6.5.2 项目实现
1.界面设计
“求 N!”程序运行后,显示的窗体如图 6-5-2 所示。在文本框内输入 N 的数值,再单击
“求阶乘”按钮,即可求出 N!,如图 6-5-3 所示。
2.程序代码1
“求 N!”程序代码 1 如下。
Private Sub Command1_Click( )
Dim M As Long
Dim N As Integer
N = Val(Text1.Text)
M = FACT(N)
Label4.Caption = Str$(M)
End Sub
Rem 求阶乘的函数过程
Public Function FACT(ByRef N As Integer) As Long
If N = 1 Then
FACT = 1 '退出递归的条件
Else
FACT = N * FACT(N - 1) '递归运算
End If
End Function
Private Sub Command2_Click( )
End
End Sub
由程序可以看出,当 N>1 时,在 FACT 函数过程中调用 FACT 函数过程,只是参数变为
N−1。这样的调用一直到 N=1 时为止。当 N=1 时,FACT 函数过程的值为 1,不再调用 FACT
函数过程,所以,此处的递归结束条件是 N=1。
3.程序代码2
“求 N!”程序代码 2 是将 FACT 函数过程放置在标准模块中。窗体模块中的程序如下。
Private Sub Command1_Click( )
Dim M As Long
Dim N As Integer
N = Val(Text1.Text)
第6章 过程和自定义数据类型 219
M = Module1.FACT(N)
Label4.Caption = Str$(M)
End Sub
Private Sub Command2_Click( )
End
End Sub
标准模块中的程序如下。
Public Function FACT(ByRef N As Integer) As Long
If N = 1 Then
FACT = 1
Else
FACT = N * FACT(N - 1)
End If
End Function
6.5.3 项目拓展
1.
“利用递归算法求斐波那契数列的第 N 号数”程序
【实例】 斐波那契数列为:0,1,1,2,3,5,8,… 可以用下面的公式来描述。
第 0 号数 FACT(0)=0
第 1 号数 FACT(1)=1
第 2 号数 FACT(2)=1
第 N 号数 FACT(N)=FACT(N−1)+FACT(N−2) (当 N>1 时)
在递推阶段,求解 FACT(N), 把它推到求解 FACT(N−1)和 FACT(N−2)。而计算 FACT(N−1),
推到计算 FACT(N−2)和 FACT(N−3),而计算 FACT(N−2),又把它们推到计算 FACT(N−3)和
FACT(N−4)…依此类推,直到计算 FACT(1)和 FACT(2),分别能立即得到结果 1 和 1。
在回归阶段,得到 FACT(1)为 1 和 FACT(2)为 1 后,返回获得 FACT(2)的结果……得到
了 FACT(N−2)和 FACT(N−1)的结果后,返回获得 FACT(N)的结果。
“利用递归算法求斐波那契数列的第 N 号数”程序运行后的窗体显示如图 6-5-4 所示,在
文本框中输入 20 后,单击“求斐波那契数列的第 N 号数”按钮,即可获得第 20 号斐波那契
数列的数值,如图 6-5-5 所示。
“利用递归算法求斐波那契数列的第 N 号数”程序的程序代码如下。
Private Sub Command1_Click( )
220 中文 Visual Basic 6.0 实用教程—结构化程序设计
2.“Hanoi(汉诺)塔问题”程序
【实例】 Hanoi 塔相传是一种古印度所罗门教徒玩的游戏。它的内容是:古代有一个梵
塔,塔内有 A,B,C 座,开始时 A 座上有 N 个大小不等、中心有孔的圆形金盘,这些圆形
金盘都穿过 A 座上的针,小片金盘在上,大片金盘在下,形成金盘宝塔形状,如图 6-5-6 所
示。要求将 A 座上的 N 片金盘全部移至 B 座。限制每次只移一个金盘,并且不允许将大的
金盘放在小金盘的上面,但移动时可以将金盘放在 C 座上。任何时候,任一座上的金盘只能
小片金盘压大片金盘,不能大片金盘压小片金盘。试给出移动的方法。
1
2
3
A B C
移动第 1 个金盘:从 A座 移到 B座
(1) 先利用 B 座,将 A 座上的
移动第 2 个金盘:从 A座 移到 C座 N–1 个金盘移到 C 座(递归地)
移动第 1 个金盘:从 B座 移到 C座
(2) 把 A 座上惟一的一个金盘
移动第 3 个金盘:从 A座 移到 B座
(金盘 N)
移动第 1 个金盘:从 C座 移到 A座
移动第 2 个金盘:从 C座 移到 B座 (3) 再利用 A 座,把 C 座上的
N–1 个金盘移到 B 座(递归地)
移动第 1 个金盘:从 A座 移到 B座
思考与练习
1.填空题
(1)过程有 和 两类。自定义过程有 、 、 和
四类。
(2)过程的调用方法有 和 两种。
(3)形参是 ,实参是 。
(4)传址方法是 ,传值方法是 。
(5)任何窗体或模块中的事件过程或其他过程,都可以调用 内的 。
(6)过程级变量的作用域是 ,模块级变量的作用域是 ,全局变量的作
用域是 。
(7)关键字 Private 表示声明 变量,Public 表示声明 变量。
(8)实现递归的条件有 和 。
2.根据下面的要求编写 Visual Basic 程序
(1)采用子过程和函数过程的方法,编写程序求 2!+4!+ … +8!的值。
(2)采用子过程和函数过程的方法,编写程序求 5 个自然数的最大公约数和最小公倍数。
(3)使用标准模块,编写程序求 5 个自然数的最大公约数和最小公倍数。
(4)编写程序,计算 N 的 M 次方的精确值。
224 中文 Visual Basic 6.0 实用教程—结构化程序设计
(5)编写程序,计算 60 位数以内数的精确乘法。
(6)哥德巴赫猜想的另一个形式是:任何大于 7 的奇数都可以表示成三个素数之和。例
如:15=3+5+7。试编写一个程序,将 9 到 99 之间的奇数表示成三个素数的和。
(7)使用递归算法,求 2!+ 4!+ … +8!。
(8)使用递归算法,显示裴波纳契数列的前 40 个数,并求它们的和。
文件管理
第 7章
7.1 文本文件加密器
7.1.1 文件的结构特点和文件的基本划分
文件是存储在外部介质(如磁盘)上的数据的集合,它可以永久性地保存信息。在应用
程序中,如果要长期保存和访问数据,必须将数据保存到文件当中。操作系统是以文件为单
位对数据进行管理的,如果想访问存放在外部介质上的数据,必须先按文件名找到所指定的
文件,然后再从该文件中读取数据。要向外部介质存储数据也必须先建立一个文件,才能向
它输出数据。Visual Basic 根据计算机访问文件的方式,提供了对各类文件的处理方法,程序
员可以使用这些手段开发出功能强大的应用程序。
1.文件的结构特点
为能有效地存取数据,就必须以某种特定方式(即文件的结构)来存取数据。文件一般
是以记录的集合组成的。记录是计算机处理数据的基本单位,它由若干个相互关联的数据项
组成。这些记录可分为等长记录和变长记录。
记录是由一些数据项组成的,数据项又是由各种字符组成的。因此,也可以说,由字符
组成了数据项,由数据项组成了记录,由记录又组成了文件。
例如:在一个学生的档案管理文件中,由字符(包括汉字)组成了学号、姓名、年龄和
性别等数据项,这些数据项又构成了一个学生的记录,多个学生的记录组合到一起就形成了
文件。
计算机对文件的存取、处理数据都是以记录为单位的。根据文件的组织形式不同,其存
取方式也多种多样,有的可根据记录号来存取数据,也有的可根据记录中的某个数据项的内
容来进行存取。
文件的存储结构可直接影响到文件系统的性能。因此,只有建立合理的文件存储结构,
才能有效地利用存储空间,且便于系统的处理。
2.按照存取方式及组成结构对文件进行划分
按照存取方式及组成结构对文件进行划分是文件划分的基本方式,使用这种划分方式,
可以将文件划分为顺序文件和随机文件两类,其含义如下所述。
(1)顺序文件:它是一种结构简单的文件。顺序文件是一条条记录按顺序进行存放的文
件,每条记录的长度可按需要变化。如果想对顺序文件中的数据信息进行查找、添加、删除
和插入记录是比较困难的,因为该类文件只提供第一个记录的存储位置,其他记录的位置无
226 中文 Visual Basic 6.0 实用教程—结构化程序设计
法获悉。要查找一个记录,必须从头开始读,直到找到要查找的记录为止。要往文件中增加
内容时,只能找到文件尾,将内容追加进去。所以对这类文件的修改,只能将所有数据全部
读入 RAM 中才可以进行修改,修改后再重新写入磁盘。
顺序文件适用于大量数据的成批处理,这种文件通常进行有规律的中间数据的修改、查
找、添加、删除和插入等操作。顺序文件的优点是:在同样内容的情况下,所占的磁盘空间
小,使用也相对较简单。
(2)随机文件:它的每条记录都是固定长度,每条记录都有记录号,每条记录中各数据
项的数据类型和占空间字节数不同,所以在使用前必须事先规定好每条记录中各数据项的类
型及长度。因为这种文件每条记录都有记录号,所以可以对记录进行定位,方便了记录的修
改、查找、添加、删除和插入。例如:在查找记录时,只要指明记录号,便可找到相应记录。
正是由于随机文件能随机访问、快速地查找更新信息而得名。
随机文件适合于需要进行数据库访问、快速查找和经常更新数据的文件,这种文件一般
是数据库文件。随机文件的缺点是:在同样内容的情况下,所占的磁盘空间较大,程序设计
较烦琐。
7.1.2 打开与读取顺序文件
1.打开顺序文件
【格式】Open “文件名” [FOR 模式][Access 操作类型][锁定]As[#]文件号[Len=记录长度]
【功能】打开“文件名”指定的顺序文件
【说明】
① 文件名:文件名字符串必须用双引号括起来。文件名最多不能超过 8 个字符。所要
打开的文件若不在当前目录下,必须加上全程路径名。
② 模式:顺序文件的模式有三种,它们用来确定对文件进行哪种操作。其名称及功能
如下。
• Input:将数据写入到文件中,对文件进行写操作。
• Output:将磁盘文件中的数据输出到内存中,对文件进行读操作。
• Append:将数据追加到文件的末尾。
③ 操作类型:顺序文件的操作类型有三种,它们用来指定对打开文件进行哪种类型的
操作,对文件的存取限定了约束条件。
• Read:只读。
• Write:只写。
• Read Write:可读可写。
④ 锁定:顺序文件的锁定类型有四种,它们用于多进程环境中,以指定其他进程对本
次打开的文件进行的操作类型。
• Shared(默认):共享。允许其他进程对本次打开的文件进行读写操作。
• Lock Read:禁止其他进程对本次打开的文件进行读操作。
• Lock Write:禁止其他进程对本次打开的文件进行写操作。
• Lock Read Write:禁止其他进程对本次打开的文件进行读写操作。
⑤ 文件号:它是一个介于 1~255 之间的整数。它给文件名分配一个通道序号。当打开
第7章 文件管理 227
某文件并为该文件指定文件号以后,任何对该文件号进行操作的语句都将影响相应文件的内
容,一旦为文件指定了文件号,该号就代表了被打开的文件,直到文件被关闭后,此文件号
才可以再供其他文件使用。
⑥ 记录长度:它是一个小于或等于 32,767 个字节的整型数据。它指定了用于数据交换
时内存数据缓冲区的大小。
在 Windows 中,数据要存储到文件中时,不是直接存到磁盘上,而是先存到一个内存
里的数据缓冲区中,直到装满后才存盘或当关闭文件时一起存盘。默认情况下,系统设置
的数据缓冲区为 512 字节。较大的缓冲区意味着为数据开较大的内存空间,但可提高文件
输入/输出的速度。该参数设置小,意味着数据占用内存空间小,但文件输入/输出速度
较慢。
例如:打开 F:\BASIC\XT 目录下的名字为 F1 的文件,指定文件号为#1 的语句如下。
Open "F:\BASIC\XT\FILE1.TXT" For Output As #1
2.读取顺序文件
在程序中用 Open 语句打开顺序文件时,必须规定打开文件的模式为 Input,表明打开文
件后要对顺序文件进行读操作。VB 能读入的文件并不限于是 VB 制作的文件,任何文本文
件都可当作顺序文件读入。从顺序文件中读入数据的语句和函数有以下三种。
(1)Input#语句
【格式】Input# 文件号,变量表
【功能】从打开的文件中读入数据。读入数据时,将第一个不为空格的字符或数字当作
数据项的开始,遇见空格、逗号或行尾则认为数据项的结束,直至遇到文件结束符时才终止
读操作。
【说明】文件号参数是用 Open 语句打开文件时指定的文件号,变量表是用逗号分隔的一
些变量,将文件中读取的各数据项分别存放到这些变量中。文件中各数据项的数据类型和顺
序与变量列表中各变量类型和顺序必须保持一致。
文件中的字符串数据项若用双引号括起来,双引号内的任何字符(包括逗号)都视为字
符串的一部分,所以若有些字符串数据项内需要有逗号,最好用 Write 语句写入文件,再用
Input 语句读出来,这样在文件中存放数据时就不会出现问题。
(2)Line Input#语句
【格式】Line Input# 文件号,字符型变量
【功能】用来读取顺序文件中的一行数据,并将这些数据存入字符型变量中。它不以逗
号或空格作为数据项的分界符,而是以回车换行符作为一行信息的结束。
【说明】如果文件中没有回车换行符或没有用 Width 语句将文件规定行宽,那么可用该语
句将文件中所含信息全部读入到内存变量中。
(3)Input$函数
【格式】Input$(读取字符数,#文件号)
【功能】该函数用于从打开的文件中读入字符串。
【说明】“读取字符数”参数表示要读字符串中字符个数,该参数取值小于或等于 65535
的整数,函数获取值为读取的字符串,包括回车换行符、空格和逗号等。前面讨论的两种读
入命令都没有读入回车换行等分界符。
228 中文 Visual Basic 6.0 实用教程—结构化程序设计
在程序中可用赋值语句调用此函数,将所读取数据赋给一个字符串变量。
7.1.3 写入顺序文件和关闭顺序文件
1.写入顺序文件
当 Open 语句的模式为 Output 或 Append 时,表明打开文件后要对文件写入数据。当文
件的打开模式设定为 Output 方式时,写操作语句会使数据从文件的开始处写入,如果文件已
存在,文件中原有的数据会被覆盖掉;若文件不存在,则会建立一个新文件,将数据从头开
始写入。当文件的打开模式设定为 Append 时,如果文件已存在,在写入数据时,将新数据
追加到文件中。
因此,一般在将数据写入文件中时,需要根据是否要覆盖原文件中的数据来确定选择采
用 Output 或 Append 模式。对已打开文件进行写操作的语句有 Print 语句和 Write 语句。
(1)Print 语句
【格式】Print #文件号,[表达式表]
【功能】它表示向“文件号”参数指定的已打开的文件中写入表达式列表所表示的信息。
【说明】表达式列表为数值或字符串表达式,各表达式之间用逗号、分号、Tab 函数或
Spc 函数分隔。用 Print 语句向文件中写入数据类似于用 Print 方法向窗体、图片框或打印机
对象上打印信息。
例如:将一些数据写入文件 F1 中的程序如下。
Open "D:\fil1.txt" For Output As #1
Print #1, "沈可的记录"
Print #1, "编号:1"
Print #1,"星期一工作时间:8" Tab(20) "星期二工作时间:9"Tab(40) "星期三工作时间:12"
Print #1,"星期四工作时间:9" Tab(20) "星期五工作时间:8"Tab(40) "星期六工作时间:0"
Print #1,"星期天工作时间:4" Tab(40) "工作时间总计:50"
Close #1
(2)Write 语句
【格式】Write #文件号,[表达式表]
【功能】将表达式表中的数据写入到“文件号”参数指定的文件中。
【说明】用 Write 语句向文件中写入信息时,表达式表中的各数据项之间用“,”分隔符,
若在 Write 语句中省略变量或表达式,将向文件内写入一空行。例如:
Open "Fil1" For Output As #1
Print #1, "沈可记录","星期一工作时间:8" Tab(20) "星期二工作时间:9"Tab(40)
Close #1
(3)文件行宽的确定
文件行宽可由 Width 语句来指定,Width 语句的格式及功能如下。
【格式】Width# 文件号,宽度
【功能】指定文件号所对应文件的行宽,规定文件中每行占多少个字符数。
【说明】“宽度”参数可为数值型表达式,取值为 0~255 之间的整数,向打开的文件中
写入了“宽度”参数规定的字符数后,会自动回车换行。如果行宽为 0(默认)时,表示对
文件的行宽没有限制。
第7章 文件管理 229
7.1.4 项目实现
常上网聊天的人都知道,在聊天的过程中最担心的就是信息泄露,也就是聊天的内容被
其他人看见。为了解决这个问题,可以制作一个文本加密器和一个文本解密器,当要输入信
息的时候使用文本加密器对文本进行加密,要察看信息的时候使用文本加密器对文本进行解
密。该程序只限于对英文文本文件和 ASCII 文本文件进行加密和解密。
加密的原理是将需要加密的所有字符依次转换为 ASCII,然后对其中字符的 ASCII 依次
进行减 9 的操作。最后将加密后的信息保存到程序目录下的 WJBC.TXT 文件中。
程序初始时的显示效果如图 7-1-1 所示。在“加密前的文本”文本框中输入需要加密的
文字后,单击“加密”按钮,可在“加密后的文本”文本框中显示出加密后的文本,如图 7-1-2
所示。单击“保存”按钮,即可将加密后的信息保存到 WJBC.TXT 文件中。
1.设置对象的属性
创建窗体如图 7-1-1 所示,在窗体中,有 3 个标签对象、两个文本框对象和 3 个按钮对
230 中文 Visual Basic 6.0 实用教程—结构化程序设计
象。3 个标签对象分别用于显示“文本文件加密器”、“加密前的文本”和“加密后的文本”
文字,位置如图 7-1-1 所示。将两个文本框的 Text 属性都设置为空,Scrollbars 属性为
“2-Vertival” 。3 个按钮的 Caption 属性分别设置为“加密”、
(纵向滚动条) “保存”和“退出”,
3 个按钮的名称从上到下分别为 CommandJM、CommandBC 和 CommandBC。
2.输入代码程序
Rem 加密
Private Sub CommandJM_Click( )
Dim YWJ, MWJ As String, S As String * 1, ASCIIN As Integer
MWJ = "" '变量 MWJ 用来保存加密结果
YWJ = RTrim$(Text1.Text) '将文本框中的内容保存到 YWJ 变量中
L = Len(YWJ) '将变量 YWJ 的字符串长度保存到 L 变量中
For I = 1 To L
S = Mid$(YWJ, I, 1) '依次从变量 YWJ 中取一个字符
ASCIIN = Asc(S) - 9 '相应的 ASCII 减 9
MWJ = MWJ + Chr$(ASCIIN) '将加密结果保存到变量 MWJ 中
Next I
Text2.Text = MWJ '将加密结果在文本框 Text2 中显示
End Sub
Rem 保存
Private Sub CommandBC_Click( )
Open "WJBC.txt" For Output As #1
Print #1, Text2.Text
Close #1
End Sub
Private Sub CommandQUIT_Click( )
Reset
End
End Sub
在程序中,变量 YWJ 用于保存“加密前的文本”文本框中的字符。变量 L 记录变量 YWJ
中字符的长度。利用循环语句,分别将变量 YWJ 中每一个字符的 ASCII 减 9,并保存到变量
ASCIIN 中。将加密后的字符依次加到变量 MWJ 的尾部。最后,将加密后的文本显示在“加
密后的文本”文本框中。单击“保存”按钮,程序将“加密后的文本”文本框中的信息保存
到 WJBC.txt 文件中。
7.1.5 项目拓展——“文本文件解密器”程序
在上一个实例中介绍了“文本文件加密器”程序的制作方法。在本实例中,将制作一个
“文件解密器”,可以将它和“文本文件加密器”一起,组成“加密、解密”组合。
程序运行后的显示效果如图 7-1-3 所示。单击“打开”按钮,即可打开程序目录下的 WJBC
文本文件,在“解密前的文本”文本框中显示。单击“解密”按钮,可在“解密后的文本”
文本框中显示出加密前的文本,如图 7-1-4 所示。
在本实例中的“文本文件解码器”程序是用于对加密的文本进行解码。解码的原理是依
次取出加密信息中的每一个字母,将其 ASCII 加 9,然后再将其重新组合并显示出来。
第7章 文件管理 231
1.设置对象的属性
创建窗体如图 7-1-3 所示,在窗体中,有 3 个标签对象、两个文本框对象和 3 个按钮对
象。3 个标签对象分别用于显示“文本文件解密器”、“解密前的文本” 、“解密后的文本”文
字,位置如图 7-1-3 所示。将两个文本框的 Text 属性都设置为空,Scrollbars 属性为“2-Vertival”
(纵向滚动条)。3 个按钮的 Caption 属性分别设置为“打开” 、
“解密”和“退出”。
2.输入代码程序
Rem 打开
Private Sub CommandDK_Click( )
Open "WJBC.txt" For Input As #1
Text1.Text = Input$(LOF(1), #1)
Close #1
End Sub
Rem 解密
Private Sub CommandJM_Click( )
Dim YWJ, MWJ As String, S As String * 1, ASCIIN As Integer
MWJ = ""
YWJ = RTrim$(Text1.Text)
L = Len(YWJ)
I=2
S = Mid$(YWJ, 1, 1)
Do While I < L And (S <> Chr(13))
S = Mid$(YWJ, I - 1, 1)
ASCIIN = Asc(S) + 9
MWJ = MWJ + Chr$(ASCIIN)
I=I+1
Loop
Text2.Text = MWJ
End Sub
Private Sub CommandQUIT_Click( )
Reset
End
End Sub
在程序中,变量 YWJ 用于保存“解密前的文本”文本框中的字符。变量 L 记录变量 YWJ
中字符的长度。利用循环语句,分别将变量 YWJ 中每一个字符的 ASCII 加 9,并保存到变量
232 中文 Visual Basic 6.0 实用教程—结构化程序设计
7.2 “学生档案管理”程序
7.2.1 文件的其他划分方式
除了按照文件的存取方式及组成结构对文件进行划分外,还可以按照数据编码方式、特
征属性及数据性质对文件进行划分。其含义如下所述。
1.按照数据编码方式对文件进行划分
(1)ASCII 文件:一般是指数据以 ASCII 进行编码储存的文件。
(2)二进制文件(Binary File):文件中的数据是以二进制格式进行编码保存的。它
是以字节数来定位数据,允许程序按所需的任何方式组织和访问数据,二进制文件可允
许对文件中各字节数据进行存取访问和改变。这类文件灵活性较大,但编程的工作量也
很大。
2.按照特征属性对文件进行划分
(1)系统文件(System File):是由操作系统及其他系统程序信息所组成的文件。这类文
件对用户不直接开放,而只能通过系统调用为用户服务。
(2)隐含文件(Hidden File):是指用户无法通过文件目录方式列出来的文件。这种文件
在磁盘中还是存在的,只是用系统命令不能直接访问和获取它的信息。
(3)只读文件(Read Only File):只能供用户读取数据的文件。程序不能向只读文件写
入信息。
(4)普通文件(Normal File):是指可以进行任意存取和访问的文件。
(5)存档文件(Archive File):它是标志了文件是否被修改过的文件。当新建或修改文
件时,系统会自动设置文件的存档属性,它不影响文件的存取,只表明文件内容被更新。存
档文件提供了一个快速检索文件的途径。
3.按照数据性质对文件进行划分
(1)程序文件(Program File):程序文件又可分为源程序文件、目标文件和可执行文件。
这类文件一般存放程序设计人员编写的程序代码及生成计算机可识别并可执行的目标和执行
文件,例如: “.COM”、“.EXE”、“.BAS”和“.OBJ”等文件。
(2)数据文件(Data File):是指可供不同类型的应用程序进行数据交流的纯数据文件。它
可以由程序进行管理,以文件访问方式进行数据的存取等操作。
7.2.2 打开与读取随机文件
1.打开随机文件
【格式】Open “文件名”For Random As #文件号 Len=记录长度
【功能】打开“文件名”参数指定的随机文件。
【说明】
① “文件号”参数是指打开文件时指定的一个通道序号。
“记录长度”参数给出了一条
第7章 文件管理 233
7.2.3 关闭与写入随机文件
1.关闭随机文件
格式和功能与关闭顺序文件的方法一样。
2.写入随机文件
【格式】Put #文件号,[记录号],变量
【功能】将变量中存放的数据写入到打开文件中由“记录号”参数指定的记录处。
【说明】
① “记录号”参数是从 1 开始的正整数,表示对第几条记录进行写操作,如果省略了
该记录号,则表示从当前位置的下一个字节开始写数据。当记录号省略时,记录号前后的逗
号不能省略。
② 变量应是在进行记录类型(即用户自定义类型)声明时定义的变量。
例如:将随机文件 XSDA 的第 3 条记录改写的程序如下。
234 中文 Visual Basic 6.0 实用教程—结构化程序设计
Type XSJL
XH As String*4
XM As String*6
NL As Integer
End Type
Dim XSJL1 As XSJL
Open "XSDA" For Random As #1 Len=Len(XSJL1)
XSJL1.XH=3
XSJL1.XM="沈可"
XSJL1.NL=18
Put #1,3, XSJL1
Close #1
7.2.4 项目实现
图 7-2-1 “学生档案管理”程序运行后的画面之一
在“查询”按钮右边的文本框中输入一个记录号,再单击“查询”按钮,即可显示出该
记录的内容,如图 7-2-2 所示。如果查询的记录号为 1,则“上一个”按钮为无效。单击“下
一个”按钮,即可显示下一条记录的内容,同时“上一个”按钮变为有效;单击“上一个”
按钮,即可显示上一条记录的内容。如果在查询时要修改记录的内容,单击“修改”按钮,
即可将该记录进行修改。追加记录的功能是将考生信息作为一条记录添加到随机文件末尾,
查询的功能是在窗体内显示“查询”按钮右边文本框中记录号指定的记录内容。
1.设置对象的属性
在窗体中,加入一些标签,用来输入提示信息;再加入两个标签,用来显示总分和平均
分;加入一些文本框,用来显示学生档案的有关内容;加入两个组合框,用来选择学生的籍
贯和年龄(也可以输入新内容);加入两个单选钮,分别用来表示男女性别;加入一个复选框,
用来确定是否获过奖;在控制栏内加入 6 个按钮,用来进行相应的操作。为了使画面好看和
第7章 文件管理 235
规整,加了 3 个框架,用来分别放置不同类型的对象。注意:一定要先加入框架对象,再加
入框架内的对象。
图 7-2-2 “学生档案管理”程序运行后的画面之二
2.输入代码程序
“学生档案管理”程序的代码程序如下。
Private JLH As Integer '变量 JLH 用来保存记录号
Rem 声明用户自定义类型,即记录类型
Private Type XSDADATATYPE '自定义类型的名称为 XSDADATATYPE
XSBH As String * 4 '学生编号
XSXM As String * 8 '学生姓名
XSXB1 As Boolean '学生男性别
XSJG As String * 4 '学生籍贯
236 中文 Visual Basic 6.0 实用教程—结构化程序设计
XSDATYPE.XSCJ(I) = Val(TextCJ(I).Text)
XSDATYPE.XSZF = XSDATYPE.XSZF + Val(TextCJ(I).Text) '求总分
Next I
LabelZF = XSDATYPE.XSZF '在 LabelZF 标签中显示总分
XSDATYPE.XSPJ = XSDATYPE.XSZF / 10 '求平均分
LabelPJ = XSDATYPE.XSPJ '在 LabelPJ 标签中显示平均分
If CheckHJ.Value = 1 Then '学生获奖复选框数据存 XSHJ 变量
XSDATYPE.XSHJ = True
Else
XSDATYPE.XSHJ = False
End If
XSDATYPE.XSDH = TextDH.Text '学生电话文本框内容存 XSDATYPE.XSDH 变量
XSDATYPE.XSYB = TextYB.Text '学生邮编文本框内容存 XSDATYPE.XSYB 变量
XSDATYPE.XSDZ = TextDZ.Text '学生地址文本框内容存 XSDATYPE.XSDZ 变量
Open "F:\VB\素材\XSDA.TXT" For Random As #1 Len=Len(XSDATYPE) '打开文件
Put #1, JLH, XSDATYPE '将变量 XSDATYPE 的内容写入文件
Close #1 '关闭文件
End Sub
Rem 查询下一个记录
Private Sub CommandXY_Click()
JLH = JLH + 1 '将编号变量 JLH 的数值自动加 1
CommandSY.Enabled = True '使[上一个]按钮有效
TextHM.Text = JLH '给 TextHM 文本框赋编号
Open " F:\邮电职高\VB2\素材\XSDA.TXT" For Random As #1 Len=Len(XSDATYPE) '打开文件
Get #1, JLH, XSDATYPE '将文件记录的内容存入变量 XSDATYPE
Close #1 '关闭文件
TextBH.Text = XSDATYPE.XSBH '将 XSDATYPE.XSBH 变量内容存学生编号文本框
TextXM.Text = XSDATYPE.XSXM '将 XSDATYPE.XSXM 变量学生姓名文本框
ComboJG.Text = XSDATYPE.XSJG '将 XSDATYPE.XSJG 变量内容存学生籍贯组合框
ComboNL.Text = XSDATYPE.XSNL '将 XSDATYPE.XSJG 变量内容存学生年龄组合框
TextRQ.Text = XSDATYPE.XSRQ '学生出生日期文本框内容存 XSDATYPE.XSRQ 变量
If XSDATYPE.XSXB1 Then '将 XSDATYPE.XSXB1 变量数据存学生性别单选钮
OptionXB1.Value = True
Else
OptionXB2.Value = True
End If
For I = 1 To 10 '将 XSDATYPE.XSCJ 数组内容保存到学生成绩文本框
TextCJ(I).Text = XSDATYPE.XSCJ(I) '将变量中的学分数据存相应的文本框
Next I
LabelZF = XSDATYPE.XSZF : LabelPJ = XSDATYPE.XSPJ '在标签中显示总分和平均分
If XSDATYPE.XSHJ Then '将 XSHJ 变量数据存学生获奖复选框
CheckHJ.Value = 1
Else
CheckHJ.Value = 0
End If
TextDH.Text = XSDATYPE.XSDH '将 XSDATYPE.XSDH 变量内容存学生电话文本框
第7章 文件管理 239
7.2.5 项目拓展——“员工工作时间管理”程序
1.设置对象的属性
在窗体 From1 的顶部绘制 1 个标签元件,将 Caption 属性设置为“员工工作时间管理”
并更改其字体颜色、大小和字体。在窗体中插入 3 个框架,分别用于插入“员工信息” 、“工
作时间”和“控制栏” 。
将用于存储工作时间的 5 个文本框组成一个对象组,命名为 TextCJ,Index 属性一次设
置为 1,2,3,4,5。窗体中其他元件的命名方法为该元件的元件名称加内容缩写,如“编
号”文本框的名称为“TextBH”。
2.输入代码程序
Private JLH As Integer '变量 JLH 用来保存记录号
Rem 声明用户自定义类型,即记录类型
Private Type DATA
BH As String * 4
XM As String * 8
BM As String * 8
XB As Boolean
DH As String * 12
SJ(1 To 10) As Integer
ZSJ As Integer
End Type
Dim TIMEDATA As DATA
Dim I As Integer
Rem 追加记录
Private Sub CommandZJ_Click( )
TIMEDATA.BH = TextBH.Text
TIMEDATA.XM = TextXM.Text
TIMEDATA.BM = TextBM.Text
TIMEDATA.DH = TextDH.Text
If OptionXB1.Value Then
TIMEDATA.XB = True
Else
TIMEDATA.XB = False
End If
TIMEDATA.ZSJ = 0
第7章 文件管理 241
For I = 1 To 5
TIMEDATA.SJ(I) = Val(TextSJ(I).Text)
TIMEDATA.ZSJ = TIMEDATA.ZSJ + Val(TextSJ(I).Text)
Next I
Label = TIMEDATA.ZSJ
Open "SJGL.TXT" For Random As #1 Len = Len(TIMEDATA)
JLH = LOF(1) / Len(TIMEDATA) + 1
Put #1, JLH, TIMEDATA
Close #1
End Sub
Rem 查询记录
Private Sub CommandCX_Click( )
JLH = Val(TextHM)
If JLH > 1 Then CommandSY.Enabled = True
Open "SJGL.TXT" For Random As #1 Len = Len(TIMEDATA)
Get #1, JLH, TIMEDATA
Close #1
TextBH.Text = TIMEDATA.BH
TextXM.Text = TIMEDATA.XM
TextDH.Text = TIMEDATA.DH
TextBM.Text = TIMEDATA.BM
If TIMEDATA.XB Then
OptionXB1.Value = True
Else
OptionXB2.Value = True
End If
For I = 1 To 5
TextSJ(I).Text = TIMEDATA.SJ(I)
Next I
LabelZSJ.Caption = TIMEDATA.ZSJ
End Sub
Rem 修改记录
Private Sub CommandXG_Click( )
TIMEDATA.BH = TextBH.Text
TIMEDATA.XM = TextXM.Text
TIMEDATA.BM = TextBM.Text
TIMEDATA.DH = TextDH.Text
If OptionXB1.Value Then
TIMEDATA.XB = True
Else
TIMEDATA.XB = False
End If
TIMEDATA.ZSJ = 0
For I = 1 To 5
TIMEDATA.SJ(I) = Val(TextSJ(I).Text)
TIMEDATA.ZSJ = TIMEDATA.ZSJ + Val(TextSJ(I).Text)
242 中文 Visual Basic 6.0 实用教程—结构化程序设计
Next I
Label = TIMEDATA.ZSJ
Open "SJGL.TXT" For Random As #1 Len = Len(TIMEDATA)
Put #1, JLH, TIMEDATA
Close #1
End Sub
Rem 查询下一个记录
Private Sub CommandXY_Click( )
JLH = JLH + 1
CommandSY.Enabled = True
TextHM.Text = JLH
Open "SJGL.TXT" For Random As #1 Len = Len(TIMEDATA)
Get #1, JLH, TIMEDATA
Close #1
TextBH.Text = TIMEDATA.BH
TextXM.Text = TIMEDATA.XM
TextDH.Text = TIMEDATA.DH
TextBM.Text = TIMEDATA.BM
If TIMEDATA.XB Then
OptionXB1.Value = True
Else
OptionXB2.Value = True
End If
For I = 1 To 5
TextSJ(I).Text = TIMEDATA.SJ(I)
Next I
LabelZSJ.Caption = TIMEDATA.ZSJ
End Sub
Rem 查询上一个记录
Private Sub CommandSY_Click( )
JLH = JLH - 1
If JLH = 1 Then CommandSY.Enabled = False
TextHM.Text = JLH
Open "SJGL.TXT" For Random As #1 Len = Len(TIMEDATA)
Get #1, JLH, TIMEDATA
Close #1
TextBH.Text = TIMEDATA.BH
TextXM.Text = TIMEDATA.XM
TextDH.Text = TIMEDATA.DH
TextBM.Text = TIMEDATA.BM
If TIMEDATA.XB Then
OptionXB1.Value = True
Else
OptionXB2.Value = True
End If
For I = 1 To 5
TextSJ(I).Text = TIMEDATA.SJ(I)
第7章 文件管理 243
Next I
LabelZSJ.Caption = TIMEDATA.ZSJ
End Sub
Rem 退出
Private Sub CommandQUIT_Click( )
Reset '关闭所有文件
End
End Sub
在程序的公用部分定义一个名为 DATA 的自定义类型,在该自定义类型中定义若干个变
量,用于存储各种信息。然后将变量 TIMEDATA 定义为自定义类型。
单击“追加”按钮后,将网页中的各种信息分别赋值给 TIMEDATA 自定义类型中的各
个子函数,然后将记录保存在 SJGL.TXT 文件中。
查询记录时,首先获取前面文本框中的数值,然后根据其编号在所有记录中查找编号匹
配的信息并进行显示。
查找上一条或下一条记录时,首先获取文本框中的数值,然后进行加 1 或减 1 操作。显
示出对应编号的记录后,在文本框中显示出该记录的编号。
7.3 中文信息加密和解密
这种加密文件一经打开,可同时进行读/写操作,但一次读写的不是一个数据项,而
是以字节为单位对数据进行访问操作。二进制文件允许用户读写或修改文件中的任何字节
信息。
7.3.1 二进制文件的打开与关闭
1.打开二进制文件
【格式】Open“文件名”For Binary As #文件号
【功能】打开一个“文件名”参数指定的二进制文件。
【说明】在打开二进制文件时,无需指明读写模式,只要打开一次便可用读写语句进行
任意的读写操作。
2.关闭二进制文件
【格式】Close [#文件号]
【功能】关闭文件号指定的二进制文件。
7.3.2 二进制文件的写入与读出
1.写二进制文件的语句
【格式】Put #文件号,[位置],变量
【功能】将变量中存放的数据写入到打开的二进制文件中指定的字节位置处。它写入的
数据等于变量长度的数据。例如,变量为整型变量,则写入两个字节的数据;变量为双精度
变量,则写入 8 个字节的数据。数据写入后,文件指针移动到变量长度位置。
【说明】“文件号”参数为打开文件时设定的文件通道号,“位置”参数为开始写数据的
244 中文 Visual Basic 6.0 实用教程—结构化程序设计
字节位置,即文件指针指向的字节。表明从第几个字节开始写数据,文件中第 1 个字节的位
置为 1,第 2 个字节的位置为 2,依此类推。 “位置”参数为整型数据。
2.读二进制文件语句
【格式】Get #文件号,[位置],变量
【功能】将打开文件中指定位置上的数据读出来存入变量中。读出数据的长度(即数据
的字节数)等于变量的长度。
【说明】
① 如果省略“位置”参数,则表示从当前位置的下一个字节(即文件指针指向的字节)
开始读数据。当“位置”参数省略时,参数前后的逗号不能省略。
② 文件指针指向的字节即为开始读取的字节。文件指针的指向还可以通过 Seek 定位语
句来确定。
3.读二进制文件的函数
【格式】Input[$](字节数,[#]文件号)
【功能】获取从打开文件中读取的数据。
【说明】如果省略“$”,则函数获取的是变体型数据,表示从文件中读取的是变体型数
据。“字节数”参数表示从文件中读取多少个字节的信息,该参数为 1~65 535 之间的整数。
数据的读取位置是从文件指针指向的当前位置的下一个字节。
7.3.3 项目实现
在程序中,将汉字文件作为二进制文件处理,特别要注意汉字文件的保存,以及一个汉
字占用两个字节。
第7章 文件管理 245
1.设置对象的属性
创建窗体如图 7-3-1 所示。在窗体中,有 1 个标签对象、两个文本框对象和 6 个按钮对
象。标签对象用于显示程序的标题“中文信息加密/解密”。两个文本框分别用于显示加密前
的文本和加密后的文本,解密后的文本也会在第二个文本框中显示。单击“加密 1”或“加
密 2”按钮后,可以按照不同的方式对文本进行加密,单击“解密 1”或“解密 2”按钮可以
分别对两种方法加密的文本进行解密。
2.输入代码程序
Private SY As Variant, FLEN As Long
Rem 打开中文文件
Private Sub CommandDK_Click( )
Open "ZWT1.TXT" For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text1.Text = SY
Close #1
End Sub
Rem 加密 1
Private Sub CommandJM11_Click( )
Open "ZWT1.TXT" For Binary As #1
SY = Mid$(SY, 5) + Left$(SY, 4)
Text2.Text = SY
FLEN = Len(SY) '这里的 SY 长度是文件长度的一半
For I = 1 To FLEN
Put #1, I * 2 - 1, Mid$(SY, I, 1) '一个汉字占两个字节
Next I
Close #1
End Sub
Rem 解密 1
Private Sub CommandJM12_Click( )
Open "ZWT1.TXT" For Binary As #1
FLEN = Len(SY)
SY = Right$(SY, 4) + Mid$(SY, 1, FLEN - 4)
Text2.Text = SY
For I = 1 To FLEN
Put #1, I * 2 - 1, Mid$(SY, I, 1)
Next I
Close #1
End Sub
Rem 加密 2
Private Sub CommandJM21_Click( )
Dim I As Long, SM, FLEN1 As Variant
Open "ZWT1.TXT" For Binary As #1
SM = ""
FLEN1 = FLEN / 2
For I = 1 To Int(FLEN1) / 2
246 中文 Visual Basic 6.0 实用教程—结构化程序设计
7.3.4 项目拓展
1.设定文件指针指向的位置
在随机文件和二进制文件中,可通过记录号和字节位置来确定需要访问的数据,那么
在 VB 中有一条移动文件指针的语句,它可设定在打开的文件中下一次进行读/写操作的
位置。
【格式】Seek[#]文件号,位置
【功能】在文件号指定的已打开的文件中,将文件指针移到指定的位置处,然后再对文
件进行读写操作。
【说明】“位置”参数是数值型表达式,它的取值范围为 1~2147483647。对于随机文件,
“位置”参数是记录号,对于二进制文件或顺序文件,“位置”参数是相对于文件头的字节
位置。
2.获取被打开文件的格式
使用 Open 语句可以打开顺序文件、随机文件和二进制文件。如果想知道打开的文件是
何种格式,可使用 FileAttr 函数进行判断。
【格式】FileAttr([文件号]、[文件属性])
【功能】获取被打开文件的模式或操作系统文件句柄的信息,即文件类型信息。在使用
该函数的时候,应注意以下几个问题。
① “文件号”参数是用 Open 语句打开文件时给定的文件序号,以指明该函数获取哪个
被打开文件的属性。
② “文件属性”参数为整型数据,该参数用以规定函数获取什么样的文件类型信息。
当该值为 1 时,函数获取该文件被打开时设定的模式,如表 7-3-1 所示。当该值为 2 时,函
数获取一个由 Windows 环境分配给该文件的文件句柄号,可以将此文件句柄用于 Windows
应用程序接口(Apl)函数中。
7.4 文本文件管理器
7.4.1 对文件操作的函数
1.LOF函数
【格式】LOF(文件号)
【功能】获取由“文件号”参数指定的已打开文件的字节长度。
248 中文 Visual Basic 6.0 实用教程—结构化程序设计
2.FileLen函数
【格式】FileLen(文件名)
【功能】获取“文件名”所指定的未打开文件的字节长度。“文件名”参数可包含全程路
径信息。若该函数中给出的文件名是已打开的文件,则函数获取的文件长度是该文件打开之
前的长度。函数值是一个长整型数值。
3.LOC函数
【格式】LOC(文件号)
【功能】获取由“文件号”参数指定的已打开文件的当前访问位置(即文件指针位置)。
对于顺序文件,可获取文件中当前访问字节位置除以 128 再取整,对于随机文件,可获取上
一次对文件进行读/写操作的记录号,不使用 Loc 的返回值,也不需要使用 Loc 的返回值。
对于二进制文件,可获取读/写的最后字节位置。函数值是长整型数据。
4.Seek函数
【格式】Seek(文件号)
【功能】获取由“文件号”参数指定的已打开文件中文件指针的当前位置。获取值为 1~
2147483647(231−1)之间的整数。该指针位置用来指定下一次读/写操作的数据位置。对于随机
文件,则获取可供读/写的下一个记录号;对于顺序文件和二进制文件,则获取下一个操作要
执行的字节位置。函数值是长整型数据。
5.EOF函数
【格式】EOF(文件号)
【功能】获取“文件号”参数指定的已打开文件的文件指针是否已指向文件尾。若已指
向文件尾,则其值为 True;若未指向文件尾,则其值为 False。使用 EOF 是为了避免因试图
在文件结尾处进行输入而产生的错误。
6.FileDateTime函数
【格式】FileDateTime(文件名)
【功能】获取“文件名”参数指定的文件被创建或最后被修改的日期与时间,获取值为
变体型的日期型数据。“文件名”参数可以包含目录或文件夹以及驱动器。
7.Dir函数
【格式】Dir[$](路径名[,文件属性])]
【功能】获取“文件属性”参数指定属性相匹配的第一个文件名、目录名或文件夹名称。
它必须与指定的模式或文件属性、或磁盘卷标相匹配。以后再调用该函数,则获取下一个与
参数相匹配的文件名。在使用该函数的时候,应注意以下几个问题。
① “路径名”参数是一个字符串表达式,指定文件所在路径名或所要列文件名。支持
多字符的通配符 (*) 和单字符 (?),用来指定多重文件。
② “文件属性”参数为常数或数值表达式,用来指定文件属性。如果省略,则会获取
匹配 pathname 但不包含属性的文件。“文件属性”参数的取值及其功能如表 7-4-1 所示。如
果省略该参数,函数获取普通型的指定文件。
③ 函数值是字符型数据,它必须与“文件属性”参数指定的模式或文件属性、或磁盘
卷标相匹配。
第7章 文件管理 249
表 7-4-1 “文件属性”参数的取值及其功能
值 常 量 功 能
0 vbNormal 指定没有属性的文件,是默认值
1 vbReadOnly 指定无属性的只读文件
2 vbHidden 指定无属性的隐藏文件
4 VbSystem 指定无属性的系统文件
16 vbDirectory 指定无属性文件及其路径和文件夹
注:“文件属性”参数的取值可以相加使用。
11.GetAttr函数
【格式】GetAttr(文件名)
【功能】获取“文件名”参数指定的文件、目录和卷标的属性,如表 7-4-3 所示。
【说明】函数获取值可以是上述值的相加组合,表示文件具有几个属性的组合。如只读
隐含文件,函数获取值为 3。文件名为字符串表达式,包含文件名、路径名或卷标。该函数
值为整型数据。
表 7-4-3 函数获取值及对应文件属性
值 文 件 属 性 常量表示(CONSTANT.XT)
12.Shell函数
【格式】Shell(命令字符串[,窗口类型])
【功能】用来运行一个可执行程序,可用于在 VB 程序中调用并运行其他应用程序。该函
数在前面已经简单介绍过。在使用该函数的使用,应注意以下几个问题。
① “命令字符串”参数是要执行的应用程序文件名或命令。在 VB 中用 Shell 函数可
执行的文件包括.COM 文件、.EXE 文件、.BAT 文件和.PIF 文件。在该参数中如果指定的是
非当前目录下的执行文件,那么必须要有全程路径名。
② “窗 口类型 ”参 数是表示 由用户规定执行程序时,窗口以什么样的窗口类型显示,
它为整型数据。
③ 如果程序执行成功,函数将获取程序的任务句柄,该句柄在调用 APl 函数时有用。
如果函数运行程序不成功,则获取错误报文信息。
④ 使用 Shell 函数时应特别注意,应有足够的内存保持 Windows、VisualBasic、当前运
行的所有程序、DOS 的新拷贝及 Shell 函数运行的程序同时装入内存,由 Windows 对内存进
行管理。
例如:X=Shell("Format A:") 语句可将磁盘 A 格式化。
X=Shell("Copy F1+F2”)或 X=Shell("Copy"+"F1"+"+"+"F2")语句可将两文件(F1
和 F2)连接在一个文件 F1 中,达到修改而不覆盖原文件内容目的。
第7章 文件管理 251
7.4.2 对文件操作的语句
【功能】将源文件拷贝到目的文件,文件名可包含路径名。不能拷贝已打开的文件。
8.SetAttr语句
【格式】SetAttr “文件名”,属性值
【功能】为“文件名”参数指定的文件设定文件属性。
【说明】文件名字符串中可包含路径,属性值为整型常量。不能对打开的文件进行操作。
9.Reset语句
【格式】Reset
【功能】将所有打开的磁盘文件关闭且将文件缓冲区中的内容写入磁盘中。
例如:在 F 驱动器的根目录下创建一个新目录 VB 的语句是:MkDir “D:\VB”
将 F:\VB 目录下所有.BAK 文件删除的语句是:Kill “D:\VB\*.BAK”
将当前目录下的文件 T1.TXT 移到 D:\VB 目录下的语句是:
Name “T1.TXT” As “D:\VB\T1.TXT”
7.4.3 项目实现
图 7-4-1 程序运行后的显示效果
1.设置对象的属性
创建窗体如图 7-4-1 所示。在窗体中,有两个标签元件、3 个文本框元件和 5 个按钮元件。
两个标签元件分别用于显示“文本文件管理器”文字和“文件的路径和文件名”文字。第 1
个文本框元件用于显示文件中的信息,将 Scrollbars 属性设置为“2-Vertival”(纵向滚动条)。
第 2 个文本框元件用于输入文件的路径和文件名,第 3 个文本框用于输入要更改的文件名。5
个按钮元件分别为“打开” 、“保存”、“删除”、“更名”和“退出”。
2.输入代码程序
Rem 打开
Private Sub Command1_Click( )
Dim SM As Variant
SM = Text2.Text
Open SM For Binary As #1
第7章 文件管理 253
7.4.4 项目拓展——“文本文件察看器”程序
1.“文本文件察看器”程序对象属性设置
创建窗体如图 7-4-2 所示。在窗体中,有 1 个标签对象、两个框架、1 个下拉列表框、两
个文本框对象和 3 个按钮对象。标签对象用于显示程序的标题“中文文件察看器”。两个框架
分别用于显示下拉列表框和制定程序。第 2 个文本框用于显示打开文件的内容。
2.“文本文件察看器”程序的程序代码
Private Sub Command2_Click( ) ;打开按钮 2
Dim SM, SY As Variant , FLEN As Long
SM = Text1.Text
Open SM For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text2.Text = SY
Close #1
End Sub
Private Sub Command3_Click( ) '打开按钮 1
Dim SM, SY As Variant,FLEN As Long
Select Case Combo2.ListIndex
Case 0
Open "ZWT1.TXT" For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text2.Text = SY
Close #1
Case 1
Open "ZWT2.TXT" For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text2.Text = SY
Close #1
Case 2
Open "ZWT3.TXT" For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text2.Text = SY
第7章 文件管理 255
Close #1
Case 3
Open "ZWT4.TXT" For Binary As #1
FLEN = LOF(1) '获得文件的长度
SY = Input(FLEN, #1)
Text2.Text = SY
Close #1
End Select
End Sub
Rem 加载选项
Private Sub Form_Load( )
Combo2.AddItem "文本文件 1"
Combo2.AddItem "文本文件 2"
Combo2.AddItem "文本文件 3"
Combo2.AddItem "文本文件 4"
End Sub
Private Sub Command1_Click( )
End
End Sub
在加载窗体时,使用 AddItem 函数为下拉列表框添加 4 个列表项,“打开”按钮的程序
中,使用分支语句和 ListIndex 函数判断下拉列表框中选中的列表项,然后在第 2 个文本框中
显示该文件中的内容。打开指定程序的方法前面已经介绍过,此处不再描述。
思考与练习
1.填空题
(1)文件是 ,它可以 ,由 组成了文件。
(2)按照存取方式及组成结构对文件进行划分,文件可分为 和 两类;
按照数据编码方式对文件进行划分,文件可分为 和 两类。
(3)记录是由 组成的,数据项又是由 组成的。
(4)顺序文件是 文件,每条记录的长度可 。
(5)随机文件的每条记录都是 ,每条记录都有 ,每条记录中各数据项
的 和 不同。
(6)随机文件适合于 的文件。随机文件的缺点是 。
2.三种文件各有什么特点?如何进行读写操作?EOF、LOC 和 LOF3 个函数有什么不同?
3.将 7.1 和 7.2 节中的程序进行合并,制作一个即可以对文本文件进行加密,又可以进
行解密的程序。
4.用不同的方法将两个文本文件连接到一起,形成一个新的文本文件。
5.使用两种方法对两个或多个文本文件进行连接,将连接后的文件保存为一个新的文件。
6.制作一个程序,在该程序中包括一个文本框和一个“打开”按钮,单机“打开”按
钮后,会在指定的几个文件中随机打开一个文件,并在文本框中显示出该文件中的信息。
7.制作一个“文件管理器”程序,如图 7-1 所示。利用该程序可以对二进制文件进行“打
256 中文 Visual Basic 6.0 实用教程—结构化程序设计
开”、“保存”、“更名”和“拷贝”等操作。
图 7-1 文件管理器
应用程序类型的名称和说明
附录 1
“新建工程”对话框给出了要选择建立的项目类型,选择不同的项目,可以确定用 Visual
Basic 6.0 开发的应用程序的类型,其中主要的应用程序类型的名称和说明如附表 1 所示。
附表 1 应用程序类型的名称和说明
应用程序类型名称 应用程序的说明
VB 应用程序向导 使用应用程序向导可以在开发环境中直接建立新的应用程序框架。在开发自己的项目时,可以使用
这个工具,并参考它所提供的应用程序原始类型
数据工程 为编程人员提供开发数据报表应用程序的框架。自动打开数据环境设计器和数据报告设计器
VB 企业版控件 这类项目是企业版所特有的,用于开发企业版应用程序。如果使用的是专业版软件,将会有“专业
版控件类型”
主菜单中各类菜单命令的作用
附录 2
附表 2-1 “文件”菜单
序 号 菜单项名称 菜单项功能
1 新建工程 建立一个新的工程文件
2 打开工程 打开一个已存在的工程文件
3 添加工程 在打开的工程组中增加一个新工程
4 移除工程 移除指定的工程
5 保存工程 保存当前正在编辑的工程
6 工程另存为 将工程按指定名称重新保存
7 保存窗体 保存当前窗体
8 窗体另存为 将窗体按指定名称重新保存
9 保存选择 仅保存选择的内容
10 保存更改的脚本 将更改后的脚本进行保存
11 打印 打印窗体或代码
12 打印设置 设置打印信息
15 文件 1、2、3、4 最近打开的四个工程(.vbp)或工程组(.vbg)的名字
16 退出 退出 Visual Basic
附 表 2-2 “编辑”菜单
序 号 菜单项名称 菜单项功能
1 撤消 取消最近的一次操作
2 重复 重复最近的一次操作
3 剪切 将被选中的内容删除并放到剪贴板中
4 复制 将被选中的内容拷贝到剪贴板中
5 粘贴 将剪贴板中的内容粘贴到光标所在处
7 移除 将表从数据库中移除
8 删除 删除被选中的控件、文本或查看表达式等
9 从数据库删除表 将数据库表从数据库中物理删除
附录 2 主菜单中各类菜单命令的作用 259
续表
序 号 菜单项名称 菜单项功能
10 全选 选中代码窗口中所有内容
11 选择全部列 选择数据库表的全部列
12 表 对数据库表进行设置主键、插入和删除列等操作
13 查找 查找指定的字符串等内容
14 查找下一个 查找指定的内容下一次出现的位置
15 替换 查找指定的内容并用新的内容替换
16 缩进 使选择的文本行向右移一个 Tab 位置
17 凸出 使选择的文本行向左移一个 Tab 位置
18 插入文件 把一个已打开的文件代码插入到当前位置
19 属性仿法列表 在“代码”窗口中用下拉式列表框显示对象的属性和方法
20 常数列表 列出属性的有效值
21 快速信息 显示“代码”窗口中选择的变量等信息
22 参数信息 显示函数或语句的参数信息
24 到行 移动数据库表的行
25 书签 建立或取消占位符,移动到下一个或前一个书签,清除所有书签
附表 2-3 “视图”菜单
序 号 菜单项名称 菜单项功能
1 代码窗口 激活相应对象的“代码”窗口
2 对象窗口 显示激活的对象
3 定义 显示光标所在处的变量或过程的定义
4 最后位置 在“代码”窗口中使光标回到上一次的位置
5 对象浏览器 显示对象浏览器,列出有关信息
6 立即窗口 在“立即”窗口中显示调试语句和输入命令的结果
7 本地窗口 在“本地”窗口中显示当前栈中的所有变量及它们的值
8 监视窗口 在“监视”窗口中显示当前观察表达式的值
9 调用堆栈 显示“调用堆栈”对话框,在中断模式下列出一个过程正在调用的其他过程
10 工程资源管理器 显示“工程资源管理器”窗口
11 属性窗口 显示“属性”窗口
12 窗体布局窗口 显示“窗体布局”窗口,可以用来预览和改变窗体的初次显示位置
13 属性页 显示用户控件的属性页
14 表 显示数据库表的列属性、引名称、关键字等
15 缩放 选择显示的比例
续表
序 号 菜单项名称 菜单项功能
18 数据视图窗口 显示数据视图窗口
19 调色板 激活并调用调色板
20 工具栏 显示工具栏
附表 2-4 “工程”菜单
序 号 菜单项名称 菜单项功能
1 添加窗体 在工程中加入一个窗体
3 添加模块 在工程中加入一个模块
4 添加类模块 在工程中加入一个类模块
5 添加用户控件 在工程中加入一个用户控件
6 添加属性页 在工程中加入一个新的或现有的属性页
7 添加用户文档 在工程中加入一个新的或现有的用户文档
13 添加文件 在工程中加入一个文件
14 移除(窗体) 在工程中移除选择的窗体
15 引用 在工程中加入一个对象库或类库
16 部件 在工具箱中加入控件、设计器和对象
17 (工程名)属性 观察选定的工程的属性
附表 2-5 “格式”菜单
序 号 菜单项名称 菜单项功能
1 对齐 以最后选择的对象为基准,将选中的对象对齐
2 统一尺寸 使选择的对象大小相同
3 按网格调整大小 按照窗体上最近的网格线调整对象的高度和宽度
4 水平间距 改变对象之间的水平距离
5 垂直间距 根据具有焦点的对象调整对象之间的垂直距离
6 在窗体中居中对齐 把选择的对象调整到窗体的中央
7 顺序 改变窗体中对象的顺序
8 锁定控件 把窗体上的所有控件锁定在当前位置,以免在设计时移动它们
附录 2 主菜单中各类菜单命令的作用 261
附表 2-6 “调试”菜单
序 号 菜单项名称 菜单项功能
1 逐语句 每次运行只执行一条语句
2 逐过程 每次运行只执行一个过程
3 跳出 跳出运行状态
4 运行到光标处 在中断模式下,程序执行到光标所在的位置
5 添加监视 在设计时或中断模式下,输入监视表达式
6 编辑监视 编辑或删除监视表达式
7 快速监视 显示监视表达式的当前值,可以用来查看变量、属性和其他表达式的值
8 切换断点 在当前行设置或取消一个断点
9 清除所有断点 清除工程中的所有断点
10 设置下一条语句 设置下一条要执行的语句
11 显示下一条语句 加亮显示下一条要执行的语句
附表 2-7 “运行”菜单
序 号 菜单项名称 菜单项功能
1 启动 运行工程管理器中的启动工程
2 全编译执行 对工程进行完全编译并运行
3 中断 当一个程序正在运行时中断它,进入中断模式
4 结束 停止运行程序,返回设计状态
5 重新启动 在中断之后重新开始执行应用程序
1 运行 运行设计的数据库查询语句
2 消除结果 消除数据库查询结果
4 分组 对结果进行分组
5 更改类型 对数据库表进行插入、更新、删除等操作
6 添加到输出 将结果添加到输出列表中
7 升序排序 对查询结果按照升序排序
8 降序排序 对查询结果按照降序排序
9 删除过滤器 删除查询的过滤器
附表 2-9 “图表”菜单
序 号 菜单项名称 菜单项功能
1 新建文本批注 在数据库图表中增加文本批注
2 设置文本字体 修改批注等文本信息的字体
262 中文 Visual Basic 6.0 实用教程—结构化程序设计
续表
序 号 菜单项名称 菜单项功能
3 添加关联表 在已有的数据库图表中增加一个与现有数据库表相关联数据表
4 显示关联标签 显示数据库表之间关联标签的名称
5 修改自定义视图 对数据库图表的显示方式进行修改
6 显示分页标记 显示数据库图表的分页标记
7 重新计算分页 重新计算数据库图表的分页
8 选项对齐 选定内容对齐
9 表对齐 数据库图表中的表图标对齐
10 调整选定表 对数据库图表中选定的表图标进行调整
附表 2-10 “工具”菜单
序 号 菜单项名称 菜单项功能
1 添加过程 在活动的模块中添加一个新的子程序(Sub)、函数(Function)、属性(Property)
或事件(Event)过程
2 过程属性 设置与对象的属性和方法有关的性质
3 菜单编辑器 显示“菜单编辑器”对话框
5 发布 发布应用程序
附表 2-11 “外接程序”菜单
序 号 菜单项名称 菜单项功能
l 可视化数据管理器 打开后可以访问或操作数据
附表 2-12 “窗口”菜单
序 号 菜单项名称 菜单项功能
1 拆分 用水平线分隔或取消代码窗口
4 层叠 在 MDI 模式中使“对象”、“代码”窗口和对象浏览器层叠排列
5 排列图标 在窗口左下角排列最小化窗口的图标
6 窗口列表 显示所有打开的窗口
附表 2-13 “帮助”菜单
序 号 菜单项名称 菜单项功能
1 内容 运行帮助,显示帮助的目录和索引
2 索引 打开帮助系统
附录 2 主菜单中各类菜单命令的作用 263
续表
序 号 菜单项名称 菜单项功能
3 搜索 打开在线文档
Pointer(指针) 这是工具箱中惟一没有控制功能的对象。在某—控件被加入到窗体中后,可以移动它的位置,
改变大小。当指针对象被选定后,只能移动控件以及改变大小。当向窗体中添加某一控件后,
指针对象将被自动选定
PictureBox(图片框) 用来显示一幅图画。也可作为一个容器,接收图片方式的输出,还可以像窗体一样作为其他
控件的载体
Label(标签) 用来显示不想让其他用户改变的文本,例如一幅画的标题
CommandButton(命 这是一个比较常用的控件,用来建立实现命令的按钮
令按钮)
OptionButton( 选 项 也叫单选框或单选按钮。这个控件是对话框中常见的组成部分,当在对话框中放置了多个选
按钮) 项按钮控件后,程序运行时用户只能从中选中一个
ListBox(列表框) 用来显示可做单一或多个选择的列表项。如果列表项太多,一个滚动条将自动加到列表框中
Hscrollbar( 水 平 滚 提供一个可视的工具,用它可以快速浏览一个具有很多条目的列表框或拥有大量信息的文本
动条) 框,也可以作为一个输入的指示设备,例如控制电脑游戏中的声音
Vscrollbar( 竖 直 滚 它的功能和水平滚动条基本相同,只是显示的方向不同
动条)
Timer(时钟) 实现以规则的时间间隔执行程序代码来触发某种事件,它在程序运行阶段是不可见的
DriveListBox( 驱 动 使用这个控件能够显示在系统中所有可用驱动器的列表,用户可以在运行阶段选择一个可用
器列表框) 的驱动器
DirListBox( 目 录 列 它和驱动器列表框的作用很相似,用于显示目录及路径
表框)
FileListbox(文件列 用于显示当前目录中所有文件的列表框,它和驱动器列表框、目录列表框结合起来使用,将
表框) 实现文件的查询功能
附录 3 工具箱中基本控件工具的名称和功能 265
续表
图 标 名 称 功 能
OLEContainer(OLE 可以在某一应用程序中嵌入其他应用程序对象
容器)
Visual Basic 6.0 试卷
附录 4
试卷(A)
一、填空(40 分,每个填空 1 分)
二、回答问题(10 分)
1.表达式有几种?算术运算符包括哪些?它们的运算顺序是怎样的?
答:(4 分)
(2)
(2)
三、分析程序运行结果(30 分)
2.写出程序中每一条语句的作用
Private Sub Form_Load()
268 中文 Visual Basic 6.0 实用教程—结构化程序设计
Show
Dim FS As Integer
FS = InputBox("请输入成绩:")
If FS >= 90 Then
Print "优!"
ElseIf FS >= 80 Then
Print "良!"
ElseIf FS >= 60 Then
Print "及格!"
Else
Print "不及格!"
End If
End Sub
答:(4 分)
3.A=1:B=2:C=3
For I=0 To 4
X=A:A=B:B=C:C=X
Print A,B,C
Next I
答:(5 分)
4.A=1:B=10:C=2
For I=A To B Step C
A=A+B:B=B+C:C=C+A
I=I+2
Print A,B,C
Next I
答:(3 分)
7.A=1:B=1
While A<=5
While B<=A
Print A,B
B=B+2
Wend
A=A+2
Wend
Print A,B
答:(4 分)
270 中文 Visual Basic 6.0 实用教程—结构化程序设计
四、采用时钟控件编写显示三角形图案的程序(20 分)
程序运行后的画面如图 1 所示,此时窗体中只有“输入行数”按钮是有效的。
单击“输入行数”按钮后,弹出一个“输入行数”对话框,该对话框的提示信息是“请输
入三角形的行数”和“3 到 17 之间的整数”
,输入文本框中的默认值为 17,如图 2。不改变该
对话框中的文本框内的数值,单击“确定”按钮,又回到窗体,此时各个按钮均变为有效。
图1 图2
单击“三角形”按钮,即可在窗体中显示出由“*”组成的三角形图案,如图 3 所示;
单击“倒三角形”按钮,即可在窗体中显示出由“*”组成的倒三角形图案,如图 4 所示。
图3 图4
控件对象的属性设置如下:
序 号 类 别 名 称 Caption 文字特点或 Interval Enabled
1 窗体 Form1 显示字符三角形 12 号、黑色 True
2 按钮 输入行数 输入行数 12 号、黑色 True
3 按钮 三角形 三角形 12 号、黑色 False
4 按钮 倒三角形 倒三角形 12 号、黑色 False
5 按钮 退出 退出 12 号、黑色 True
6 时钟 Timer11 无 Interval=100 False
7 时钟 Timer12 Interval=0 False
8 时钟 Timer21 Interval=100 False
9 时钟 Timer22 Interval=0 False
答:输入代码程序如下:
附录 4 Visual Basic 6.0 试卷 271
试卷(B)
一、填空(40 分,每个填空 1 分)
二、回答问题(10 分)
1.如何使用工具箱中的控件工具在窗体中创建控件对象?
答:(2 分)
2.打开“代码”窗口的方法是什么?如何打开“工程资源管理器”?
答:(2 分)
272 中文 Visual Basic 6.0 实用教程—结构化程序设计
3.如何运行程序?如何使运行的程序停止运行?(各有两种方法)
答:(2 分)
4.如果有多个工程文件,应如何操作就可以运行任何一个工程文件?
答:(2 分)
5.如果有多个窗体文件,应如何操作就可以运行任何一个窗体文件?
答:(2 分)
三、分析程序运行结果(30 分)
1.For A=1 To 20
If A Mod 2=1 Then
Print A,
End If
Next A
答:(4 分)
2.写出程序中每一条语句的作用和整个程序的作用
Private Sub Form_Activate()
Dim N As Integer, SUM, SUN1 As Long
SUM = 0: SUM1 = 0
For N = 1 To 100
SUM = SUM + N
SUM1 = SUM1 + SUM
Next N
Print SUM1
End Sub
附录 4 Visual Basic 6.0 试卷 273
答:(8 分)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
整个程序是求:
3.For A=1 To 5
Print Tab(10-A);
For B=1 TO 2*A-1
Print “*”;
Next B
Print
Next A
答:(4 分)
4.A=1:B=3:I=5
Do
C=A:A=B:B=C
Print A,B,C
I=I−2
Loop Until I<=0
Print A,B,C
答:(4 分)
5.I=1
While I<=5
Print I,
274 中文 Visual Basic 6.0 实用教程—结构化程序设计
I=I+2
Wend
Print "I=";I
答:(4 分)
7.A=3:B=4
While A>=1
While B>=A
Print A,B
B=B-2
Wend
A=A−2
Wend
Print A,B
答:(3 分)
四、字母水平来回移动的程序(20 分)
程序运行后的画面如图 1 所示。单击窗体中的“开始”按钮,即可看到一个字母从左向
右移动,移到最右边后,另一个字母又从右向左移动。周而复始,不断来回移动,如图 2 所
示。在字母来回移动的过程当中,字母不断改变、颜色也在不断变化。单击窗体中的“退出”
按钮后,可使程序中止运行。
附录 4 Visual Basic 6.0 试卷 275
图1
图2
图3
控件对象的属性设置如下:
序 号 类 别 名 称 Caption 文字特点或 Interval Enabled
6 按钮 Command1 开 始 12 号 True
9 按钮 Command2 结 束 12 号 True
答:输入代码程序如下:
部分参考答案
附录 5
第1章 思考与练习
1.填空题
(1)学习版(Learning) 专业版(Professional) 企业版(Enterprise)
(2)文件 编辑 视图 工程 格式 调试 运行 查询 图表 工具 外接程序窗
口 帮助
(3)工程 类型文件
(4)工程 .vbp 窗体 .frm 标准模块 .bas 类模块 .cls 资源 .res .ocx
(5)工程资源管理器 “视图” “工程资源管理器”
(6)“对象”下拉列表框 “过程”下拉列表框 程序编辑区域 “过程查看”按钮“全
模块查看”按钮
(7)单击“视图”→“代码窗口”菜单命令 单击选中一个对象,单击鼠标右键,弹出
它的快捷菜单,再单击该菜单中的“查看代码”命令;在调出代码编辑器的同时,也创建了
该对象的一对过程头和过程尾语句 双击某一个对象,在调出代码编辑器的同时,也创建了
该对象的一对过程头和过程尾语句
(8)对象 代码 数据
(9)属性分类 英文字母
(10)使用“属性”窗口修改其属性值来完成 在程序中使用代码来完成
(11)改变对象属性的 针对对象进行操作的程序和改变对象属性值的程序
(12)鼠标事件 键盘事件
(13)结构化程序设计 面向对象程序设计 事件驱动程序设计 顺序 选择 循环
(14)“开始” “所有程序” “Microsoft Developer Network” “MSDN Library Visual Studio 6.0”
(15)从左至右、自顶向下地顺序执行 并不一定都要执行 “无论分支多少,仅选其
一”
(16)反复执行 不成立后(或成立后)
第2章 思考与练习
1.填空题
(1)字母 汉字 255 40 1
附录 5 部分参考答案 277
(2)标准数据类型 用户自定义数据类型
(3)字节型 布尔型 整型 长整型 单精度型 双精度型 货币型 日期型 变长字
符型 定长字符型 对象型 变体型(数值) 变体型(字符)
(4)一般表示法 序号表示法
(5)变体型
(6)255 “: ”
(7)一个空格和一个下划线
(8)9.6 99 E 9
(9)−12 12 89 9 2008 年北京奥运”2008 年北京奥运
(10)中华人民 8 年北京奥运 接 2008 年 ABC123
(11)10 1 −1 1 −1 64
(12)56 13 −1 −5 −6 5 5
3.合法的数据:(2) (7) (8) (9) (10) (12)
4.Visual Basic 的变量:(1)
(2)
(3)(5) (8)
(9)(10)(11)
(13)
(14)
(15)
(16)
6.False False True
第3章 思考与练习
1.填空题
(1)为了解决一个特定问题而采取的特定和有限的操作步骤,就是用于求解某个特定问
题的一些指令的集合 流程图 N-S 图 PAD 图
(2)有穷性 确定性 可行性 输入性 输出性
(3)顺序结构 选择结构 循环结构
(4)关系表达式表达 逻辑表达 数值表达式 数值形式的字符串表达式
(5)内循环与外循环的循环变量名称不能够相同 外循环必须完全包含内循环,不可以
出现交叉现象 不可以没有执行 For 语句,就执行 Next 语句
(6)图形
(7)图形 流程线 矩形框内
(8)问题分析图 图形 二维 上到下 层次 层次清楚 逻辑关系明了 在有多次嵌
套时,不易出错
(9)当型 Do Loop 语句是先判断条件,再执行循环体语句序列中的语句
2.下面程序运行后的结果是什么?
(1)
(2)输入物体重量。根据重量显示相应信息。重量大于等于 30 时,显示"超重!超重部
分需补交运费";否则显示"没超重!不用补交运费!" 。
278 中文 Visual Basic 6.0 实用教程—结构化程序设计
(3)
第 1 小题 第 2 小题
第 3 小题 第 4 小题
第 5 小题 第 6 小题
第 7 小题 第 8 小题
第 9 小题 第 10 小题
(4)输入一个数,根据其值显示不同的数字。
附录 5 部分参考答案 279
第5章 思考与练习
1.填空题
(1)一组具有相同数据结构的元素组成的数据集合 构成数组的各个数据或变量
(2)常规数组 动态数组
(3)大小固定的数组,也就是说常规数组中包含的数组元素的个数不变 只有在程序的
执行过程中才给数组开辟存储空间,在程序未运行时,动态数组不占用内存,可以将这部分
存储空间移作他用 不变 大小 不变
(4)定义数组
(5)这些元素 数组名 数组元素 下标变量 数组名 序号
(6)变量
(7)数组下标 一个变量名
(8)常量 变量 数值型表达式
2.分析下面Visual Basic程序的运行结果
第6章 思考与练习
1.填空题
(1)系统提供的过程 由用户自己定义、可供事件过程多次调用的自定义过程 Sub 子
过程 函数过程 属性过程 “Event”保留字开始的事件过程
(2)Sub 子过程名[实参列表] Call Sub 子过程名(实参列表)
280 中文 Visual Basic 6.0 实用教程—结构化程序设计
(3)被调过程中的参数 在主调过程(主过程)中的参数
(4)把形参变量的内存地址传递给被调用过程 Visual Basic 给形参分配一个临时的内存
单元,将实参的值传递到这个临时单元
(5)标准模块 过程
(6)所在的过程 所在的模块 整个应用程序
(7)模块级 全局
(8)可以用递归形式来表示一个问题 递归结束的条件,程序的运行可使递归结束条件
成立
第7章 思考与练习
1.填空题
(1)存储在外部介质(如磁盘)上的数据的集合 永久性地保存信息 记录的集合
(2)顺序 随机 文本文件 二进制文件
(3)一些数据项 各种字符
(4)一条条记录按顺序进行存放的 可按需要变化
(5)固定长度 记录号 数据类型 占空间字节数
(6)需要进行数据库访问、快速查找、经常更新数据 在同样内容的情况下,所占的磁
盘空间较大,程序设计较繁琐
Scratch儿童编程: http://shop120628677.taobao.com
八百媳妇理财博客: http://www.babaixifu.com
5岁儿童编程下载 http://babaixifu.com/shares/