You are on page 1of 288

中等职业学校计算机技能型紧缺人才培养规划教材

计算机软件专业

中文 Visual Basic 6.0 实用教程


——结构化程序设计
沈大林 杨旭 关点 杜金 等编著

人 民 邮 电 出 版 社
图书在版编目(CIP)数据
中文 Visual Basic 6.0 实用教程:结构化程序设计/沈大林,杨旭,关点,杜金编著.
—北京:人民邮电出版社,2005.6
中等职业学校计算机技能型紧缺人才培养规划教材.计算机软件专业

ISBN 7-115-13279-8

Ⅰ.中… Ⅱ.①沈… ②杨… ③关… ④杜… Ⅲ.BASIC 语言-程序设计-专业学校-教


材 Ⅳ.TP312

中国版本图书馆 CIP 数据核字(2005)第 047457 号

内 容 提 要

本书按项目驱动方式,以知识点配合实例的方法进行讲解,同时注意到知识的完整性、系统性和实用
性。全书共分 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
中等职业学校计算机技能型紧缺人才培养规划教材
编 委 会

主 任 武马群

副 主 任 韩立樊 吴清平 王晓丹

委 员 (以汉语拼音为序)
陈道波 陈丽敏 韩祖德 李 红 李文刚 李亚平
刘玉山 潘 沈大林 苏永昌 孙振业 谭建伟
王宇昕 向 伟 许成云 詹 虹 张惠珍 张 平
张世民 周越山 朱荣国 朱同庆

秘 书 张孟玮 赵鹏飞
编者的话

Visual Basic 语言是在 Basic 语言的基础之上推出的,它继承了 Basic 语言面向普通使


用者和易学易用的优点,同时又引入了可视化图形用户界面的程序设计方法和面向对象的
机制。
所以 Visual Basic 语言具有为广大非计算机专业人员学习、
使用、研究和开发 Windows
环境下应用程序的特点。
本书共分 7 章,各章均结合所介绍的知识配有大量实例,章后提供大量习题。第 1 章
介绍中文 Visual Basic 6.0 工作环境和基本操作方法,结构化程序设计概述;第 2 章介绍中
文 Visual Basic 6.0 编程基础;第 3 章介绍基本算法、选择结构语句和循环结构语句;第 4
章介绍优化算法和程序设计方法;第 5 章介绍数组和数据结构基础;第 6 章介绍过程和自
定义数据类型;第 7 章介绍文件管理。
本书根据教育部建议“采用项目教学”的要求,充分体现项目教学的精神,采用知识
点配合实例的方法进行讲解,同时注意到知识的完整性、系统性和实用性。全书除了介绍
大量的知识点外,还介绍了近 100 个应用实例,300 多道思考与练习题。程序实例有详细
的讲解,容易看懂、便于教学,读者可以先了解相关的知识点,然后跟着实例进行操作,
轻松掌握中文 Visual Basic 6.0 软件的编程方法。
本书内容由浅入深、由易到难、循序渐进、图文并茂,理论与实际操作相结合,可使
读者在阅读的过程中边操作边学习,不但能够快速入门,而且可以达到较高的水平。
本书的特点是:按节细化了知识点,并结合知识点介绍了相关的实例,每节的名称就
是要完成的项目的名称(即实例的名称),在每节的一开始介绍了与本节项目有关的知识,
每节的“项目实现”内介绍了完成该项目的操作过程和方法,每节的“项目拓展”内介绍
了与本节项目和相关知识点有关的拓展实例和拓展知识。
本书的作者包括学校的骨干计算机教师、程序人员和公司内的培训工程师,他们具有
丰富的教学实践经验,并总结出了一套容易让学生接受的项目驱动式教学方法,提高了教
学的效率和质量。在教学过程中,建议教师在使用本书进行教学时,一边带着学生做每章
中的实例,一边讲解各实例中的知识点,将它们有机地结合在一起,可以达到良好的教学
效果。对于基础较差的学生,可以不讲述第 6 章的内容。
参加本书编写工作的主要人员有:杨旭、关点、杜金、魏雪英、沈大林、曲彭生、沈
昕、肖柠朴、毕凌云、张铮、李强、姜树昕、马开颜、郝侠、李征、张磊、刘庆荣、崔元
如、杨艳清、张伦、陈一兵、马骏、于金霞、季明辉、康生强、郭鸿博、杨来英、李瑞梅、
李稚平、赵艳霞、石淳、董鑫、赵亚辉、关山、胡野红、闵光岳等。
由于技术的不断变化以及操作过程中的疏漏,
书中难免有不妥之处,
恳请广大读者批评指正。

编者
丛书前言

实施信息化的关键在人才,在我国各行各业都需要大批的各个层次的计算机应用专业人
才。在未来几年内,我国经济和社会发展对计算机应用与软件专业初级人才具有很大的需求,
而这些人才的培养主要应由中等职业教育来承担。要培养具备综合职业能力和全面素质,直
接在生产、服务、技术和管理等第一线工作的技能型人才,必须在课程开发上,从职业岗位
技能分析入手,以教材建设推动中等职业教育教学改革,从而提高中等职业教育质量。
人民邮电出版社根据《教育部等七部门关于进一步加强职业教育工作的若干意见》
的指示精神,在深入调查研究的基础上,会同企业技术专家、中等职业学校教师、职业
教育教研人员按照专业的“培养目标与规格”教学要求进行整体规划设计了本套教材。
本套教材以教育部办公厅、信息产业部办公厅联合颁布的“中等职业学校计算机应用与
软件技术专业领域技能型紧缺人才培养培训指导方案”为依据,遵循“以全面素质为基
础,以职业能力为本位;以企业需求为基本依据,以就业为导向;适应行业技术发展,
体现教学内容的先进性和前瞻性;以学生为主体,体现教学组织的科学性和灵活性”等
技能型紧缺人才培养培训的基本原则。
本套教材适用于中等职业学校计算机及相关专业,按计算机软件、多媒体应用技术、
计算机网络技术及应用等 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 实用教程—结构化程序设计

第 5 章 数组和数据结构基础 .................................................................................................... 141


5.1 选举程序 ........................................................................................................................... 141
5.2 改变二维数组 ................................................................................................................... 146
5.3 线性表的插入和删除 ....................................................................................................... 152
5.4 数据的排序 ....................................................................................................................... 164
思考与练习 ................................................................................................................................ 178
第 6 章 过程和自定义数据类型 ................................................................................................ 183
6.1 求组合数 ........................................................................................................................... 183
6.2 计算阶乘和 ....................................................................................................................... 194
6.3 求 2 的 N 次方精确值 ...................................................................................................... 200
6.4 统计学生成绩 ................................................................................................................... 211
6.5 利用递归算法求阶乘 ....................................................................................................... 216
思考与练习 ................................................................................................................................ 223
第 7 章 文件管理 ........................................................................................................................ 225
7.1 文本文件加密器 ............................................................................................................... 225
7.2 “学生档案管理”程序 ................................................................................................... 232
7.3 中文信息加密和解密 ....................................................................................................... 243
7.4 文本文件管理器 ............................................................................................................... 247
思考与练习 ................................................................................................................................ 255
附录 1 应用程序类型的名称和说明 ......................................................................................... 257
附录 2 主菜单中各类菜单命令的作用 ..................................................................................... 258
附录 3 工具箱中基本控件工具的名称和功能 ......................................................................... 264
附录 4 Visual Basic 6.0 试卷 ................................................................................................ 266
附录 5 部分参考答案 ................................................................................................................. 276
结构化程序设计概述
第 1 章

1.1 Visual Basic 6.0 简介和工作环境

1.1.1 中文 Visual Basic 6.0 简介

Visual Basic 语言是 Microsoft(微软)公司在 Basic 语言的基础之上推出的可视化开发工


具,它是在 Windows 操作平台下设计应用程序的一个最简捷的工具,是一种通用的程序设计
语言。
Basic 是 Beginners All-Purpose Symbolit Instruction Code 的缩写,它的中文含义是“初学
者通用符号指令代码”。Basic 语言是一种在计算机技术发展历史上应用得最为广泛的语言,
它具有面向普通使用者和易学易用的优点。Visual 的英文原意是“可视的” ,在这里是指开发
图形用户界面(Gul)的方法,即“可视化程序设计” 。可视化是指一般不需要编写大量的程
序代码,就可以设计出界面元素的外观和位置。所以 Visual Basic 是基于 Basic 的可视化的程
序设计语言。
1.Visual Basic 语言的发展
Microsoft 公司于 1991 年推出 Visual Basic 1.0 以后,不断修改 Visual Basic 的一些缺陷,
同时增加了许多功能。从 1992 年至今,陆续推出了 Visual Basic 2.0(简称 VB2.0)、VB3.0、
VB4.0、VB5.0、VB 6.0 和 VB.NET 多个版本。其中,VB 5.0 以前的版本主要应用于 DOS 和
Windows 3.X 环境中,VB 5.0 以后的版本只能运行在 Windows 9X、Windows 2000、Windows
XP 或 Windows NT 等操作系统下,是一个 32 位应用程序的开发工具。目前,中文 Visual Basic
6.0(简称 VB 6.0)是我国使用最多的一个版本。
2.Visual Basic 6.0 的版本
Visual Basic 6.0 包括 3 个版本,分别为学习版(Learning)、专业版(Professional)和企
业版(Enterprise)。
① 学习版是 Visual Basic 6.0 的基础版本,包括所有的内部控件,适用于初学者。
② 专业版主要面向计算机专业开发人员,除了具有学习版的全部功能外,还包括
ActiveX 和 Internet 控件开发工具之类的高级特性。
③ 企业版是 Visual Basic 6.0 的最高版本,除具有专业版的全部功能外,还包括一些特
殊的工具。
这些版本是在相同的基础上建立起来的,以满足不同层次的用户需要。对大多数用
户来说,专业版可以满足需要。本书使用的是中文 Visual Basic 6.0 企业版,但介绍的内
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.1.2 中文 Visual Basic 6.0 的工作环境

单击 Windows 的“开始”→“所有程序”→“Microsoft Visual Basic 6.0 中文版”→“Microsoft


Visual Basic 6.0 中文版”菜单命令,即可启动中文 Visual Basic 6.0。此时会调出“新建工程”
第1章 结构化程序设计概述 3

对话框的“新建”选项卡,如图 1-1-1 所示。在该


选项卡中给出了要选择建立的项目类型,选择不
同的项目,可以确定使用 Visual Basic 6.0 开发的
应用程序的类型。
在“新建工程”对话框中,选择“标准.EXE”
项目类型,再单击“打开”按钮,即可调出中文
Visual Basic 6.0 的工作环境窗口,如图 1-1-2 所示。
中文 Visual Basic 6.0 的工作环境也叫开发环境或
IDE,它由标题栏、菜单栏、标准工具栏(也叫工
具栏)、工具箱(也叫控件箱)、窗体、工程资源
管理器、“属性”窗口、代码窗口(该窗口在图 1-1-2
中不可见)和“窗体布局”窗口等组成。 图 1-1-1 “新建工程”对话框

图 1-1-2 Visual Basic 6.0 的工作环境窗口

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+E

打开工程 用于打开已有的工程文件,快捷键为 Ctrl+O

保存工程 用于保存当前的工程文件,快捷键为 Ctrl+S

剪切 将选中的对象剪切到剪贴板中,快捷键为 Ctrl+X

复制 将选中的对象复制到剪贴板中,快捷键为 Ctrl+C

粘贴 将剪贴板中的内容粘贴到当前位置处,快捷键为 Ctrl+V

它在“代码”窗口打开时才有效,单击它可调出“查找”对话框,利用该对
查找
话框可查找字符,其快捷键为 Ctrl+F

撤消 撤消刚刚完成的操作,快捷键为 Ctrl+Z

重复 重新进行刚刚被撤消的操作

启动 开始运行当前的工程,快捷键为 F5

中断 暂时中断当前工程的运行,快捷键为 Ctrl+Break

结束 结束当前工程的运行

工程资源管理器 打开“工程资源管理器”窗口,快捷键为 Ctrl+R


第1章 结构化程序设计概述 5

续表
图 标 名 称 作 用

属性窗口 打开“属性”窗口,快捷键为 F4

窗体布局窗口 打开“窗口布局”窗口

对象浏览器 打开“对象浏览器”对话框,快捷键为 F2

工具箱 打开“工具箱”窗口

数据视图窗口 打开“数据视图”窗口

Visual Component Manager 打开“Visual Component Manager”窗口(可视化部件管理器)

名称为数字显示区,用来显示当前对象的位置与大小,左边的数字是对象的
坐标位置(窗体工作区左上角的坐标为(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-1-4 所示,单击该菜单中的“隐


藏”菜单命令,可以将工具箱隐藏。单击“视图”→“工具箱”菜单命令,可调出隐藏的工
具箱。
5.工程资源管理器
应用程序建立在工程的基础之上,一个工程是各种类型文件的集合,它包括工程文件
(Vbp)、窗体文件(Frm)、标准模块文件(Bas)、类模块文件(Cls)、资源文件(Res)和包
含 ActiveX 的文件(ocx)等。Visual Basic 为了对这些工程资源进行有效的管理,提供了工
程资源管理器。单击“视图”→“工程资源管理器”菜单命令,即可调出“工程资源管理器”
窗口,如图 1-1-5 所示。

图 1-1-4 工具箱的快捷菜单 图 1-1-5 “工程资源管理器”窗口

(1)工程文件:它存储了与该工程有关的所有文件和对象的清单,这些文件和对象自动
链接到工程文件上,每次保存工程时,其相关文件信息也随之更新。当然,某个工程下的对
象和文件也可供其他工程共享使用。在工程的所有对象和文件被汇集在一起并完成编码以后,
就可以编译工程,生成可执行文件。
(2)窗体文件:它存储了窗体上使用的所有控件对象、对象的属性、对象相应的事件过
程及程序代码。一个应用程序至少包含一个窗体文件。
(3)标准模块文件:它存储了所有模块级变量和用户自定义的通用过程。通用过程是指
可以被应用程序各处调用的过程。
(4)类模块文件:用来建立用户自己的对象。类模块包含用户对象的属性及方法,但不
包含事件代码。
工程资源管理器是以树型结构图的方式对资源进行管理,类似于 Windows 资源管理器。
工程资源管理器的标题栏中显示的是工程的名称,标题栏下面的 3 个按钮,从左到右分别是
“查看代码”按钮、“查看对象”按钮和“切换文件夹”按钮。单击“查看代码”按钮可调出
“代码”窗口,用来显示和编辑代码;单击“查看对象”按钮可切换到模块的对象窗口;单击
“切换文件夹”按钮可决定工程中的列表项是否以目录的形式显示。
6.“属性”窗口
“属性”窗口用于设置和描述对象属性,如图 1-1-6 所示。在“属性”窗口中,标题栏内
显示的是当前对象的名称。标题栏下边是“对象”下拉列表框,用户可以在其中选择所需的
对象名称,“属性”窗口会随着选择对象的不同而变化。“对象”下拉列表框的下面是两个排
序选项卡,用来切换“属性”窗口的显示方式。在“属性”列表框中,列出了对象的属性名
称(左边)和属性值(右边),用户可以通过改变右边的取值来改变对象属性值。最下边是属
第1章 结构化程序设计概述 7

性含义提示信息显示框,如果对属性不熟悉,可以参考属性含义提示信息显示框内显示的属
性含义解释。
“属性”窗口有两种显示方式,一种是按照字母排序,各属性名称按照字母的先后顺序
排列显示;另一种是按照分类排序,即按照“外观”、“位置” 、“行为”等分类对各属性进行
排序显示。
打开“属性”窗口的方法通常有以下 3 种:
① 单击“视图”→“属性窗口”菜单命令;
② 单击标准工具栏中的“属性窗口”按钮 ;
③ 将鼠标指针移到相应的对象上,单击鼠标右键,调出它的快捷菜单,然后单击该快
捷菜单中的“属性窗口”菜单命令。
7.“窗体布局”窗口
“窗体布局”窗口的外观如图 1-1-7 所示,它用于设计应用程序运行时各个窗体在屏幕上
的位置。在“窗体布局”窗口中有一个计算机屏幕,屏幕中有一个窗体 Form1。用鼠标将 Form1
拖曳到适合的位置,程序运行后,Forml 将出现在屏幕中对应“窗体布局”窗口的位置。

图 1-1-6 “属性”窗口 图 1-1-7 “窗体布局”窗口

单击“视图”→“窗口布局”菜单命令可调出“窗体布局”窗口。
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-1-10 窗体快捷菜单 图 1-1-11 “代码”窗口快捷菜单


第1章 结构化程序设计概述 9

1.2 第 1 个简单的 Visual Basic 程序

本节介绍如何使用中文 Visual Basic 的集成开发环境来制作一个简单的 Visual Basic 程


序。通过本实例的学习,可以初步掌握设计界面、设置对象属性和编写程序代码的方法;掌
握代码编辑器的组成和基本使用方法,以及了解如何获得相关的帮助;掌握存储程序、运行
程序、创建安装程序和应用安装程序的方法。

1.2.1 代码编辑器

Visual Basic 的代码编辑器就是“代码”窗口(见图 1-1-9)


,它是用来进行程序设计的窗
口,可以在其中的程序编辑区内显示和编辑程序代码。
1.代码编辑器的组成
(1)“对象”下拉列表框:用来选择不同的对象名称,选择对象名称后,即可自动在程
序编辑区内产生一对过程头语句和过程尾语句,过程头语句中的事件名称是该对象的默认
事件。
(2)“过程”下拉列表框:用来选择不同的事件过程名称(也叫事件名称),还可以选择
用户自定义过程名称。只有在“对象”下拉列表框中选择了对象名称后,“过程”下拉列表框
内才会有事件名称。
(3)程序编辑区:用户可以在一对过程头语句和过程尾语句之间输入程序代码。在程序
编辑区中,可以用鼠标拖曳选中代码,拖曳鼠标可以将选中的代码移动。在选中的代码上,
单击鼠标右键,会弹出它的快捷菜单(见图 1-1-11),利用该菜单可以复制、剪切和粘贴选中
的代码。将鼠标指针移到程序编辑区内,单击鼠标右键,调出它的快捷菜单,单击该快捷菜
单中的“属性/方法列表”菜单命令,可以调出“属性/方法”列表框,供用户选择其中的属
性、方法和常量名称。
用户可以打开多个代码编辑器,查看不同窗体中的代码,并可在各个代码编辑器的程序
编辑区之间复制代码。注意:在程序运行当中,不可以修改程序编辑区内的代码。
(4)“过程查看”按钮 :单击该按钮后,在程序编辑区内,只显示“对象”下拉列表
框中选中对象的过程程序代码。
(5)“全模块查看”按钮 :单击该按钮后,在程序编辑区内,显示相应窗体内所有对
象的过程程序代码。
2.调出代码编辑器的方法
① 单击“视图”→“代码窗口”菜单命令。
② 单击选中一个对象,单击鼠标右键,弹出它的快捷菜单,再单击该菜单中的“查
看代码”菜单命令。在调出代码编辑器的同时,也创建了该对象的一对过程头和过程尾
语句。
③ 双击某一个对象,在调出代码编辑器的同时,也创建了该对象的一对过程头和过程
尾语句。
3.自动显示对象的属性和方法
当用户在程序编辑区内输入一个对象的名称并按下小数点“.”键后,系统会自动弹出包
10 中文 Visual Basic 6.0 实用教程—结构化程序设计

括该对象可用于程序的全部属性和方法的列表,如图 1-2-1 所示。用户可以从该列表框中选择


需要的属性或方法名称,双击该属性或方法名称,即可将选中的属性或方法名称加入到程序当
中。在该列表中,图标为 的表示是属性;图标为 的表示是方法,如 Caption 是属性,Drag
是方法。

图 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

图 1-2-3 MSDN 起始页

另外,更常用的方法是在编程时通过联机帮助来使用 MSDN。要获取控件的联机帮助,
可在窗体中选取相应控件,再按 F1 键;要获取方法、函数或事件的相关帮助,则在“代码”
窗口中选中方法、函数或事件的关键字(见图 1-2-4 左图),再按 F1 键。此时,系统会自动
查找并打开相关信息,如图 1-2-4 右图所示。

图 1-2-4 通过联机帮助获取信息

1.2.3 项目实现

该程序运行后的画面如图 1-2-5 左图所示,单击“显示学习 VB 信息”按钮后,窗体内


会增加显示一些文字,同时窗体和按钮的标题文字也会发生变化,如图 1-2-5 右图所示。

图 1-2-5 第 1 个简单的 Visual Basic 程序运行后的两个画面


12 中文 Visual Basic 6.0 实用教程—结构化程序设计

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”,依此类推。此处按钮对象
的名字采用其默认值。

图 1-2-6 在“Form1”窗体中添加按钮 图 1-2-7 Caption 属性设置

“名称”属性的值由一些字符组成,可以修改,字符可以是数字、字母、带下划线的字符
和汉字,但第一个字符必须是字母或汉字,不能有标点符号和空格,最多不能超过 40 个字符。
(4)单击工具箱中的指针按钮 ,再单击窗体。在窗体的“属性”窗口中,可以看到它
的“名称”属性的默认值是“Form1”,窗体的“名称”属性值也可以修改,但不可以有两
个窗体使用相同的名字。窗体对象“名称”属性的默认值是“Form”加一个数字序号,第 1
个窗体“名称”属性的默认值是“Form1”,第 2 个窗体“名称”属性的默认值是“Form2”,
依此类推。此处窗体对象的名字采用其默认值。
3.输入代码程序
(1)将鼠标指针移到窗体内,单击鼠标右键,弹出它的快捷菜单,单击该菜单中的“查
看代码”菜单命令,调出相应的“代码”窗口,如图 1-2-8 所示。
(2)在“代码”窗口内的“对象”下拉列表框中,选择“Form”对象名称,此时的“代
第1章 结构化程序设计概述 13

码”窗口内会自动生成一个空的事件过程,它只有两行代码(过程头代码和过程尾代码),如
图 1-2-9 所示。

图 1-2-8 “代码”窗口之一 图 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 所示。

图 1-2-10 “代码”窗口之三 图 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 的代码程序如图 1-2-12 所示。


在输入“Form1.Caption = "跟我学 VB 程序设计语言"”代码时,当输入到 Form1 后面的
小数点时,会弹出窗体的属性和方法名称列表框,如图 1-2-13 所示。用户可以从该列表框中
选择需要的属性或方法的名称,双击该属性或方法名称(例如:Caption),即可将选中的属
性或方法名称加入到程序当中。

图 1-2-12 实例 1 的代码程序 图 1-2-13 弹出属性名称列表框

1.2.4 项目拓展

1.保存程序
(1)单击“文件”→“保存工程”菜单命令,可调出“文件另存为”对话框,如图 1-2-14
所示。选择文件夹,输入文件名称,单击“保存”按钮,将窗体文件保存(扩展名为.frm),
然后调出“工程另存为”对话框,如图 1-2-15 所示。在“文件名”文本框中输入文件名称,
然后单击“保存”按钮,即可将工程文件(扩展名为.vbp)保存。

图 1-2-14 “文件另存为”对话框 图 1-2-15 “工程另存为”对话框

如果计算机已安装了 SourceSafe 软件,则会调出一个“Source Code Control”提示框,


如图 1-2-16 所示,提示用户是否将工程加入 SourceSafe。单击“No”按钮,即可完成保存文
件的任务。

图 1-2-16 “Source Code Control”提示框


第1章 结构化程序设计概述 15

(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 以内的偶数和

本节介绍如何使用中文 Visual Basic 的集成开发环境来制作第二个简单的 Visual Basic 程


序。通过本实例的学习,可以进一步掌握设计界面、设置对象属性和编写程序代码的方法,
了解什么是结构化程序设计,什么是事件驱动程序设计,什么是面向对象程序设计。

1.3.1 什么是结构化程序设计

1965 年 E.W.Dijkstra 首先提出结构化程序设计的概念。什么是结构化程序设计呢?目前,


一种比较流行的说法是:结构化程序设计是单入口单出口的结构,采用自顶向下、逐步求精、
逐步细化的设计方法。Visual Basic 采用了事件驱动程序设计方法,通过事件动作调用相对划
分得比较小的过程子程序。对于具体的过程本身,仍然要使用结构化程序设计方法,用控制
结构来控制程序执行的流向。
一个结构化程序应当具有以下特点:
① 只有一个入口;
② 只有一个出口;
③ 没有死语句(永远执行不到的语句),每一条语句都至少应当有一条从入口到出口的
路径通过它;
④ 没有死循环(无限制的循环)。
1966 年,博姆(Bohm)和雅可比尾(Jacopini)两位学者提出了只用 3 种基本的结构就
能实现任何单入口单出口的结构,这 3 种基本的结构就是“顺序结构” 、“选择结构”和“循
环结构”。这 3 种基本结构都具有只有一个入口和一个出口的特点,不会出现死循环。经过实
践证明,任何一个单入口和单出口的程序结构,都可以认为是这 3 种结构中的几种结构相互
结合的整体。
1.顺序结构
顺序结构是一种线性结构,也是程序设计中最简单、最常用的基本结构。它是按照顺序
完成一系列操作或事物。在日常生活中有许多符合顺序结构的事情,例如公司老总给某个职
工下达一天的任务:先打扫办公室,再到传达室取文件,再采购一台计算机,再发送一封快
件,最后回到公司向公司部门主管汇报一天的工作结果。
在程序设计中,顺序结构程序是把计算机要执行的各种处理命令依次排列起来。事件发
生后,便从左至右、自顶向下地顺序执行这些语句(一个语句行中,从左至右顺序执行各条
语句),直至执行完所有语句行的语句或执行至 End 语句为止。例如,计算 2+4+6+8+10 等于
多少。对于这个问题可以先计算 2+4=6,再计算 6+6=12,再计算 12+8=20,最后计算 20+10=30。
如果用计算机语言将上述过程从开始到最后一一表述出来,就是一个完整的顺序结构程序。
在 1.2 小节中,两个事件过程中的程序就是顺序结构程序。
2.选择结构
选择结构是一种常用的主要基本结构,是计算机科学用来描述自然界和社会生活中分支
现象的重要手段。在实际工作中,常常需要根据某个条件是否成立,来决定下一步应做什么
工作。
第1章 结构化程序设计概述 17

选择结构的事件发生后,会出现两种或多种不同的结果,最终是一种什么样的结果,要
根据不同的条件是否成立来决定。例如,公司老总给某个职工下达一天的任务:先打扫办公
室,再到传达室取文件,再看是否下雨,如果不下雨,则采购一台计算机;如果下雨,则在
办公室整理材料;最后都要向公司部门主管汇报一天的工作结果。
在程序设计中,同样存在这种情况。在这种情况下,程序不再按照顺序来执行各语句行
的语句,而是根据给定的条件来决定选取哪条路径,执行哪些语句。选择结构的特点是:根
据所给定选择条件是否为真(即条件成立),而决定从各实际可能的不同操作分支中,选择
执行某一分支的相应操作。例如,对于计算机程序自动依次产生的正整数 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 的工作环境中。

图 1-3-1 “打包和展开向导”对话框 图 1-3-2 “外接程序管理器”对话框

重新启动 Visual Basic 6.0 的工作环境,打开要打包的工程文件。单击“外接程序”→“打


包和展开向导”菜单命令,调出“打包和展开向导”对话框,如图 1-3-1 所示(没有“浏览”
按钮)。在该对话框的“选择工程”文本框中已有了要打包的工程文件的路径和文件名。
(2)
“打包和展开向导”对话框中有“打包” 、“展开”和“管理脚本”3 个功能按钮。单
击“展开”按钮,可以将安装程序包分发出去。单击“管理脚本”按钮,可以对“包装脚本”
和“展开脚本”进行管理。
(3)单击“打包和展开向导”对话框中“打包”按钮,开始创建主安装程序。如果应用
程序没有生成相应的可执行文件,则向导会指导用户生成应用程序的可执行文件;如果已经
编译并生成了可执行文件,则向导会跳过这一步。然后,向导创建一个名为 Setup.exe 的可执
行文件,并调出“打包和展开向导-打包脚本”对话框。
(4)单击“下一步”按钮后,调出“打包和展开向导 - 包类型”对话框,如图 1-3-3
所示。利用该对话框可以选择生成的包类型,它有两种选择:“标准安装包”和“相关
文件”。
(5)在“包类型”列表中,选择“标准安装包”选项。单击“下一步”按钮,调出“打
包和展开向导 - 打包文件夹”对话框,如图 1-3-4 所示。

图 1-3-3 “打包和展开向导 - 包类型”对话框 图 1-3-4 “打包和展开向导 - 打包文件夹”对话框


第1章 结构化程序设计概述 19

(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 项目实现

该程序运行后的画面如图 1-3-7 左图所示,单击“求 10 以内的偶数和”按钮后,窗体内


会显示 10 以内的偶数和,如图 1-3-7 右图所示。该程序的制作过程如下。
1.设计程序的界面和对象的属性
(1)用鼠标拖曳调整窗体的大小。单击工具箱中的 Pointer(指针)按钮 ,单击工具箱
20 中文 Visual Basic 6.0 实用教程—结构化程序设计

中的 CommandButton 按钮 ,然后在“Form1”窗体中拖曳鼠标,制作一个按钮。
(2)单击选中“Command1”按钮,在其“属性”窗口中,设置 Caption 属性值为“求
10 以内的偶数和”,“名称”属性采用默认值“Command1”。
(3)单击工具箱中的指针按钮 ,再单击窗体。在窗体的“属性”窗口中,设置“名称”
属性的值采用默认值“Form1”,Caption 属性值为“求 10 以内的偶数和”。此时的窗体如
图 1-3-8 所示。

图 1-3-7 “求 10 以内的偶数和”程序运行后的显示效果 图 1-3-8 在“Form1”窗体

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 选 择 窗 体

1.4.1 Visual Basic 文件类型

Visual Basic 的应用程序主要由工程文件(扩展名为.vbp)、窗体文件(.frm)、窗体的二


进制数据文件(.frx)、标准模块文件(.bas)和类模块文件(.cls)等几种类型的文件组成。
现分别简介如下。
1.工程文件
工程文件包含组成应用程序的所有窗体文件(.frm)、模块文件(.bas)和其他文件的信
息,也包含环境设置选项方面的信息。
单击“文件”→“打开工程”菜单命令,调出“打开工程”对话框,利用该对话框可以
打开一个现存的工程文件。单击“文件”→“保存工程”菜单命令,可以保存工程。
2.窗体文件
窗体文件用来存放几个窗体和控件的描述和属性设置,也包括窗体级的常数、变量、外
部过程声明、过程声明和过程代码等。如果程序中没有扩展名为.frm 的窗体文件,则表示没
第1章 结构化程序设计概述 23

有用户界面。
3.窗体的二进制数据文件
窗体的二进制数据文件含有窗体内控件的二进制属性数据。这些文件是在创建窗体时自
动产生的。
4.标准模块文件
标准模块文件用于存放在几个窗体内都需要使用的公共代码,包含常数、类型、变量声
明、过程声明和过程代码。
单击“工程”→“添加模块”菜单命令,或单击标准工具栏内按钮 的黑色箭头按钮,
调出它的菜单,单击该菜单中的“添加模块”菜单命令,调出如图 1-4-1 所示的对话框。单
击选择“新建”选项卡,单击“打开”按钮,即可调出“工程 1-Module2(Code)”窗口,如
图 1-4-2 所示。利用该窗口可以创建标准模块文件。

图 1-4-1 “添加模块”对话框 图 1-4-2 “工程 1-Module2(Code)


”代码窗口

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 实用教程—结构化程序设计

④ “帮助文件名”文本框:用来输入与工程相关的 Help 文件名称。


⑤ “工程帮助上下文标识符”文本框:用来输入上下文标识符,它是在“对象浏览器”
中,当选定“?”按钮时调用的“帮助”主题的上下文标识符。
⑥ “工程描述”文本框:用来输入工程的外部名称,显示在“引用”和“对象浏览器”
对话框内。
2.添加工程
在已建的工程环境中,通过添加新的或现有的工程,可以构成工程组。当装入多个工程
时,工程资源管理器窗口的标题名称会就变为“工程组” 。
(1)添加新的工程:单击“文件”→“添加工程”菜单命令,调出“添加工程”对话框,
选中“新建”选项卡,单击“标准.EXE”选项,单击“打开”按钮,即可在工程资源管理器
窗口(即“工程 - 工程 1”窗口)内添加一个工程。此时的“工程-工程 1”窗口标题变为“工
程组 - 组 1”
,如图 1-4-4 所示。另外,单击标准工具栏内的“添加工程”按钮 ,可以直接
在“工程 - 工程 1”窗口内添加一个工程。

图 1-4-4 工程资源管理器窗口(即“工程组 - 组 1”窗口)

(2)添加现有工程:单击“文件”→“添加工程”菜单命令,调出“添加工程”对话框,
选中“现存”选项卡,单击选中现有的工程文件,单击“打开”按钮,即可在“工程 - 工程
1”窗口内添加一个现有的工程。注意:打开的工程名称不可以与已有的工程名称相同。
3.在工程中添加文件
(1)在工程中添加窗体:单击“文件”→“工程窗体”菜单命令,调出“添加窗体”对
话框,选中“新建”选项卡,单击选中“窗体”选项,单击“打开”按钮,即可在工程资源
管理器窗口当前工程下添加一个窗体,如图 1-4-4 所示。另外,单击标准工具栏内的“添加
窗体”按钮 ,可以直接在工程资源管理器窗口内添加一个窗体。
(2)在工程中添加其他文件:可以在工程中添加模块、属性页和用户控件等文件,通过
单击选择“工程”菜单的各种添加命令,即可在工程中添加文件。

1.4.3 项目实现

“选择窗体”程序运行后的画面如图 1-4-5 所示。单击“窗体 1”按钮,即可调出实例 1


程序,并运行该程序,单击该程序右上角的“关闭”按钮 ,即可回到图 1-4-5 所示的画
面;单击“窗体 2”按钮,即可调出实例 2 程序,并运行该程序;单击“窗体 3”按钮,即
可调出实例 3 程序,并运行该程序;单击“退出”按钮,即可退出程序的运行。程序设计
第1章 结构化程序设计概述 25

方法如下。
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 所示。更改窗体文件名称的目的是,在一个工程文件中不
可以有相同名称的窗体文件。

图 1-4-5 “选择实例”程序运行后的画面 图 1-4-6 工程资源管理器 图 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”。

图 1-4-9 加载新窗体后的工程资源管理器 图 1-4-10 修改窗体后的工程资源管理器

(6)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。单击该对话框
的“现存”选项卡,选择实例 1 中的窗体文件“Form1.frm”,单击“打开”按钮,即可将该
窗体文件打开,并加载到当前的工程中。此时的“工程-工程 1”工程资源管理器如图 1-4-11
所示。
(7)单击“文件”→“保存工程”菜单命令,将当前工程文件保存到“实例 2-选择窗体”
目录中。至此已将 3 个实例的窗体文件加载到同一个工程文件当中。
(8)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。单击“打开”
按钮,即可在当前工程中创建一个新的窗体,窗体的名称自动设置为“Form4”。此时的工程
资源管理器如图 1-4-12 所示。

图 1-4-11 加载新窗体后的工程资源管理器 图 1-4-12 程序的工程资源管理器

(9)单击“工程”→“工程 1 属性”菜单命令,调出“工程 1 - 工程属性”对话框,再在


“启动对象”下拉列表框中选择“Form4”选项,然后单击“确定”按钮。以后,单击标准工
具栏内的“启动”按钮或者按 F5 键,即可运行新创建的“Form4”窗体程序。采用同样的方
法还可以运行其他窗体程序,以检查各个窗体的程序是否能够正常运行。
(10)单击“文件”→“工程另存为”菜单命令,调出“工程另存为”对话框。将修改
后的工程保存为“工程 1.vbp”工程文件。
2.设置对象的属性
(1)参看图 1-4-5,创建 6 个对象:1 个窗体对象,名称为“Form4”,BackColor 属性设
置为黄色;1 个标签对象,名称为“Label1”;4 个按钮对象,名字分别为“Command1”、
“Command2”、“Command3”和“Command4”。4 个按钮的 BackColor 属性设置为灰色,字
体属性设置为宋体,大小为小四号,字形为粗体。
(2)4 个按钮对象的 Caption 属性分别为(从左到右、从上到下) “窗体 1”、“窗体 2”、
“窗体 3”和“退出”。4 个按钮的其他属性采用默认值。
(3)“Form4”窗体对象的 Caption 属性设置为“选择窗体”,BackColor 属性为灰色,
第1章 结构化程序设计概述 27

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)中文 Visual Basic 6.0 的菜单栏主要包括________、________、________、________、


________、________、________、________、________、________、________、________和
________。
(3)应用程序建立在________的基础之上,一个工程是各种________的集合。
(4)工程包括有如下文件:________文件,该文件的扩展名是________;________文件,
该文件的扩展名是________;________文件,该文件的扩展名是________;________文件,
该文件的扩展名是________;________文件,该文件的扩展名是________。以及 ActiveX 的
文件等,该文件的扩展名是________。
(5)Visual Basic 为了对这些工程资源进行有效的管理,提供了________。单击________
→ ________菜单命令,即可调出“工程资源管理器”窗口。
(6)代码编辑器由________、________、________、________和________组成。
(7)调出代码编辑器的方法有________、________和________3 种。
(8)Visual Basic 应用程序的基本单元就是________。对象是________和________的集合。
(9)“属性”窗口有两种显示方式,一种是按照________排序,另外一种是按照________
排序。
(10)对象属性的设置可以有________和________两种方法。
(11)方法是________操作。在 Visual Basic 中,方法是________。
(12)事件可分为________事件和________事件等。
(13)通常的程序设计方法有________、________和________3 种。结构化程序设计中的
3 种基本结构是________、________和________。
(14)安装好 MSDN 后,单击________ → ________ → ________ → ________菜单命
令,即可启动 MSDN Library Visual Studio 6.0。
(15)从顺序结构与选择结构的执行过程来看,计算机在执行程序时,顺序结构中所有
书写出来的语句都________,选择结构中书写出来的分支语句________,并且一般情况下均
有________的特性。
(16)程序的循环结构是指:在编写程序让计算机工作时,当在某个条件成立时(或不
成立时),________循环体中的某段程序或某条语句,直到条件________才停止这种重复工作。
2.回答关于基本操作的问题
(1)中文 Visual Basic 的工作环境主要由哪几部分组成?
(2)如何在窗体中创建控件对象?
(3)如何在“代码”窗口中自动地显示出对象的属性和方法?
(4)如何在“代码”窗口中自动地显示语句或函数的语法帮助信息?
(5)如何运行程序和停止程序的运行?
(6)如何生成 Visual Basic 程序的可执行文件(扩展名为.exe 的文件)?
(7)如何打开“属性”窗口,打开“属性”窗口有几种方法?简述这几种方法。
(8)如何打开“窗体布局”窗口,如何打开“代码”窗口,如何打开工程资源管理器?
(9)如何使用“属性”窗口修改对象的属性值,如何在程序中修改对象的属性值?
(10)如何保存一个编写好的程序,如何打开一个 Visual Basic 程序文件?
(11)如何创建一个安装程序?
30 中文 Visual Basic 6.0 实用教程—结构化程序设计

(12)如何安装 MSDN?如何使用 Visual Basic 的帮助?


3.编写一个 Visual Basic 程序,程序运行后,单击窗体中的“显示 1”按钮,即可在窗
体中显示“迎接 2005 年的抗日战争胜利 60 周年!”;单击窗体中的“显示 2”按钮,即可在
窗体中显示“迎接 2008 年北京奥运会! ”。
4.编写一个 Visual Basic 程序,要求窗体内有 3 个按钮分别为“按钮 1”、
“按钮 2”和
“按钮 3”。程序运行后,用户单击不同的按钮,窗体中会显示出不同的内容,窗体和按钮的
标题也会发生相应的变化。
5.编写一个 Visual Basic 程序,计算 100 以内的偶数和。
6.编写一个 Visual Basic 程序,计算 100 以内的奇数和。
7.编写一个 Visual Basic 程序,计算 500 以内的所有自然数的和。
8.编写一个 Visual Basic 程序,计算 10!。
中文 Visual Basic 6.0 编程基础
第 2

2.1 输 入 密 码

2.1.1 数据的类型

数据是描述客观事物的数、字符和所有能输入到计算机并被计算机程序处理的符号集
合。在中文 Visual Basic 6.0 中,数据是指常量、变量、字符串和数组等。每一个数据都属于
一种特定的数据类型,不同的数据类型所占的存储空间不一样,表示和处理的方法也不一样,
这就需要进行数据类型的说明或定义。
Visual Basic 的数据类型可分为标准数据类型和用户自定义数据类型两大类。标准数据类型
又称为基本数据类型,它是由 Visual Basic 直接提供给用户的数据类型,用户不用定义就可以直
接使用;用户自定义数据类型是由用户在程序中以标准数据类型为基础,并按照一定的语法规则
创建的数据类型,它必须先定义,然后才能在程序中使用。标准数据类型如表 2-1-1 所示。
表 2-1-1 Visual Basic 的标准数据类型
数 据 类 型 关 键 字 类 型 符 字 节 数 范 围

字节型 Byte 无 1 0~255

布尔型 Boolean 无 2 True 与 False

整型 Integer % 2 −32 768 到 32 767,小数部分四舍五入

−2 147 463 648 到 2 147 463 647,


长整型 Long & 4
小数部分四舍五入

负数:−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

日期型 Date 无 8 100.1.1~9999.12.31

变长字符型 String $ 字符串长度 0~约 20 亿字节,1 字节/字符

定长字符型 String*size $ 字符串长度 size 1~65 535 字节(64KB)

对象型 Object 无 4 可供任何对象引用

变体型(数值) Variant 无 16 任何数值,最大可达 Double 的范围

变体型(字符) Variant 无 字符串长 与变长度字符串有相同的范围


32 中文 Visual Basic 6.0 实用教程—结构化程序设计

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

数部分最多有 4 位,可在数据后面加尾符“@”来表示货币类型数据,例如 689.59@。


2.字符串型数据
字符串是由双引号括起来的一串基本字符集中的字符(不含双引号、回车符和换行符)
序列。字符串中可以包含汉字,一个汉字或一个英文字母都是一个字符,例如“BASIC 6.0” 、
“中文”。如果一个字符串不包含任何字符,则称该字符串为空字符串,简称空串。默认的初
值为空串。在 Visual Basic 中,字符串型数据可分为变长字符串和定长字符串两种。
(1)变长字符串型:它的长度是可以变化的,在计算机中为变长字符串分配的存储空间
也是随着字符串的实际长度的变化而变化的,变长字符串最多可容纳大约 20 亿个字符,一般
所用的字符串数据大多属于这一类。
(2)定长字符串:它的长度是固定不变的,在计算机中为定长字符串分配的存储空间也
是固定不变的,而不管字符串的实际长度是多少。定长字符串最多可容纳 64K 个字符。例如:
Dim SN1 As String '声明变长字符串型变量 SN1
Dim SN2 As String*36 '声明定长(36 个字符)字符串变量 SN2

对上例声明的定长字符串变量 SN2,若赋予的字符少于 36,则右部补空格;若赋予的字


符超过 36 个,则多余部分截去。
3.日期型数据
日期型数据除了可以表示日期之外,还可以表示时间。表示的日期范围为 100 年 1 月 1
日到 9999 年 12 月 31 日,时间范围为 0:00:00 到 23:59:59。时间默认初值为 00:00:00。日期
型数据的表示方法有两种,一种是一般表示法,另一种是序号表示法。
(1)一般表示法:它是用一对“#”号将日期和时间前后括起来的表示方法。例如:#Jan
32004#、#26 March#、#2004-8-11 10:32:50Am#、#6/10/98 12:11:45PM#等。在日期类型的数
据中,不论将年、月、日按照何种排列顺序输入,日期之间的分隔符用的是空格还是“-”号,
月份用数字还是用英文单词表示,系统会自动将其转换成由数字表示的“月/日/年”格式。
如果日期型数据不包括时间,则 Visual Basic 会自动将该数据的时间部分设定为午夜 0 点(一
天的开始)。如果日期型数据不包括日期,则 Visual Basic 会自动将该数据的日期部分设定为
公元 1899 年 12 月 30 日。
(2)序号表示法:用来表示日期的序号是双精度实数,Visual Basic 会自动将其解释为日
期和时间。其中,序号的整数部分表示日期,小数部分表示时间。午夜为 0,正午为 0.5。
在 Visual Basic 中,用于计算日期的基准日期为公元 1899 年 12 月 31 日,负数表示在此
之前的日期,正数表示在此之后的日期。例如,1.5 表示 1899 年 12 月 31 日中午 12 点,−5.3
表示 1899 年 12 月 25 日上午 7 点 12 分。
可以对日期型数据进行运算。通过加减一个整数来增加或减少天数;通过加减一个分数
或小数来增加或减少时间。例如,加 15 就是加 15 天,而减掉 1/12 就是减去 2 小时。
4.逻辑型数据和对象型数据
(1)逻辑类型数据:它只有真(True、Yes 或 On)和假(False、No、Off)两个值,分
别表示成立和不成立,其缺省值为 False。逻辑类型数据常作为程序的转向条件,以控制程序
的流程。当布尔型数据转换成整型数据时,True 转换为−1,False 转换为 0;当将其他类型数
据转换成逻辑数据时,非 0 数转换为 True,0 转换为 False。默认的初值是 False。
(2)对象型数据:它通过 4 个字节地址来存储,该地址指向应用程序中的一个对象。可
34 中文 Visual Basic 6.0 实用教程—结构化程序设计

以用 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

无效(Null) 1 OLE 自动化对象(OLEAutomation Object) 9

整型(Integer) 2 错误(Error) 10

长整型(Long) 3 布尔型(Boolean) 11

单精度型(Single) 4 变体数组(Variant) 12

双精度型(Double) 5 非 OLE 自动化对象(Non-OLEAutomation Object) 13

货币型(Currency) 6 字节型(Byte) 17

日期型(Date) 7 数组(Array) 8192

6.用户自定义型数据
用户自定义型数据由若干个标准数据类型组成。自定义类型通过 Type 语句来实现。关
于用户自定义数据类型将在以后的章节中详细介绍。

2.1.2 常量

常量是在程序运行过程中,其值保持不变的量,例如数值、字符串等。在 Visual Basic


中,常量可分为一般常量和符号常量两种。
1.一般常量
一般常量就是在程序中,以直接明显的形式给出数据本身的数值。根据常量的数据类型,
一般常量有数值常量、字符常量、逻辑常量和日期常量。
(1)数值常量:它由正号、负号、数字和小数点组成,例如 569、21.86、6.8E-3(单精
度型)、6.8D3(双精度型)等。
(2)字符常量:它由双引号括起来的字符串组成,例如"ABC123"、"123"和"迎接 2008
年奥运"等。
(3)逻辑常量:它由 False(假)和 Ture(真)组成。
第2章 中文 Visual Basic 6.0 编程基础 35

(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 “对象浏览器”窗口

在“工程/库”下拉列表框(左上角第 1 个下拉列表框)中选择 Visual Basic、Visual BasicA、


Visual BasicRUN 或“工程 1”等选项,即选择了相应的对象库,再在“类”列表框中选择组
名称,然后在其右边的“成员”列表框中列出相应的标准符号常量、属性和方法名称。单击
选中一个名称后,在“对象浏览器”窗口底部的文本框中,会显示它的功能说明。
通过使用标准符号常量,不但可以使程序变得易于阅读和编写,同时,标准符号常量值
在 Visual Basic 更高版本中可能还要改变,标准符号常量的使用也可使程序保持兼容性。例
如:窗体对象的 WindowsState 属性可接受的标准符号常量有 VbNormal(正常)、VbMaximized
(极小化)和 VbMaximized(最大化)。
(2)自定义符号常量:它是由程序设计人员按照规定的语法规则在编写程序时命名的。
它必须先定义,然后才能在程序的代码中使用。在定义自定义符号常量时,常量的名称最好
应具有一定的含义,以便于理解和记忆。自定义符号常量的定义语法规则如下。
【格式】[Public|Private] Const 常量名[类型符|As 类型关键字]=表达式
【功能】先计算赋值号右边表达式的值,然后将此值赋给左边的符号常量。
36 中文 Visual Basic 6.0 实用教程—结构化程序设计

【说明】等号(=)右边的表达式可以是数值型、字符串型、布尔型或日期型表达式,甚
至可用先前定义过的常量来定义新常量。但在表达式中不能出现变量和函数运算,也不能出
现用户自定义类型数据。虽然在定义符号常量的表达式中可以出现其他已经定义的符号常量,
但应注意在两个或两个以上的常量之间不能出现循环定义。 用 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

在 Visual Basic 中,符号常量、变量、过程和自定义函数名称都必须遵循上述规则。


2.变量的数据类型
在 Visual Basic 中变量的数据类型有 11 种,它们是 Integer(整型),Long(长整型),Single
(单精度浮点型),Double(双精度浮点型),Currency(货币型),Byte(字节型),String(字
符串型),Boolean(布尔型),Date(日期时间型) ,Object(对象型)和 Variant(变体型)。
变量的数据类型决定变量能够存储哪种数据。
3.变量的声明
通常,必须对变量先进行声明,再使用变量。变量声明就是将变量的名称和数据类型事
先通知给应用程序,也叫做变量定义。在 Visual Basic 中可以使用如下几种方法进行变量的
声明。
(1)隐式声明:隐式声明就是在使用一个变量之前并不专门声明这个变量而直接使用。
例如:PI=3.14、NTl=Int(RND*16)等,即在给 PI 和 NTl 变量赋值的同时,自动声明了变
量 PI 和 NTl,而在赋值前并没有对变量 PI 和 NTl 进行声明。
隐式声明的变量属于变 体 ( Variant) 数 据 类 型 变 量 。 采 用 隐式声明的变量,会在输
入变量名称发生错误时,而使应用程序运行结果产生错误,而且这种错误不易被发现,系统
也不会给出错误提示信息。
(2)用 Dim 语句声明变量:用 Dim 语句声明变量的方法如下。
【格式】Dim 变量名 [As 数据类型关键字]
Dim 变量名 [As 数据类型关键字],变量名 [As 数据类型关键字]……
【功能】将变量名指定的变量定义为由类型关键字指明的变量类型。其中:数据类型可
使用表 2-1-2 中所列出的类型关键字或用户自定义的类型名。方括号“[]”内的部分表示可以
缺省。如果缺省“AS 类型关键字”部分,则所创建的变量默认为变体类型。
【说明】
① 一条 Dim 语句可同时声明多个不同类型的变量,但每个变量必须有自己的类型关键
字。例如:
Dim N1 As integer,N2 As singl 该语句声明了整型变量 N1 与单精度型变量 N2。
Dim P1,T1 As Double 该语句声明了变体型变量 P1 与双精度型变量 T1。
② 一条 Dim 语句可以同时声明多个相同类型的变量,但每个变量之间必须用逗号分割。
例如:
Dim N1,N2,N3 As integer 该语句声明了 3 个整型变量。
③ 对于字符串变量,根据其字符串长度是否固定,其声明的方法有两种:
Dim 字符串变量名 AS String
Dim 字符串变量名 AS String*字符数
前一种方法声明的字符串将是不定长的字符串;后一种方法可声明定长的字符串,存放
的最多字符个数由其中的字符数给出。例如:
Dim AB1 AS String*50 定义了一个长度为 50 个字符的字符串变量 AB1。
④ 还可以用 Static、Public、Private 等关键字声明变量,这将在以后介绍。
⑤ 一个变量的有效使用范围称为该变量的作用域。在模块顶部的通用声明段用 Dim 关
键字声明的变量叫模块级变量。模块级变量的作用域是该模块中的所有过程,对该模块中的
38 中文 Visual Basic 6.0 实用教程—结构化程序设计

所有过程都起作用,但对其他模块不起作用。
(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 项目实现

“输入密码”程序运行后的画面如图 2-1-2 所示。单击“请输入密码”按钮后,弹出一个


“请您输入密码”对话框,该对话框的提示信息是“请您输入密码!”和“密码是:” ,输入文
本框中的默认值为 0,如图 2-1-3。在该文本框中输入密码后,单击“确定”按钮,又回到窗
体。根据输入密码是否正确,窗体中会显示相应的提示信息。如果输入“19471107”密码,
则窗体中会显示“密码正确! ”文字,如图 2-1-4 所示。程序的设计方法如下。

图 2-1-2 程序运行结果之一 图 2-1-3 程序运行结果之二 图 2-1-4 程序运行结果之三

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 所示。单击该调色板中的蓝色色块,为标签文字选中红色。

图 2-1-5 “字体”对话框 图 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 个按钮是缺省值

默认按钮 256 在“消息”对话框中第 2 个按钮是缺省值

512 在“消息”对话框中第 3 个按钮是缺省值

0 应用程序暂停运行,直到用户对“消息”对话框做出响应才继续执行下面的程序
等待模式
4096 全部应用程序都被挂起,直到用户对消息框做出响应才执行下面程序

④ 函数值为整型,如表 2-1-4 所示。它告诉程序用户单击了哪一个按钮。如果“消息”


对话框内显示“Cancel”按钮,则按 Esc 键和单击“Cancel”按钮的效果一样。
42 中文 Visual Basic 6.0 实用教程—结构化程序设计

表 2-1-4 消息函数的函数值及其含义
函 数 值 含 义 函 数 值 含 义 函 数 值 含 义 函 数 值 含 义

1 OK(确定) 3 Abort(终止) 5 Ignore(忽略) 7 No(否)

2 Cancel(取消) 4 Retry(重试) 6 Yes(是)

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 表达式

Visual Basic 表达式是用运算符和圆括号将常量、变量和函数按照一定的语法规则连接而


成的有一定意义的式子。一个独立的常量、变量或函数也可以看作一个简单的表达式。根据
表达式中使用的运算符以及表达式的数值类型可以将表达式分为算术表达式、字符串表达式、
关系表达式和逻辑表达式。
第2章 中文 Visual Basic 6.0 编程基础 43

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

【格式】<表达式 1><关系运算符><表达式 2>


【功能】先计算表达式 1 和表达式 2 的值,得出两个相同类型的值,然后再进行关系运
算符所规定的关系运算。如果关系表达式成立,则计算结果为 True,否则为 False。
【说明】
① 表达式 1 和表达式 2 是两个类型相同的表达式,可以是算术表达式,也可以是字符
串表达式,还可以是其他的关系表达式等。
② 对于数值型数据,按其数值的大小进行比较;对于字符串型数据,从左到右依次按
其每个字符的 ASCII 码值的大小进行比较,如果对应字符的 ASCII 码值相同,则继续比较下
一个字符,如此继续,直到遇到第一个不相等的字符为止。
例如:9+2>28-6 的值是 False,"ABD">="ABCD"的值是 True。
③ 所有比较运算符的优先顺序均相同,如要想改变运算的先后顺序,需使用圆
括号括起来。关系表达式的书写规则与算术表达式的书写规则相同。
4.逻辑表达式
(1)逻辑运算符:逻辑运算符是进行逻辑运算所使用的运算符,包括 Not(非)、And(与)
Or(或)、Xor(异或)、Eqv(等价)和 Imp(蕴含)等。
(2)逻辑表达式:用逻辑运算符将两个关系式连接起来的有意义的式子。
【格式】Not<表达式>或<表达式 1> And|Or|Xor| Eqv |Imp <表达式 2>
【功能】先计算表达式的值,计算结果为真(True)或假(False),再将进行逻辑非运算。
计算结果是逻辑数据真(True)或假(False)。
【说明】
① 表达式、表达式 1 和表达式 2 为关系表达式,也可以是另外的逻辑表达式。逻辑表
达式的书写规则与算术表达式的书写规则相同。逻辑运算符及其真值如表 2-2-1 所示,其中
用 A 和 B 代表两个表达式的值。
表 2-2-1 逻辑运算符及其真值表
Not A A And B A Or B A Xor B A Eqv B A Imp B
A B
(取反) (与) (或) (异或) (等价) (蕴含)
True True False True True False True True

True False True False True True False False

False True False False True True False True

False False True False False False True True

② 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 项目实现

程序运行后的画面如图 2-2-2 所示。单击“输入半径”按钮后,弹出一个“输入半径”


对话框,该对话框的提示信息如图 2-2-3 所示。在“输入半径”对话框中的文本框中输入半
径数值(例如:输入 6)后,单击“确定”按钮,又回到窗体。

图 2-2-2 程序运行结果 之一 图 2-2-3 程序运行结果之二

单击“圆周长”按钮,即可在窗体中显示出相应的圆周长,如图 2-2-4 所示;单击“圆


面积”按钮,即可在窗体中显示出相应的圆面积,如图 2-2-5 所示;单击“球体积”按钮,
即可在窗体中显示出相应的球体积。

图 2-2-4 程序运行结果之三 图 2-2-5 程序运行结果之四

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 文 字 特 点

1 窗体 Form1 计算圆周长、面积和球体积 5 号、黑色、粗体

2 标签 Label1 空 三号、蓝色、粗体

3 标签 Label2 空 三号、红色、粗体

4 按钮 Command11 输入半径 5 号、黑色、粗体

5 按钮 Command12 圆周长 5 号、黑色、粗体

6 按钮 Command13 圆面积 5 号、黑色、粗体

7 按钮 Command14 球体积 5 号、黑色、粗体

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-2-6 复合表达式运算的 验证程序 图 2-2-7 程序运行结果

2.3 函 数 运 算

2.3.1 数学函数

1.数学函数列表
数学函数的函数名、函数值类型和函数功能如表 2-3-1 所示。
表 2-3-1 数学函数
第2章 中文 Visual Basic 6.0 编程基础 49

函 数 名 函数值类型 功 能 举 例

Abs(N) 同 N 的类型 求 N 的绝对值 Abs(6.2) = 6.2,Abs(−7) = 7

N>0,其值为 1;N=0,其值为 0; N<0,


Sgn(N) Integer Sgn(+186)=1,Sgn(−186)= −1,Sgn(0)=0
其值为-1

Sqr(N) Double 求 N 的算术平方根,N>=0 Sqr(81)=9,Sqr(400)=20

Exp(N) Double 求自然常量 e 的幂 Exp(2)=7.38905609893065

Log(N) Double 求 N 的自然对数值,N>0 Log(2)=0.693147180559945

Sin(N) Double 求 N 的正弦值 Sin(0)=0

Cos(N) Double 求 N 的余弦值 Cos(0)=1

Tan(N) Double 求 N 的正切值 Tan(0)=0

Atn(N) Double 求 N 的反正切值 Atn(1)=0.785398163397448

Int(N) Integer 求不大于 N 的最大整数 Int(6.9)=6,Int(−6.9)=−7

Fix(N) Integer 将 N 的小数部分截去,求其整数部分 Fix(6.9)=6,Fix(−6.9)=−6

Rnd[(N)] Single 求[0,1]之间的一个随机数,N>=0 Rnd(1)、Rnd

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("")会产生错误

Chr$(N) String 求以 N 为 ASCII 码的字符 Chr(66)="B"

将 N 转换为字符串,如果 N>0,则返回 Str$(−12345)=" −12345"


Str$(N) String
的字符串中包含一个前导空格 Str(12345)=" 12345"
Val("12345abc")=12345
Val(C) Double 将 C 中的数字字符转换成数值型数据
遇到第 1 个非数字的字符时,停止转换

Len(C) Long 求字符串 C 中包含的字符个数 Len("Abab 字符串 4")=8


50 中文 Visual Basic 6.0 实用教程—结构化程序设计

续表
函 数 名 函数值类型 功 能 举 例

将字符串 C 中的小写英文字母转换成大
Ucase$(C) String Ucase("Basic")="BASIC"
写英文字母

将字符串 C 中的大写英文字母转换成小
Lcase$(C) String Ucase("Basic")="basic"
写英文字母
Len(Space(5))=5
Space$(N) String 产生 N 个空格的字符串
注:引号内有 5 个空格

产生 N 个由 C 指定的第 1 个字符组成的 String(5,"BASIC")="BBBBB"


String$(N,C) String
字符串,C 可以是 ASCII 码数 String(5,66)="BBBBB"

Left(C,N) String 从字符串 C 左边截取 N 个字符 Left$("BASIC",3)="BAS”

从字符串 C 的最右边开始,截取 N 个字
Right$(C,N) String Right$("BASIC",3)="SIC”

从字符串 C 中 N1 指定的起始处开始, Mid("BASIC",2,3)="ASI"


Mid$(C,N1 [,N2)) String
截取 N2 个字符 Mid("BASIC",2)="ASIC"

Ltrim$(C) String 删除字符串 C 的前导空格 Ltrim(" BASIC")="BASIC"

Rtrim$(C) String 删除字符串 C 的尾部空格 Ltrim(" BASIC ")=" BASIC"

Trim$(C) String 删除字符串 C 中的前导和尾部空格 Ltrim(" BASIC ")="BASIC"


StrComp("ABC","abc",1)=0
比较字符串 C1 和字符串 C2 的大小,N
StrComp(C1,C2[,N]) Integer StrComp("ABC","abc",0)=−1
是比较类型,取值 0、1 或 2
StrComp("abc ","ABC ",0)=1
InStr(2,"ABCDE","C",4)=3
在字符串 C1 中,从 N1 开始到 N2 位置,
开始找 C2,省略 N1 时从 C1 头开始找, InStr(2, "ABCDEF", "CDE")=3
InStr([N1,]C1,C2[,N2]) Integer
省略 N2 时找到 C1 尾止。找不到时,函 InStr("ABCDEFGH", "CDE")=3
数值为 0
InStr("ABCDEFGH","XY")=0

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

含多少个字符。如果其值为 0,则函数值为空串;如果其值大于或等于字符串 C 中的字符个


数,则函数值为整个字符串。
RightB 函数与 Right 函数功能相近,只不过 RightB 函数求的是字符串的字节数,而不是
字符串中字符的个数。RightB("ABCDEFGHIJK",4)="JK"。
(7)N1 是数值表达式,其值表示开始截取字符的起始位置。如果该数值超过字符串 C
中的字符数,则函数值为空串。N2 是数值表达式,其值表示要截取的字符数。如果省略该参
数,则函数值将包含字符串 C 中从起始位置到字符串末尾的所有字符。
MidB 函数与 Mid 函数功能相近,只不过 MidB 函数求的是字符串的字节数,而不是字
符串中字符的个数。例如,MidB("ABCDEFG",7,6)="DEF"。
(8)因为将一字符串赋值给一定长字符串变量时,如字符串变量的长度大于字符串的长
度,则用空格填充该字符串变量尾部多余的部分,所以在处理定长字符串变量时,删除空格
的 Ltrim 和 Rtrim 函数是非常有用的。
(9)对于字符串比较函数 StrComp(C1,C2[,N]),N 是指定字符串的比较类型。比较类型
可以是 0、1 或 2,若比较类型为 0,则执行二进制比较,此时英文字母区分大小写;若比较
类型为 1,则执行文本比较,此时英文字母不区分大小写;若比较类型为 2,则是执行基于数
据库(Microsoft Access)信息的比较。若省略该参数,则默认比较类型为 0。
当字符串 C1 小于字符串 C2 时,函数值为−1;当字符串 C1 等于字符串 C2 时,函数值
为 0:当字符串 C1 大于字符串 C2 时,函数值为 1。
3.字符串格式化
字符串格式化是将字符串按格式化符号指定的格式进行强制大小写显示等。常用的字符
串格式化符号及使用举例如表 2-3-3 所示。
表 2-3-3 字符串格式化的格式化符号及其作用
符 号 作 用 字符串表达式 格式化符号 显 示 结 果

< 强迫字母以小写显示 Basic "<" basic

> 强迫字母以大写显示 Basic ">" BASIC

@ 实际字符位小于符号位 ABCDEFG "@@@@@@@@@@" ABCDEFG


时,字符前加空格 在“ABCDEFG”前有 3 个空格

& 实际字符位小于符号位 ABCDEFG “&&&&&&&&&&” ABCDEFG


时,字符前不加空格 在“ABCDEFG”前无空格

2.3.3 项目实现

程序运行后的画面如图 2-3-1 所示。在左边的文本框中输入一个数据后,单击“SIN”按


钮后,即可在右边的文本框中显示相应的正弦数值,如图 2-3-2 所示;单击“COS”按钮后,

图 2-3-1 程序运行结果之一 图 2-3-2 程序运行结果之二


52 中文 Visual Basic 6.0 实用教程—结构化程序设计

即可在右边的文本框中显示相应的余弦数值,如图 2-3-3 所示;单击“TAN”按钮后,即可


在右边的文本框中显示相应的正切数值;单击“SQR”按钮后,即可在右边的文本框中显示
相应的平方数值,如图 2-3-4 所示。程序的设计方法如下。

图 2-3-3 程序运行结果之三 图 2-3-4 程序运行结果之四

1.设置对象的属性
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。
(2)单击工具箱中 CommandButton(按钮)按钮 ,然后在窗体中拖曳鼠标,在窗体
内的下边创建 1 个按钮控件对象。然后使用相同的方法,再在窗体内的下边创建 5 个按钮控
件对象。6 个按钮的 Caption 和“名称”属性如表 2-3-4 所示。
表 2-3-4 按钮的属性
属 性 名 称 1 2 3 4 5 6

Caption SIN COS TAN SQR 清除 退出

名称 Command1 Command2 Command3 Command4 QC TC

(3)单击工具箱中的 Label(标签)按钮 ,然后在窗体中拖曳鼠标,在窗体内的上边


创建一个标签对象。单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的标签对象,
在其“属性”窗口内 Caption 属性值文本框中输入“函数运算”文字,保留“名称”文本框
中的默认名称“Label1”,设置文字字体为楷体、三号、加粗,颜色为蓝色。
(4)单击工具箱中的 TextBox(文本框)按钮 ,然后在窗体中拖曳鼠标,在标题的下
边创建一个文本框对象。单击工具箱中的 Pointer(指针)按钮 ,单击选中新创建的文本框
对象,在其“属性”窗口中,删除 Text 属性值文本框中的“Text1”字符,保留“名称”文
本框中的默认名称“Text1”。按照与设置标签文字字体和颜色相同的方法,设置该文本框文
字的字体为宋体、5 号、加粗,颜色为黑色。
(5)按照上述方法,再创建一个相同字体和颜色属性的文本框“Text12”。
2.输入代码程序
在“代码”窗口中输入的代码程序如下。文本框的 Text 属性就是其内的字符和文字。
Const PI As Single = 3.1415926 '定义一个单精度型常量 PI
Rem ********** 计算正弦 **********
Private Sub Command1_Click ( )
Text2.Text = Sin(Val(Text1.Text) * PI / 180) '计算正弦
End Sub
Rem ********** 计算余弦 **********
Private Sub Command2_Click( )
Text2.Text = Cos(Val(Text1.Text) * PI / 180) '计算余弦
End Sub
第2章 中文 Visual Basic 6.0 编程基础 53

Rem ********** 计算正切 **********


Private Sub Command3_Click( )
Text2.Text = Tan(Val(Text1.Text) * PI / 180) '计算正切
End Sub
Rem ********** 计算开方 **********
Private Sub Command4_Click( )
Text2.Text = Sqr(Val(Text1.Text)) '计算开方
End Sub
Rem ********** 清除数据 **********
Private Sub QC_Click( )
Text1.Text = "" '赋给“Text1”文本框 Text 属性空字符串
Text2.Text = "" '赋给“Text2”文本框 Text 属性空字符串
End Sub
Rem ********** 退出程序运行 **********
Private Sub TC_Click( )
End
End Sub

2.3.4 项目拓展

1.转换函数
转换函数可将一种类型的数据转换成另一种类型的数据。常见的转换函数的函数
名和函数值类型如表 2-3-5 所示。
表 2-3-5 转换函数
函 数 名 函数值类型 函 数 名 函数值类型

CBool Boolean(布尔型) CInt Integer(整型)

CByte Byte(字节型) CLng Long(长整型)

CCur Currency(货币型) CSng Single(单精度型)

CDate Date(日期型) CVar Variant(变体型)

CDbl Double(双精度型) CStr String(字符型)

Hex[$](N) 十进制数转换为十六进制数 Oct[$](N) 十进制数转换为八进制数

(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-3-5 判断和转换函数及表达式验证程序 图 2-3-6 程序运行结果

2.4 使用 Windows 的记事本和游戏程序

2.4.1 日期和时间函数

1.日期和时间函数列表
日期和时间函数的函数名、函数值类型和函数功能如表 2-4-1 所示。
表 2-4-1 日期和时间函数
函 数 名 函数值类型 功 能
Now Date 返回当前的系统日期和系统时间
Date[$][( )] Date 返回当前的系统日期
Time"$""( )" Date 返回当前的系统时间

相对 1899 年 12 月 30 日(为 0)返回一个天数值。其中的年、月、日参数为


DateSerial(年,月,日) Integer
数值型表达式
DateValue(C) Integer 相对 1899 年 12 月 30 日(为 0)返回一个天数值,参数 C 为字符型表达式
第2章 中文 Visual Basic 6.0 编程基础 55

续表
函 数 名 函数值类型 功 能

返回日期 D 的年份,D 可以是任何能够表示日期的数值、字符串表达式或它


Year(D) Integer 们的组合。其中,参数为天数时,函数值为相对于 1899 年 12 月 30 日后的指
定天数的年号,其取值在 1753 到 2078 之间
Month(D) Integer 返回日期 D 的月份,函数值为 1 到 12 之间的整数
Day(D) Integer 返回日期 D 的日数,函数值为 1 到 31 之间的整数
WeekDay(D) Integer 返回日期 D 是星期几,函数值与星期的对应关系如表 2-4-2 所示
Hour(T) Integer 返回时间参数中的小时数,函数值为 0 到 23 之间的整数
Minute(T) Integer 返回时间参数中的分钟数,函数值为 0 到 59 之间的整数
Second(T) Integer 返回时间参数中的秒数,函数值为 0 到 59 之间的整数

返回参考日期 D 加上一段时间 T 之后的日期,“时间单位”是一个字符串,


DateAdd(时间单位,时间,D) Date
表示所要加上的时间的单位,其取值及含义如表 2-4-3 所示

返回两个日期 D1 和 D2 之间的间隔时间。如果日期 D1 比 D2 早,则函数值为


DateDiff(时间单位,D1,D2) Long 正数,否则函数值为负数。时间单位,同 DateAdd 函数的时间单位参数,如
表 2-4-3 所示

判断参数是否可转换成日期,参数可以是任何类型的有效表达式。可转化则
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 项目实现

程序运行后的画面如图 2-4-1 所示。单击“使用记事本程序”按钮后,即可调出 Windows


的记事本程序,同时在记事本中打开一个文本文件,如图 2-4-2 所示;单击“使用游戏程序”
按钮后,即可调出相应的扫雷游戏程序 WINMINE.exe。该程序的设计方法如下。

图 2-4-1 程序运行结果之一 图 2-4-2 程序运行结果之二

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

构化程序设计\素材”路径下。将扫雷游戏程序 WINMINE.exe 保存在和该 Visual Basic 程序相同


的文件夹内。
2.输入代码程序
在“代码”窗口中输入的代码程序如下。
Dim N1 As Integer, N2 As Integer
Rem ************ 调用记事本程序和文本文件 ************
Private Sub Command1_Click( )
N1 = Shell("F:\邮电职高\Visual Basic-结构化程序设计\游戏和记事本\NOTEPAD.exe" + " " + "F:\邮电
职高\Visual Basic-结构化程序设计\素材\TEXT3.TXT", 1)
End Sub
Rem **************** 调用游戏程序 ****************
Private Sub Command2_Click( )
N2 = Shell("WINMINE.exe", 1)
End Sub

2.4.4 项目拓展

1.格式输出函数(Format$)
用格式输出函数 Format$可以使数值、日期或字符串按指定的格式输出,一般用于 Print
方法中。其格式如下:
【格式】Format$(表达式[,"格式化符号"])
其中:表达式是要格式化的数值、日期和字符串类型表达式。格式化符号是表示输出表
达式值时所采用的输出格式。格式化符号要用引号括起来。
• 数值格式化:它是将数值型表达式的值按“格式化符号”指定的格式输出。有关格式
化符号及其应用举例如表 2-4-5 所示。注意:对于符号 0 与#,若要显示的数值表达式的整数
部分位数多于格式化符号的位数,则按实际数值显示,若小数部分的位数多于格式化符号的
位数,则四舍五入显示。
表 2-4-5 数值格式化的格式化符号及其作用
符 号 作 用 数值表达式 格式化字符串 显 示 结 果

实际数字小于符号位数时,数字 1234.567 “00000.0000” 01234.5670


0
前后加 0 1234.567 “000.0” 1234.6

实际数字小于符号位数时,数字 1234.567 “#####.####” 1234.567


#
前后不加 0 1234.567 “###.#” 1234.6

. 加小数点 12345 “00000.00” 12345.00

, 千分位 1234.567 “##,##0.0000” 1,234.5670

% 数值乘以 100,加百分号 1234.567 “####.##%” 123456.7%

$ 在数字前强加”$”号 1234.567 “$####.#” $1234.6

+ 在数字前强加”+”号 1234.567 “+####.#” +1234.6

1 在数字前强加”-”号 -1234.567 “-####.#” -1234.6

E+ 用指数表示 0.1234 “0.00E+00” 1.23E-01

E- 用指数表示 1234.567 “0.00E-00” 1.23E03


58 中文 Visual Basic 6.0 实用教程—结构化程序设计

• 日期和时间格式化:它是将日期型或数值型表达式的值转换为日期、时间的序数值,
并按“格式化符号”指定的格式输出。有关格式化符号及其应用举例如表 2-4-6 所示。

表 2-4-6 日期和时间格式化的格式化符号及其作用
符 号 作 用 符 号 作 用

d ,个位前不加 0
显示日期(1~3) dd 显示日期(01~31),个位前加 0

ddd 显示星期的缩写(Sun~Sat) dddd 显示星期全名(Sunday~Saturday)

ddddd 显示完整日期(日、月、年),默认格式为 mm/dd/yy

w 星期为数字(1~7,1 是星期日) ww 一年中的星期数(1~53)

m ,个位前不加 0
显示月份(1~12) mm 显示月份(01~12),个位前加 0

mmm 显示月份缩写(Jan~Dec) mmmm 月份全名(January~December)

y 显示一年中的天数(1~366) yy 两位数显示年份(00~99)

yyyy 四位数显示年份(0100~9999) q 显示季度数(1~4)

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)

显示完整时间(小时、分和秒),默认格式 AM/PM 12 小时的时钟,中午前 AM 或 am 中午后 PM


ttttt
为 hh:mm:ss am/pm 或 pm

A/P 或 a/p 显示 12 小时的时钟,中午前为 A 或 a 中午后为 P 或 p

其 中 ,分 钟 的 格 式 化 符 号 m、mm 与 月 份 的 格 式 化 符 号 相 同,区 分 的 方 法 :是 跟
在 h、 hh 后 的 为 分 钟 , 否 则 为 月 份 。 非 格 式 化 符 号 -、 /、 : 等 照 原 样 显 示。
2.格式输出函数应用举例
例 1 数值格式化输出验证程序如图 2-4-3 所示,程序运行结果如图 2-4-4 所示。

图 2-4-3 数值格式化输出验证程序 图 2-4-4 程序运行结果

例 2 日 期 和 时 间 格 式 化 输 出 验 证 程 序 如 图 2-4-5 所 示 , 程 序 运 行 结 果 如 图
2-4-6 所 示 。
第2章 中文 Visual Basic 6.0 编程基础 59

图 2-4-5 日期和时间格式化输出验证程序 图 2-4-6 程序运行结果

• 字符串格式化:字符串格式化是将字符串按格式化符号指定的格式进行强制大小写显
示等。常用的字符串格式化符号及使用举例如表 2-4-7 所示。
表 2-4-7 字符串格式化的格式化符号及其作用
符 号 作 用 字符串表达式 格式化符号 显 示 结 果

< 强迫字母以小写显示 Basic “<” basic

> 强迫字母以大写显示 Basic “>” BASIC

实际字符位数小于符号 ABCDEF,
@ ABCDEF “@@@@@@@@”
位时,字符前加空格 在“ABCDEF”前有 2 个空格

实际字符位小于符号位 ABCDEF,在“ABCDEF”前
& ABCDEF “&&&&&&&&&”
时,字符前不加空格 无空格

3.日期和时间函数的验证程序
日期和时间函数的验证程序如图 2-4-7 所示,程序是用来验证上面介绍的判断和转换函
数的一些概念,程序运行结果如图 2-4-8 所示。

图 2-4-7 日期和时间函数的 验 证 程 序 图 2-4-8 程序运行结果

2.5 使用 Print 方法输出信息

Visual Basic 语言包含了普通 Basic 语言具有的一些语句,例如 Let(赋值)、End(结束)、


60 中文 Visual Basic 6.0 实用教程—结构化程序设计

Beep(响铃) 、Rem(注释)和选择语句、循环语句等。普通 Basic 语言中的一些语句在 Visual


Basic 中成为了方法,例如 Print(打印语句)和 CLS(清屏语句)等。关于选择语句、循环
语句等将在下一章介绍。语句是由 Visual Basic 关键字、常量、变量、函数、表达式、对象
名称、属性和方法等组成的指令。最简单的语句可以只有一个 Visual Basic 关键字,例如 End。
一个语句行可以有多条语句,各语句之间必须用冒号“:”分隔;一条语句也可以分多行书写。

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 。

2.5.2 Print 和 Cls 方法

1.Print方法
Print 方法在窗体、图片框、立即窗口和打印机等对象中,用来显示文本字符串和表达式
的值。Print 方法的格式和功能与早期 Basic 语言中的 PRINT 语句类似。
【格式】[对象名称.]Print[表达式表]
【功能】首先计算表达式的值,然后在指定的对象中,输出表达式的值。
【说明】
① 对象可以是窗体(Form)、立即窗口(Debug) 、图片框(PictureBox)和打印机(Printer)
等,如果省略对象名称,则在当前窗体上输出。
② Print 关键字可以用“?”代替,Visual Basic 会自动将它翻译为 Print。
③ 表达式表是由若干个表达式组成,各表达式之间可用分隔符为逗号(,)、分号(;)
第2章 中文 Visual Basic 6.0 编程基础 61

或 Tab、Spc 函数等。分隔符和 Tab、Spc 函数可以在一条语句中混合应用。


④ Print 的显示格式有分区格式和紧凑格式两种。当各表达式用逗号作为分隔符时,按
打印区显示数据项,每隔 14 列开始一个打印区,每列的宽度是所选字体磅值大小的所有字符
的平均宽度。
当各表达式用分号作为分隔符时,输出格式为紧凑格式,此时将在每个数值的后面增加
一个空格,如果数值为正数,将把正号显示为空格。在 Print 中,可以将逗号、分号和 Tab、
Spc 函数混合使用。
⑤ 如果 Print 的末尾没有分号、逗号或 Tab 函数,则每一次执行 Print 后会自动换行,即
光标移到下一行的最左边。其后再执行 Print 时,将在新的一行上显示表达式的值。
⑥ 如果 Print 的末尾加有分号、逗号或 Tab 函数,则其后再执行 Print 时,不一定在新的
一行上显示表达式的值。当使用分号时,下一个 Print 输出的内容将紧跟在当前 Print 所输出
内容的后面;当使用逗号,则在同一行上跳到下一个显示区段显示下一个 Print 所输出的内容。
当只有 Print 时,只将光标移到下一行,不输出任何内容。
2.与Print方法有关的函数
为了使数据按指定的位置输出,Visual Basic 提供了几个与 Print 配合使用的函数。
(1)Tab 函数:Tab 函数与 Print 方法一起使用,对输出光标进行定位。
【格式】Tab(n)
【功能】计算数值型表达式 n 的值,把光标或打印头位置移到由数值型表达式 n 的数值指定
的列数,从此列开始输出数据。要输出的内容放在 Tab 函数后面,可以用分号隔开。例如:
Print Tab(5);"学号";Tab(15)"姓名";Tab(25)"性别";Tab(35)"成绩"
【说明】n 为数值表达式,其值为一个整数,它是下一个输出位置的列号,表示在输出前
把光标或打印头移到该列。通常最左边的列号为 1。如果当前的显示位置已经超过 n,则自动
下移一行。当 n 大于行的宽度时,显示位置为 n Mod 行宽数,如果 n<1,则把输出位置移到
第 1 列。当在一个 Print 中有多个 Tab 函数时,每个 Tab 函数对应一个输出项。
(2)Spc 函数:在 Print 方法或 Print#语句中,使用 Spc(n)函数可以添加 n 个空格。
【格式】Spc(n)
【功能】计算数值型表达式 n 的值,它给出了显示或打印下一个表达式值之前插入的空
格数。Spc 函数与输出项间可用分号分隔。例如:
Print Spc(3); "学号"; Spc(6); "姓名"; Spc(6); "性别"; Spc(6); "成绩"
【说明】
① 当 Print 方法与不同大小的字体一起使用时,使用 Spc 函数打印的空格字符的宽度总
是等于以磅数为单位(选用字体内的)所有字符的平均宽度。
② Spc 函数与 Tab 函数的作用类似,可以互相代替。但应注意,Tab 函数从对象的左端
开始计数,而 Spc 函数只表示两个输出项之间的间隔。
③ 除 Spc 函数外,还可以使用 Space 函数,该函数与 Spc 函数的功能类似。
④ 要精确地把文本输出到窗体、图片框或打印页上,可以使用对象的位置属性 CurrentX
和 CurrentY。
注意:如果在 Form_Load 事件内显示信息,必须使用 Show 方法或者把 AutoRedraw 属
性设为 True。否则,当程序运行时什么都不显示。
62 中文 Visual Basic 6.0 实用教程—结构化程序设计

3.Cls方法
【格式】Cls
【功能】将窗体(Form) 、图片框(PictureBox)等内的文本内容清除。默认的对象是窗体。
例如:Form1.Cls、Picture1.Cls、Cls。Form1.Cls 和 Cls 语句的效果一样。

2.5.3 项目实现

图 2-5-1 所示 程 序 是 用 来 验 证 Print 方法和与之有关的函数功能的 实 例 , 程 序 运 行


的 结 果 如 图 2-5-2 所 示 。

图 2-5-1 Print 方法应用程序 图 2-5-2 程序运行结果

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

流程图规定的几何图形如表 3-1-1 所示。


表 3-1-1 流程图规定的几何图形
符 号 作 用 符 号 符 号

起始框:表示程序的起始和终 输入输出框:表示输入输出数据

处理框:表示完成某种项目的 流程线:表示程序执行的方向
操作

判断框:表示进行判断 连接点:表示两段流程图流程的连
接点

用流程图描述程序的 3 种基本结构如图 3-1-1 所示。

A 成立
条件

不成立
B A B

(a) (b)

A
A
成立 成立
条件 条件

不成立 不成立

当型循环 直到型循环
(c)

图 3-1-1 流程图描述程序 3 种基本结构

2.N-S 图描述方法
N-S 图是 1973 年美国科学家 Nassi 和 Shneid erman B 首次提出的一种描述算法的图形方
法。N-S 图形方法完全去掉了流程线,全部算法写在一个矩形框内,总框内包含其他的功能
框。用 N-S 图描述程序的 3 种基本结构如图 3-1-2 所示。

条件 条件
A 不
成立 成立 A

B A B A
条件

(a) (b) 当型循环 直到型循环


(c)

图 3-1-2 N-S 图描述程序 3 种基本结构


3.PAD 图描述方法
PAD(Problem Analysis Diagram,问题分析图)是近年来在软件开发中被推广使用的一
种描述算法的图形方法。它是一种二维图形,从上到下各框功能顺序执行,从左到右表示层
68 中文 Visual Basic 6.0 实用教程—结构化程序设计

次关系。这种描述算法的方法,层次清楚,逻辑关系明了,在有多次嵌套时,不易出错。用
PAD 图描述程序的 3 种基本结构如图 3-1-3 所示。
A A


件 当条件 A 直到条件 A

当型循环 直到型循环
B B

(a) (b) (c)

图 3-1-3 用 PAD 图描述程序的 3 种基本结构

3.1.3 项目实现

储户到银行提取存款时,银行的出纳员应如何付款才可以使储户拿到的人民币的张数最
少呢?“银行取款”程序可以根据用户输入的金额数,计算出每种面值所需的数量,程序运
行后的画面如图 3-1-4 所示。在“取款总金额”标签右边的两个文本框内分别输入要提取金
额的整数和小数部分,单击“面值分配方案”按钮,则会在下面的标签中显示出各种人民币
的数量,如图 3-1-5 所示。

图 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 项目拓展——“四则运算”程序

“四则运算” 程序运行后会产生两个 100 以内的随机正整数,


如图 3-1-6 所示。
分别单击
“+”

“−”、“*”
、“÷”按钮,可以求两个数字的和、差、积、商。例如,单击“+”按钮后,即可求
两个随机正整数的和,如图 3-1-7 所示。单击“重新”按钮,则会重新产生两个随机正整数,
可以开始新的计算。单击“退出”按钮,结束程序运行。

图 3-1-6 “四则运算”程序的起始画面 图 3-1-7 “四则运算”程序求积运算


70 中文 Visual Basic 6.0 实用教程—结构化程序设计

1.“四则运算”程序的对象属性设置
“四则运算”程序的控件对象有 6 个标签和 7 个按钮,如图 3-1-7 所示。这些对象的主要
属性设置如表 3-1-2 所示。对象的序号按从上到下、从左到右的顺序依次排号。
表 3-1-2 “四则运算”程序控件对象的属性设置
序 号 类 别 名 称 Caption 文 字 特 点

1 窗体 Form1 四则运算 楷体_GB2312、小四号、粗体

2 标签 标题 进行四则运算题的计算 楷体_GB2312、18 号、红色

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 计 算 运 费

在 Visual Basic 中,实现选择结构的语句有单选择双分支、多选择多分支和多分支开关


语句。条件语句的功能都是根据表达式的值是否成立,有条件地执行一组语句。

3.2.1 单选择双分支语句

1.单行式 If Then Else 语句


【格式】If 条件 Then 语句序列 1 [Else 语句序列 2]
【功能】格式中的“条件”可以是关系表达式或逻辑表达式。当条件成立(即其值为 True)
时,执行“语句序列 1”各条语句;当条件不成立(即其值为 False)时,执行“语句序列 2”
各条语句,如果没有“Else 语句序列 2”则不执行,然后执行其后的语句。其功能可参看图
3-1-1 至图 3-1-3 中的(b)图。图中的 A 就是语句序列 1,图中的 B 就是语句序列 2。
【说明】
① 语句序列中的语句可以有多条,各条语句之间应用冒号分隔。
② 格式中的“条件”可以是数值表达式和数值形式的字符串表达式,当它们的值为非
零的数(例如:233)或由非零的数组成的字符串(例如:"a string")时,执行“语句序列 1”
的各条语句;当它们的值为 0 或由 0 的数组成的字符串(例如:0、"0")时,执行“语句序
列 2”的各条语句。括号“[ ]”内的内容是可选项。
2.区块式 If Then Else 语句
【格式】If 条件 Then
语句序列 1
[Else
语句序列 2]
End If
72 中文 Visual Basic 6.0 实用教程—结构化程序设计

【功能】当条件成立时,执行“语句序列 1”中的各条语句;当条件不成立时,执行“语
句序列 2”中的各条语句,如果没有“Else 语句序列 2”选项,则不执行,然后执行 End If 后
面的各条语句。括号“[ ]”内的内容是可选项,其功能可参看图 3-1-1 至图 3-1-3 中的(b)图。
【说明】“语句序列 1”和“语句序列 2”可以由一个语句行或多个语句行组成。在编程
的习惯上,常把夹在关键字 If、Then 和 Else 之间的语句序列以缩排的方式排列,这样会使程
序更容易阅读理解。

3.2.2 If Then Elself 语句

无论是单行式还是区块式的 If… Then… Else 语句,都只有一个条件表达式,只能根据一


个条件表达式进行判断,因此最多只能产生两个分支。
如程序需要根据多个条件表达式进行判断,产生多个分支时,就需要使用 If… Then…
ElseIf 语句。
【格式】If 条件 1 Then
语句序列 1
[ElseIf 条件 2 Then
语句序列 2]
......
[Else
语句序列 N]
End If
【功能】当条件 1 的值为 True 时,则执行语句序列 1;当条件 1 的值为 False 时,则再判
断条件 2 的值……依此类推,直到找到一个值为 True 的条件为止,并执行其后面的语句序列。
如果所有条件的值都不是 True,则执行关键字 Else 后面的语句序列 N。无论哪一个语句序列,
执行完后都接着执行关键字 End If 后面的语句。其功能可参看图 3-2-1 所示的流程图。
【说明】语句中的“条件”和语句序列的要求及功能与 If Then Else 语句相同。

不成立
不成立 不成立
不成立
条件 1 条件 2 …… 条件 N–1

成立 成立 成立

语句序列 1 语句序列 2 …… 语句序列 N–1 语句序列 N

图 3-2-1 If Then Elself 语句流程图

3.2.3 项目实现

“计算运费”程序是用来为货物托运站计算运费的。该程序运行后,窗体如图 3-2-2 所示。


单击窗体中的“输入货物的重量”按钮,即可调出一个“请输入货物重量数”对话框,要求
第3章 基本算法和控制结构 73

输入一个数,它是货物重量。输入一个货物重量值(例如:50),如图 3-2-3 所示,然后单击


“确定”按钮,即可关闭“请输入货物重量数”对话框,回到原窗体中,并在窗体中显示出收
费结果,如图 3-2-4 所示。货物的收费标准是:如果货物的重量小于或等于 30kg,按每千克
2 元收费;如果货物的重量大于 30kg 时,除了按每千克 2 元收费外,超出 30kg 部分需每千
克加收 0.80 元。程序的设计方法如下。

图 3-2-2 程序运行结果 图 3-2-3 输入货物重量 图 3-2-4 显示运费

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

图 3-2-5 If Then Else 语句流程图 图 3-2-6 If Then Elself 语句流程图

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

所示。

图 3-2-7 “符号函数”程序运行后的 3 个画面

不成立 不成立
N>0 N=0 N<0

成立 成立 成立

FH=“这是正数!” FH=“这是零!” FH=“这是负数!”

图 3-2-8 If Then Elself 语句流程图

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))
If N > 0 Then
FH = "这是正数!"
ElseIf N = 0 Then
FH = "这是零!"
ElseIf N < 0 Then
FH = "这是负数!"
End If
Label2.Caption = "输入的数是:" & N
Label3.Caption = FH
End Sub
Private Sub Command2_Click()
End
End Sub
2.“工资扣税”程序
【实例】“工资扣税”程序是用来统计工资上交税款情况。该程序运行后,窗体如图 3-2-9
所示。单击窗体中的“输入工资数”按钮,即可调出一个“请输入工资数”对话框,如图 3-2-10
所示。输入一个工资数值(此处输入 1800),然后单击“确定”按钮,即可关闭“请输入工
资数”对话框,回到原窗体中,并在窗体中显示出统计结果,如图 3-2-11 所示。输入不同的
工资数后,单击“请输入工资数”对话框中的“确定”按钮,可以显示不同的统计情况,如
图 3-2-12 所示。
76 中文 Visual Basic 6.0 实用教程—结构化程序设计

图 3-2-9 程序运行结果 图 3-2-10 输入工资数 图 3-2-11 显示统计结果

图 3-2-12 书如不同的工资数后显示不同的统计结果

工资的扣税标准是:如果工资小于或等于 1 000 元,则不交税;如果工资大于 1 000 元


而小于等于 1 500 元时,超出 1 000 元的部分需要交纳 5%的税款;如果工资大于 1 500 元而
小于等于 5 000 元时,超出 1 500 元而小于等于 5 000 元的部分需要交纳 20%的税款;如果工
资大于 5 000 元而小于等于 10 000 元时,超出 5 000 元而小于等于 10 000 元的部分需要交纳
30%的税款;如果工资大于 10 000 元时,超出 10 000 元的部分需要交纳 40%的税款。
(1)用鼠标拖曳“Form1”窗体四周的灰色方形控制柄,适当调整窗体的大小。在窗体
内的下边创建两个按钮控件对象。两个按钮的 Caption 属性分别为“输入工资数”和“退出” ,
“名称”属性采用默认值“Command1”和“Command2”。“Form1”窗体的 Caption 属性值
设置为“工资扣税”,设置文字字体为宋体、四号、加粗,颜色为红色。
(2)在窗体内创建 4 个标签对象,保留“名称”文本框中的默认名称“Label1”、
“Label2”、“Label3”和“Label4”。“Label1”标签对象的 Caption 属性值设置为“工资扣
税”,设置文字字体为宋体、四号、加粗,颜色为红色。其他标签对象的 Caption 属性值
设置为空字符串,设置文字字体为黑体、5 号、加粗,颜色为黑色,它们的 SackStyle 的
属性都为 1-Opaque。
下面是输入的代码程序,程序中的选择结构程序的流程图如图 3-2-13 所示。

不成立 不成立 不成立 不成立


N1>1000And N1>1500And N1>5000And
N1<=1000 N1>10000
N1<=1500 N1<=5000 N1<=10000

成立 成立 成立 成立 成立

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-2-13 If Then Elself 语句流程图

Private Sub Command1_Click()


第3章 基本算法和控制结构 77

Dim N1, N2, N3 As Single


TS$ = "请您输入工资数!" + Chr(13) + Chr(10) + "工资数是:"
Rem 将输入的工资数赋给变量 N
N1 = Val(InputBox(TS$, "请输入工资数", 0, 5000, 1600))
If N1 <= 1000 Then
N2 = 0
ElseIf N1 > 1000 And N1 <= 1500 Then
N2 = (N1 - 1000) * 0.05
ElseIf N1 > 1500 And N1 <= 5000 Then
N2 = (N1 - 1000) * 0.05 + (N1 - 1500) * 0.15
ElseIf N1 > 5000 And N1 <= 10000 Then
N2 = (N1 - 1000) * 0.05 + (N1 - 1500) * 0.15 + (N1 - 5000) * 0.1
ElseIf N1 > 10000 Then
N2=(N1-1000)* 0.05+(N1-1500)*0.15+(N1-5000)*0.1+(N1-10000)*0.1
End If
N3 = N1 - N2
Label2.Caption = "原工资数是:" & N1
Label3.Caption = "上缴税款是:" & N2
Label4.Caption = "实发工资数是:" & N3
End Sub
Private Sub Command2_Click()
End
End Sub

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

不成立 成立

FH="这是负数!" FH="这是正数!" FH="这是零!"

图 3-3-1 选择结构的嵌套流程图

3.3.2 Select Case 语句

If Then ElseIf 语句可以包含多个 ElseIf 子语句,这些 ElseIf 子语句中的条件一般情况下


是不同的。但当每个 ElseIf 子语句后面的条件都相同,而条件表达式的值并不相同时,使用
If Then ElseI 语句编写程序就会很烦琐,此时可使用下面介绍的 Select Case 语句。
【格式】Select Case 表达式
[Case 取值列表 1
语句序列 1]
[Case 取值列表 2
语句序列 2]
......
[Case Else
语句序列 N]
End Select
【功能】计算表达式的值,再将其值依次与每个 Case 关键字后面的“取值列表”中的数
据和数据范围进行比较,如果相等,就执行该 Case 后面的语句序列;如果都不相等,则执行
Case Else 子语句后面的语句序列 N。无论执行的是哪一个语句序列,执行完后都接着执行关
键字 End Select 后面的语句。程序中的选择结构程序的流程图如图 3-3-2 所示。
【说明】
① 表达式可以是数值表达式或字符串表达式。
② 每一个 Case 后面的“取值列表”中的数据是表达式可能取得的结果,其“取值列表”
的格式有以下 3 种。
第3章 基本算法和控制结构 79

表达式

计算表达式的值与取值列
表 N–1 中的数据不相等
取值列表 1 取值列表 2 …… 取值列表 N–1

计算表达式的值与取值 计算表达式的值与取值 计算表达式的值与取值


列表 1 中的数据相等 列表 2 中的数据相等 列表 N–1 中的数据相等

语句序列 1 语句序列 2 …… 语句序列 N–1 语句序列 N

图 3-3-2 Select Case 语句流程图


• 数 值 型 或 字 符 型 常 量 或 表 达 式 。 例 如 ,“ 10 ”、“ 1,5,7 ”、“ Val("n")−5 ”、“ S ”、
“"A",F,E”
、“Chr(65) & 12”等。其中,认为数字可以是数值或字符,认为字母是变量,只有
用引号括起来的字母才会被认为是字母。
• 使用“To”来表示数值或字符常量区间,“To”两边可以是数值型或字符型常量。例
如,“1 To 10”、“A To D” 、“"A" To "D"”等。注意“To”左边的数值或字符应小于“To”右
边的数值或字符。
• 使用“Is 表达式”来表示数值或字符串区间。这种方法适用于取值为含有关系运算符
的式子,在实际输入时,加或不加 Is 都可以,光标一旦离开该行,Visual Basic 会自动将它
加上。例如, “Is>10”、“Is>=S”、 “Is<="X"”等。
上述的三种格式可以混合使用。例如,Case A To F,16,30,Is>10。其中,A To F 为变
量 A 和 F 所表示的数据区间的数据,16 和 30 可以是数值或字符数据,Is>10 为 Is 表达式,
表示所有大于 10 的数据。
可以同时设置多个不同的范围,各范围之间用逗号分隔开来。例如,−16,1 To 100。
③ 如果不止一个 Case 后面的取值与表达式相匹配,则只执行第一个与表达式匹配的
Case 后面的语句序列。

3.3.3 项目实现

“求一元二次方程的解”程序运行后,窗体显示如图 3-3-3 所示(没有文本框中的数值)。


在“a=”
、“b=”和“c=”3 个文本框中输入数之后,单击“求根”按钮,即可在按钮下边的
标签内显示一元二次方程 ax2+bx+c=0 根,如图 3-3-3 左图(两个相等的根)
、图 3-3-3 中图(两
个不同的实根)和图 3-3-3 右图(没有实根)所示。

图 3-3-3 一元二次方程的根
80 中文 Visual Basic 6.0 实用教程—结构化程序设计

2
2 − b ± b − 4ac
一元二次方程 ax +bx+c=0 的求根公式 x = 是数学中最常用的公式之一,
2a

本实例中将求根公式程序化,只要输入 a、b、c 的值,就可以自动求出方程的根。


1.设置对象的属性
(1)按照图 3-3-3 所示在窗体上添加 5 个标签,3 个文本框和 3 个按钮,添加顺序为从上
到下,从左到右。各对象名称均取默认名称。
(2)“Label1”标签对象的 Caption 属性为“求一元二次方程的根”,“Label2”标签对象
的 Caption 属性为“a=”“Label3”标签对象的 Caption 属性为“b=”
, ,“Label4”标签对象的
Caption 属性为“c=”,“Label5”标签对象的 Caption 属性为空。3 个文本框对象的 Text 属性
为空。
(3)“Label1”标签对象的字体为宋体、三号字、加粗,颜色为红色;“Label2”到“Label4”
标签对象的字体为黑体、5 号字、加粗,颜色为蓝色;“Label5”标签对象的字体为黑体、5
号字、加粗,颜色为红色。3 个按钮的 Caption 属性分别为“求根”、“清除”和“退出”,字
体为黑体、5 号字、加粗,颜色为红色。
下面采用两种语句来输入代码程序,程序的运行效果一样。
2.使用选择结构嵌套的代码程序
Private Sub Command1_Click()
Dim a As Integer, b As Integer, c As Integer
Dim D As Single, x1 As Single, x2 As Single
Dim FCG As String
a = Val(Text1.Text)
b = Val(Text2.Text)
c = Val(Text3.Text)
D=b*b-4*a*c
If D < 0 Then
FCG = "该方程无实根!" '判断是否有实根
Else
If D = 0 Then
x1 = (-b) / (2 * a) '求方程的实根
FCG = "该方程有两个相同的实数根:" + Chr(13) + "x1 ="+Str(x1)
Else
x1 = (-b + Sqr(D)) / (2 * a) '求方程的第一个实根
x2 = (-b - Sqr(D)) / (2 * a) '求方程的第二个实根
FCG="该方程有两个不同实数根:"+Chr(13)+"x1="+Str(x1)+ "x2="+Str(x2)
End If
End If
Label5.Caption = FCG
End Sub
Rem 清除各文本框中的内容
Private Sub Command2_Click()
Text1.Text = ""
Text2.Text = ""
第3章 基本算法和控制结构 81

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 选择结构的嵌套流程图

3.Select Case 语句的代码程序


将窗体的“名称”属性改为“Form2” ,Caption 属性改为“Form2”
。然后,单击“文件”→
“工程另存为”菜单命令,将当前的工程保存为“工程 2.vbp”文件。单击“文件”→“Form1.frm
另存为”菜单命令,将当前的窗体文件保存为“Form2.frm”文件。
将程序中的结构化程序进行修改如下。程序中的选择结构程序的流程图如图 3-3-5 所示。

D
(D=b×b–4×a×c)

Is<0 Is=0 Is>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-5 使用 Select Case 语句的流程图


82 中文 Visual Basic 6.0 实用教程—结构化程序设计

Private Sub Command1_Click()


Dim a As Integer, b As Integer, c As Integer
Dim D As Single, x1 As Single, x2 As Single
Dim FCG As String
a = Val(Text1.Text)
b = Val(Text2.Text)
c = Val(Text3.Text)
D=b*b-4*a*c
Select Case D '使用 D 为分支条件,判断根的性质
Case Is < 0
FCG = "该方程无实根!" '没有实根
Case Is = 0
x1 = (-b) / (2 * a) '求方程的实根
FCG = "该方程有两个相同的实数根:" + Chr(13) + "x1 = " + Str(x1)
Case Is > 0
x1 = (-b + Sqr(D)) / (2 * a) '求方程的第一个实根
x2 = (-b - Sqr(D)) / (2 * a) '求方程的第二个实根
FCG="该方程有两个不同实数根:"+Chr(13)+" x1="+Str(x1) + "x2="+Str(x2)
End Select
Label5.Caption = FCG
End Sub
Rem 清除各文本框中的内容
Private Sub Command2_Click()
Text1.Text = ""
Text2.Text = ""
Text3.Text = ""
End Sub
Rem 退出程序运行
Private Sub Command3_Click()
End
End Sub

3.3.4 项目拓展——“工资扣税”程序

1.Select Case 语句的验证程序


在窗体内创建一个名称为“Command1”的按钮和一个名称为“Label1”的标签,标签用
来显示输入的数据。单击“Command1”按钮后即可执行下面的程序。在输入不同的数据后,
会在窗体中显示不同的内容。用户可以上机操作,并输入不同的数据,以了解 Select Case 语
句的功能,理解“取值列表”格式的特点。程序如下。
Private Sub Command1_Click()
Dim N As String, B, C As Integer '声明变量 FS1 是字符型,B 和 C 变量是数值型
N = InputBox$("请输入字符数据:") '输入一个数据,赋给变量 N
Cls:Label1.Caption = N:B = 100: C = 200
Select Case N
Case "A" To "G" '输入打头字母为 A 到 G(包括字母 A 和 G)的字符串时,输出 1
Print "1"
第3章 基本算法和控制结构 83

Case 11, 18, 36, "20" '输入 11、36、20 时,输出 2


Print "2"
Case Val("50") - 10 '输入 40 时,输出 3
Print "3"
Case B, C '输入 100 或 200 时,输出 4
Print "4"
Case "H", B + C '输入 H 或 300 时,输出 5
Print "5"
Case "W" + Chr(65) & 22 '输入 WA22 时,输出 6
Print "6"
Case Is > "R" '输入大于 R 的大写字母时,输出 7
Print "7"
Case "X" To "Z",30,50,Is<0 '输入 X 到 Z 的字母或 30 或 50 或负数时,输出 8
Print "8"
Case Else '输入不符合上述要求的数据时,输出“无符合的数据!”
Print "无符合的数据!"
End Select
End Sub
2.使用 Select Case 语句的“工资扣税”程序
Private Sub Command1_Click()
Dim N1, N2, N3 As Single
TS$ = "请您输入工资数!" + Chr(13) + Chr(10) + "工资数是:"
Rem 将输入的工资数赋给变量 N
N1 = Val(InputBox(TS$, "请输入工资数", 0, 5000, 1600))
Select Case N1 '使用 D 为分支条件,判断根的性质
Case Is <= 1000
N2 = 0
Case 1001 To 1500
N2 = (N1 - 1000) * 0.05
Case 1501 To 5000
N2 = (N1 - 1000) * 0.05 + (N1 - 1500) * 0.15
Case 5001 To 10000
N2 = (N1 - 1000) * 0.05 + (N1 - 1500) * 0.15 + (N1 - 5000) * 0.1
Case Is > 10000
N2=(N -1000)*0.05+(N1-1500)*0.15+(N1-5000)*0.1+(N1-10000) *0.1
End Select
N3 = N1 - N2
Label2.Caption = "原工资数是:" & N1
Label3.Caption = "上缴税款是:" & N2
Label4.Caption = "实发工资数是:" & N3
End Sub
Private Sub Command2_Click()
End
End Sub
84 中文 Visual Basic 6.0 实用教程—结构化程序设计

3.4 九九乘法表

在解决实际问题时,常常需要重复某些相同的操作,即对某一语句或语句序列重复执行
多次,解决此类问题,就要用到循环结构语句。

3.4.1 For Next 语句

1.For Next 语句的格式与功能


【格式】 For 循环变量=初值 To 终值 [Step 步长值]
[循环体语句序列]
Next [循环变量]
【功能】
① 执行 For 语句时,首先计算初值、终值和步长值各数值型表达式的值,再将初值赋给
循环变量。然后将循环变量的值与终值进行比较,如果循环变量的值没有超出终值,则执行循
环体语句序列的语句,否则执行 Next 下面的语句。
② 执行 Next 语句时,将循环变量的值与步长值
循环变量赋初值
确定终止和步长值 相加,再赋给循环变量,然后将循环变量的值与终值
进行比较,如果循环变量的值没有超出终值,则执行
循环体语句
循环体语句序列的语句,否则执行 Next 下面的语句。
③ 若步长值为正数,则循环变量的值大于终值时
为超出;若步长值为负数,则循环变量的值小于终值
循环变量+步长值 否 时为超出。
循环变量是否超出终止
For Next 语句的功能可参看图 3-4-1 所示的流程图。
是 【说明】
① 如果没有关键字 Step 和其后的步长值,则默
图 3-4-1 For Next 语句功能的流程图
认步长值为 1。
② 循环变量是数值型变量,初值、终值和步长值都是数值型的常量、变量或表达式,
但不能是数组的数组元素。
③ 在循环体语句序列中可以加入 Exit For 语句,执行该语句后会强制程序脱离循环,执
行 Next 下面的语句。Exit For 语句通常放在选择结构语句之中使用。
④ 如果出现循环变量的值总没有超出终值的情况,则会产生死循环。此时,可按
Ctrl+Break 快捷键,强制终止程序的运行。
⑤ 在 For Next 循环语句的循环体语句序列中可以使用 Exit For 语句,它的作用是退出该
循环体,它一般用于循环体语句序列中的判断语句。
2.分析程序的运行结果
分析循环语句程序的运行过程和运行结果,有利于帮助了解循环语句的功能。
【实例 1】程序如下。
Private Sub Form_Activate()
For N = 2 To 8 Step 3
第3章 基本算法和控制结构 85

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 所示。

图 3-4-2 实例 1 程序运行结果 图 3-4-3 实例 2 程序运行结果


【实例 3】求 1+2+…+100 的值。
程序如下。程序中的循环结构程序的流程图如图 3-4-4 所示。
Private Sub Form_Activate()
Dim N As Integer, SUM As Long
SUM = 0 '给变量 sum 赋初值 0
Rem 可循环 100 次,每一次循环使变量 N 自动加 1,N 依次取值 1,2,…,100
For N = 1 To 100
SUM = SUM + N '累加语句,进行变量 N 的累加
Next N
Print "1+2+…+100="; SUM '显示计算结果
End Sub
程序运行结果为:1+2+…+100=5050
【实例 4】求 10!的值。
程序如下。程序中的循环结构程序的流程图如图 3-4-5 所示。
86 中文 Visual Basic 6.0 实用教程—结构化程序设计

Private Sub Form_Activate()


Dim N As Integer, SUM As Long
SUM = 1 '给变量 sum 赋初值 1
Rem 可循环 10 次,每一次循环使变量 N 自动加 1,N 依次取值 1,2,…,10
For N = 1 To 10 '可循环 10 次,每一次循环使 N 自动加 1,N 依次取值 1,2,…,10
SUM = SUM * N '累加语句,进行变量 N 的累加
Next N
Print "10!="; SUM '显示计算结果
End Sub
程序的运行结果为:10!=3628800

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-4 实例 3 程序的流程图 图 3-4-5 实例 4 程序的流程图

【实例 5】求 1+(1+2)+…+(1+2+…+100)的值。


程序如下。程序中的循环结构程序的流程图如图 3-4-6 所示。
Private Sub Form_Activate()
Dim N As Integer, SUM, SUN1 As Long
SUM = 0: SUM1 = 0 '给变量 SUM 和 SUM1 赋初值 0
Rem 可循环 100 次,每一次循环使变量 N 自动加 1,N 依次取值 1,2,…,100
For N = 1 To 100
SUM = SUM + N '累加语句,进行变量 N 的累加运算
SUM1 = SUM1 + SUM '累加语句,进行变量 SUM 的累加运算
Next N
Print "1+(1+2)+…+(1+2+…+100)="; SUM1 '显示计算结果
End Sub

说明:在求 1+2+…+100 值的程序中,第 1 次循环中,SUM 的值为 1;第 2 次循环中,


SUM 的值为 1+2=3…第 100 次循环中,SUM 的值为 1+2+3+…+100=5050。可见,每次循环
中 SUM 的值正好是求 1+(1+2)+…+(1+2+…+100)值式子中的各项值,因此只要在每循环时将
SUM 进行累加即可。
程序的运行结果为:1+(1+2)+…+(1+2+…+100)=171700
第3章 基本算法和控制结构 87

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

① 执行 1 语句,变量 A 等于 1,外循环的终值为 2,外循环的步长值为 1。


② 执行 2 语句,变量 B 等于 5,内循环的终值为 3,内循环的步长值为−2。
③ 执行 3 语句,在第 1 行显示变量 A 的值 1,变量 B 的值 5,如图 3-4-8 所示。
④ 执行 4 语句,变量 B 加步长值−2 给变量 B,变量 B 为 3,与终值 3 比较,不小于终
值 3,返回到第 3 语句。

外循环变量 A=1 终值为 2 步长值为 1

内循环变量 B=5 终值为 3 步长值为–2


SUM=0
SUM1=0
显示变量 A 和 B 的值

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-6 实例 5 程序的流程图 图 3-4-7 循环嵌套的流程图


88 中文 Visual Basic 6.0 实用教程—结构化程序设计

⑤ 执行 3 语句,在第 2 行显示变量 A 的值 1,变量 B 的值 3,如图 3-4-8 所示。


⑥ 执行 4 语句,变量 B 加步长值−2 给变量 B,变量 B 为 1,与终值 3 比较,小于终值
3,执行第 5 条语句。
⑦ 执行 5 语句,A 加步长值 1 给 A,A 为 2,不大于终值 2,执行第 2 条语句。
⑧ 执行 2 语句,变量 B 等于 5,内循环的终值为 3,内循环的步长值为-2。
⑨ 执行 3 语句,在第 3 行显示变量 A 的值 2,变量 B 的值 5,如图 3-4-8 所示。
  执行 4 语句,B 加步长值-2 给 B, B 为 3,不小于终值 3,返回到第 3 语句。
  执行 3 语句,在第 4 行显示变量 A 的值 2,变量 B 的值 3,如图 3-4-8 所示。
  执行 4 语句,变量 B 加步长值-2 给变量 B,变量 B 为 1,
与终值 3 比较,小于终值 3,执行第 5 条语句。
  执行 5 语句,A 加步长值 1 给 A,A 为 3,与终值 2 比较,
大于终值 2,执行第 6 条语句,在第 5 行显示 A 的值“A=3” ,B
图 3-4-8 程序运行结果 的值“B=1”,如图 3-4-8 所示。
2.循环嵌套的注意事项
对于循环嵌套应注意以下几点。
① 内循环与外循环的循环变量名称不能相同。
② 外循环必须完全包含内循环,不可以出现交叉现象。
③ 不可以没有执行 For 语句,就执行 Next 语句。
下面的情况是错误的:
出现交叉现象 内外循环变量名称相同
For A=1 TO 30 For A=1 TO 56
For B=5 TO 1 Step –2 For A=16 TO 2 Step –3
…… ……
Next A Next A
Next B Next A

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-4-9 “九九乘法表 1”运行结果

程序中,外循环的循环变量 N1 用来产生被乘数,内循环的循环变量 N2 用来产生乘数。


每显示完一行后换行。
2.九九乘法表 2
“九九乘法表 2”程序运行后的画面如图 3-4-10 所示。程序只是将“九九乘法表 1”程序
中的“For N2 = 1 To n1”改为“For N2 = 1 To 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 9
Print Tab(N2 * 12 - 12); Str$(N1) + "×" + Str$(N2) + "=" + Str$(N1 * N2);
Next N2
Print
Next N1

图 3-4-10 “九九乘法表 2”运行结果

3.九九乘法表 3
“九九乘法表 3”程序运行后的画面如图 3-4-11 所示。程序只是将“九九乘法表 2”程序
“九九乘法表 3”程序如下。
中的内循环语句进行如下修改即可。
Private Sub Form_Activate()
90 中文 Visual Basic 6.0 实用教程—结构化程序设计

Dim N1, N2 As Integer


FontSize = 15
ForeColor = vbRed
FontBold = True
Print Tab(30); "九九乘法表": Print
FontSize = 10
ForeColor = vbBlue
FontBold = False
For N1 = 1 To 9
For N2 = N1 To 9
Print Tab(N2 * 12 - 12); Str$(N2) + "×" + Str$(N1) + "=" + Str$(N2 * N1);
Next N2
Print
Next N1
End Sub

图 3-4-11 “九九乘法表 3”运行结果

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 实用教程—结构化程序设计

Private Sub Form_Activate()


Dim A, B As Integer
For A = l1 To 100
For B = 9 To 90
If (A-8)<>(B-8)*3 Or (A+8)/(B+8)<>Int((A+8)/(B+8)) Then GoTo BT
Print "父亲现在岁数:"; A, "儿子现在岁数:"; B
BT: Next B
Next A
End Sub
在该程序中,使用了“Goto 标号”语句,可以无条件转到标号(例如:BT)所指示的
语句行,标号的右边一定要加冒号“:”。
5.“人民币取法”程序
【实例】 有面值为壹元、贰元和伍元的人民币若干,从中取出 20 张使其总值为 80 元,
问有多少种取法?每种取法中的壹元、贰元和伍元人民币各有多少张?
设取壹元人民币有 A 张,贰元人民币有 B 张,伍
元人民币有 C 张,共有 N 种取法。用三重循环产生各
种取法,在循环体内用条件判断语句进行是否符合条件
的判断,从而找出符合其总值为 80 元的取法。根据题
意可知,循环变量 A 的终值不能大于 80,循环变量 B
图 3-4-12 “人民币取法”程序运行结果 的终值不能大于 40,变量 C 的循环变量的终值不能大
于 18(因 5×16=80)。程序的运行结果如图 3-4-12 所示。程序如下:
Private Sub Form_Load()
Show
For A = 0 To 80
For B = 0 To 40
For C = 0 To 16
If A + B + C = 30 And A + B * 2 + C * 5 = 80 Then
N=N+1
Print Tab(2); "壹元张数:"; A;
Print Tab(17); "贰元张数:"; B;
Print Tab(32); "伍元张数:"; C
End If
Next C, B, A
Print: Print "人民币取法的总数为:"; N
End Sub

3.5 连续自然数的和

3.5.1 While Wend 语句

1.While Wend 语句的格式和功能


【格式】 While 条件
第3章 基本算法和控制结构 93

[循环体语句序列]
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

图 3-5-1 程序运行结果 图 3-5-2 While Wend 语句的流程图

① 执行 3 语句时,判断 N <= 6 关系表达式成立(其值为 True),则执行 4 语句。


② 执行 4 语句时,变量 N 加 2 后赋给变量 N,变量 N 为 2;变量 SU 加变量 N 的值 2 后
赋给变量 SU,变量 SU 为 2。
③ 执行 5 语句后,显示变量 SU 和变量 N 的值 2 和 2,如图 3-5-1 所示。
④ 执行 6 语句,返回 3 语句。执行 3 语句时,再判断 N <= 6 关系表达式成立,则执行
4 语句。执行 4 语句后,变量 N=4,变量 SU=6。
⑤ 执行 5 语句后,显示变量 SU 和变量 N 的值 6 和 4,如图 3-5-1 所示。
⑥ 执行 6 语句,返回 3 语句。执行 3 语句时,再判断 N <= 6 关系表达式成立,则执行
94 中文 Visual Basic 6.0 实用教程—结构化程序设计

循环体语句。执行完 4 语句和 5 语句后,变量 N=6,变量 SU=12,显示变量 SU 和变量 N 的


值 12 和 6,如图 3-5-1 所示。
⑦ 执行 6 语句,返回 3 语句。执行 3 语句时,再判断 N <= 6 关系表达式成立,则执行
循环体语句。执行完 4 语句和 5 语句后,变量 N=8,变量 SU=20,显示变量 SU 和变量 N 的
值 20 和 8,如图 3-5-1 所示。
⑧ 执行 6 语句,返回 3 语句。执行 3 语句时,再判断 N <= 6 关系表达式不成立,则执
行 7 语句 Print "SU="; SU,显示变量 SU 的值,如图 3-5-1 所示。
【实例 2】程序如下。它的流程图如图 3-5-3 所示。程序运行结果如图 3-5-4 所示。
Private Sub Form_Activate()
Dim N As Integer
N = 10: A = 1: B = 2: C = 3
While N > 4
C = A: A = B: B = C
N=N-3
Print A, B, C
Wend
Print "N="; N
End Sub

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-3 While Wend 语句的流程图 图 3-5-4 程序运行结果

第 1 次执行 While N>4 语句时,判断 N>4 关系表达式成立,执行循环体语句。语句


C=A:A=B:B=C 的作用是将 A、B 的值互换,输出 A、B、C 的值分别为 2、1、1;N=N–3 语
句使变量 N 变为 7,然后显示 A、B、C 的值。第 2 次执行 While N >4 语句时,判断 N>4 关
系表达式成立,执行循环体语句,输出 A、B、C 的值分别为 1、2、2;N=N–3 语句使变量 N
变为 4,然后显示 A、B、C 的值。第 3 次执行 While N>4 语句时,判断 N>4 关系表达式不
成立,执行 Wend 语句下边的语句 Print "N=";N,显示 N 的值为 4。

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-5 当型 Do Loop 语句的流程图 图 3-5-6 直到型 Do Loop 语句的流程图

3.5.3 项目实现

“连续自然数的和”程序运行后的画面如图 3-5-7 左图所示,在两个文本框中各输入 N 和


M 的值后,再单击“计算”按钮,即可显示出计算结果,如图 3-5-7 右图所示。

图 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

SUM = SUM + A + B '累加语句,进行变量 A 和 B 的累加运算


Print Tab(5 + K * 16); A; '定位显示变量 A 的值
Print Tab(21 + K * 16); B; '定位显示变量 B 的值,间隔为 16
If K =2 Then '每行显示 4 个数后换行
Print '换行
K = -2 '重设变量 K 的值,以保证下一次循环时 K 为 0
End If
A = A + B: B = A + B '产生两个新的裴波纳契数列的数
K=K+2 '重设变量 K 的值,以保证下一次循环时 K 为 0
Next N
Print: Print: Print Tab(25); "SUM="; SUM '两次换行后,显示计算的和
End Sub

程序运行中,前 4 次循环中,循环次数(序号)
、变量 K 的值、式子 5+K * 16 和 21+K *
16 的取值变化如表 3-5-1 所示。
表 3-5-1 程序运行中各有关项的取值变化

序 号 K 5+K * 16 21+K * 16 序 号 K 5+K * 16 21+K * 16

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 第 1 小题 For N2 =5 To 3 STEP –2


A="A":B="B":C="C" For N3=2 To N2
For K=5 To 1 Step -1 Print N1,N2,N3
X=A:A=B:B=C:C=X Next N3
Print A,B,C,K
Next N2
Next K
Next N1
Rem 第 2 小题
Print N1,N2,N3
For N=3 To 25 Step 2
Rem 第 4 小题
If N Mod 5=1 Then
Print "N=";N, A=1:B=10:C=2
End If For I=A To B Step C
Next N A=A+B:B=B+C:C=C+A
Rem 第 3 小题 I=I+2:Print A,B,C
For N1=5 To 10 Step 3 Next I
100 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 实用教程—结构化程序设计

20.使用当型 Do Loop 语句和直到型 Do Loop 语句分别编写求 2!+4!+…+10!值的程


序。使用 For Next 语句编写编写求 2!+4!+…+10!值的程序。
21.编写“求连续自然数的积”程序,该程序运行后的画面与图 3-5-7 左图一样,在两
个文本框中各输入 N 和 M 的值后,再单击“计算”按钮,即可显示出 N 到 M 连续自然数的
积,即 N*(N+1)*(N+2)*…*(M-1)*M。
优化算法和程序设计方法
第 4

4.1 优化算法—有趣的 4 个自然数

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 项目实现

有这样 4 个自然数,它们是一位或两位不为 0 的自然数,而且各自然数的和小于 50,各


自然数之间都互不相等,各自然数中任意两个自然数的和为偶数,任意 3 个自然数之和可以
被 3 整除,4 个自然数之和可以被 4 整除。要求编程显示出符合上述要求的,其和为最小的
一组 4 个自然数,以及它们的和。程序的设计方法可以有多种,下面介绍两种程序的设计
方法。
1.程序1
可以用 4 个循环分别产生 4 个自然数,各自然数的取值可以从 1 到 50。程序如下。
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 50
For B = 1 To 50
For C = 1 To 50
For D = 1 To 50
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 4 个自然数之和可以被 4 整除
If (A + B + C + D) Mod 4 <> 0 Then GoTo BT
Rem 将最小的一组符合条件的自然数和它们的和保存在相应的变量中
If A + B + C + D < S Then
第4章 优化算法和程序设计方法 105

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 程序的运行结果

方数并赋给变量 S,再分别取出前两位数与后两位数,分别赋给变量 A 和 B,然后判断变量


S 是否符合要求。这里产生 32~99 之间的所有自然数,是因为 31 的平方数为三位数,32 的
平方数为四位数,99 的平方数也为四位数。采用这种方法,比利用一个循环产生四位自然数
的方法的运行时间要短,算法的运算效率要高。设计的程序如下。
Dim N, S, A, B As Integer
Private Sub Form_Activate()
For N = 32 To 99
S=N*N '求出变量 N 的平方数,并赋给变量 S
108 中文 Visual Basic 6.0 实用教程—结构化程序设计

A = Int(S / 100): B = S - A * 100 '取出前两位数与后两位数,分别赋给变量 A 和 B


If (A + B) * (A + B) = S Then '判断(A + B) * (A + B) = S 条件是否成立
Print S,
End If
Next N
End Sub

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 文钱,一只母鸡值 3 文钱,三只小鸡值 1


文钱,有钱 100 文,买鸡 100 只,问所买公鸡几只?母鸡几只?小鸡几只?”编写程序,求
出它的所有解。
这是一道不定方程的典型题目。所谓不定方程是指未知数的个数多于方程个数的整系数
方程,它不但要求方程的解是整数或正整数,而且往往解的范围被限制在有限的范围内。许
多不定方程的应用题,其内容丰富、有趣,而且还与实际生活密切相关。
根据此题给出的条件,设公鸡为 A 只,母鸡为 B 只,小鸡为 C 只,可以列出下面的不
定方程式。下面采用穷举法,编写程序来解这个不定方程。
可以看出,上边的不定方程式中有 3 个未知数,但只有两个方程。按照穷举法的思想,
从方程解的定义出发,可以任取一组变量 A、B、C 的值带入不定方程式的两个式子中进行
检验,如果可以使两个式子成立,则为一组解,否则不是方程的解。

⎧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 实用教程—结构化程序设计

K 的 3 个循环分别用来产生第 1、2、3 名的运动员序号,A、B、C、D 四名运动员的序号分


别为 1、2、3、4,再用 Chr$(64+I)将获得冠军的运动员(A、B、C 或 D)显示出来,用 Chr$(64+J)
将获得亚军的运动员(A、B、C 或 D)显示出来,用 Chr$(64+K)将获得第 3 名的运动员(A、
B、C 或 D)显示出来。设计的程序如下。程序运行结果如图 4-2-3 所示。
Dim I, J, K, S As Integer
Private Sub Form_Activate()
For I = 1 To 4
For J = 1 To 4
For K = 1 To 4
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 '用来控制一行显示 5 个符合条件的运动员
End If
Next K
Next J
Next I
End Sub
3.“照片中都有谁”程序
【实例】 有 6 个同学到照相馆去照相,每次 3 个同学一起照相,一共应照多少张相片,
每张相片中都有谁?请编写程序解决该问题。
该题目是一个组合问题,它是从 6 个元素中选取 3 个元素的组合,应采用组合列举方法,
注意它是无序的。将这 6 个同学分别用字母 A、B、C、D、E 和 F 表示。程序中,用变量 I、J、
K 三个循环来分别产生照片中的序号,A、B、C、D、E 和 F 6 个学生的序号分别为 1、2、3、4、
5、6,再用 Chr$(64+I)、Chr$(64+J)和 Chr$(64+K)将照片中代表学生的字母显示出来。为了保证
产生的组合是无序的,则必须保证 6≥K>J>I≥1,可以通过选择每一个循环的初值和终值来实现。
设计的程序如下。程序运行结果如图 4-2-4 所示。

图 4-2-3 程序的运行结果 图 4-2-4 程序的运行结果

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 求 300 以内的素数和

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。

2 140 除数为 2 时可以整除 140,商 70


2 70 除数为 2 时可以整除 70,商 35
5 35 2、3 不能够整除 35,除数增加到 5 时可以整除 35,商 7

7 7 5、6 不能够整除 7,除数增加到 7 时可以整除 35,商 1


1 当商为 1 时,素因数分解结束

图 4-3-1 140 分解素数因数的方法

(2)以 45 为例:将 45 分解素数因数的方法与上述方法基本一样,用 45 除以最小的素


114 中文 Visual Basic 6.0 实用教程—结构化程序设计

数 2,不可以整除,再用 45 除以稍大的素数 3,可以整除,商 15;用其商 15 除以最小的素


数 2,不可以整除,再用其商 15 除以稍大的素数 3,可以整除,商 5;用其商 5 除以最小的
素数 2 不能整除,再用商 5 除以稍大的素数 3,不可以整除,再用商 5 除以稍大的素数 5,可
以整除,商 1。45 分解为素因数后,45=3*3*5。如图 4-3-2 所示。

3 45 2 不能够整除 45,除数增加到 3 可以整除 45,商 15


3 15 2 不能够整除 15,除数为 3 时可以整除 15,商 5
5 5 2、3 不能够整除 5,除数为 5 时可以整除 5,商 1
1 当商为 1 时,素因数分解结束

图 4-3-2 45 分解素数因数的方法

4.3.2 项目实现

“求 300 以内的素数和”程序可以显示 300 以内所有素数、素数个数和素数的和,要求每


行显示 8 个素数。采用素数定义求素数的方法编写的程序如下。程序运行结果如图 4-3-3 所示。

图 4-3-3 “求 300 以内的素数和”程序的运行结果

Private Sub Form_Activate()


Dim K, S, L, N As Integer '声明变量 K、S、L、N 为整型变量
Dim SUM As Long '声明变量 SUM 为长整型变量
K=1 '变量 K 用来统计素数的个数,赋初值 1
L=0
Print 2, '显示第 1 个质数
For N = 3 To 300 '产生 3 到 300 之间的所有自然数,赋给变量 N
For S = 2 To N-1 '依次用 N 除以 2 到 N-1 之间的自然数
If N Mod S = 0 Then L = 1: Exit For '如果能够整除,则给 L 赋 1,并退出循环
Next S
If L = 1 Then '如果 L=1 表示不是质数,变量 L=0 表示是质数
L=0 '将变量 L 还原为 0,L 为 0 时表示时素数
Else
If K Mod 8 = 0 Then '如果一行显示了 8 个质数,则换行
Print '换行
End If
Print N, '如果 L=0(即 L 不等于 1),则显示一个素数
K=K+1 '变量 K 用来统计素数的个数,K 自动加 1
SUM = SUM + N '变量 SUM 用来统计素数的和
End If
Next N
第4章 优化算法和程序设计方法 115

Print: Print: Print Tab(10); "300 以内质数个数为:"; K; '显示质数的个数


Print Tab(60); "300 以内质数的和为:"; SUM; '显示 300 以内质数的和
End Sub
程序中,用循环变量 N 的外循环来产生 3~300 之间的奇数,并赋给循环变量 N,用循
环变量 S 的内循环来产生 2 到 SQR(N)之间的所有自然数,作为除数。用变量 N 的数值除以
变量 S 的数值,如果变量 N 的数值能够被变量 S 的一个数值整除,则赋给变量 L 数值 1,表
示该变量 N 的数值不是素数;如果变量 N 的数值不能够被变量 S 的所有数值整除,则赋给变
量 L 数值 0,表示该变量 N 的数值是素数。以后,再根据变量 L 的值是否为 0,来确定是否
显示变量 N 的数值,即素数。素数的个数用变量 K 来统计,素数的和用变量 SUM 来统计。

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 程序的运行结果

Dim L, A, N, S As Integer '声明变量 K、S、L、N 为整型变量


Dim MM As Long '声明变量 SUM 为长整型变量
Dim TS$ '定义一个字符型变量 TS$
Private Sub Form_Activate()
Rem 保证输入的数是一个大于 2 的偶数
L=0
While L <> 1
TS$ = "请您输入一个大于 2 的偶数!" + Chr(13) + Chr(10) + "输入的偶数是:"
MM = Val(InputBox(TS$,"输入一个大于 2 的偶数",0,5000,1600)) '将输入的数赋给变量 MM
If MM > 2 And Int(MM / 2) = MM / 2 Then L = 1
Wend
Rem 验证哥德巴赫猜想的第一个命题(任何一个大于 2 的偶数都是两个素数的和)
Rem 显示 4 是两个素数的和
116 中文 Visual Basic 6.0 实用教程—结构化程序设计

If MM = 4 Then Print "4=2+2": GoTo BT1


Rem 显示大于 4 的偶数是两个素数的和
A= 1
BT1: A = A + 2 '产生一个新的奇数
N=A
Rem 判断变量 A 是否是素数,L=0 时是素数
L=0
For S = 2 To Sqr(N) '依次用 N 除以 2 到 SQR(N)间的自然数
If N Mod S = 0 Then L = 1: Exit For '如果能够整除,则给 L 赋 1,并退出循环
Next S
If L = 1 Then GoTo BT1 '如果 L=1 表示不是质数,则转 BT1 行语句
Rem 判断变量 MM - A 是否是素数,L=0 时是素数
N = MM - A
L=0
For S = 2 To Sqr(N) '依次用 N 除以 2 到 SQR(N)间的自然数
If N Mod S = 0 Then L = 1: Exit For '如果能够整除,则给 L 赋 1,并退出循环
Next S
If L = 1 Then GoTo BT1 '如果 L=1 表示不是质数,则转 BT1 行语句
Print MM; "="; A; "+"; MM - A; '显示结果
End Sub

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-1 右图所示。

图 4-4-1 “求两个数的最大公约数和最小公倍数”程序的运行结果

程序中的对象有:1 个窗体,5 个标签,两个文本框,两个按钮。它们的名称属性均采


118 中文 Visual Basic 6.0 实用教程—结构化程序设计

用默认值,标签 Label5 和 Label6 的 Border Style 属性设置为 1-Fixed Single,其他属性读者可


根据图 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
R=1 '余数 R 赋初值 1
While R <> 0
P = Int(A / B): R = A - B * P '求余数 R,变量 R 保存商
If R <> 0 Then A = B: B = R '如果余数 R 不为 0,则产生新的 A 和 B
Wend
Q=B
Rem 求 A 和 B 的最小公倍数 S
S = Val(Text1.Text) * Val(Text2.Text) / Q
Label5.Caption = Q '最大公约数赋标签 Label5
Label6.Caption = S '最小公倍数赋标签 Label6
End Sub
Private Sub Command2_Click()
End
End Sub

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

Label6.Caption = S '最小公倍数赋标签 Label6


End Sub
Private Sub Command2_Click()
End
End Sub

2.“求三个数的最大公约数和最小公倍数”程序
【实例】 “三个数的最大公约数和最小公倍数”程序运行后的画面如图 4-4-2 左图所示。
在三个文本框中输入三个数字后,单击“计算”按钮,即可算出这三个数的最大公约数和最
小公倍数,如图 4-4-2 右图所示。

图 4-4-2 “三个数的最大公约数和最小公倍数”程序运行结果

程序中的对象有:1 个窗体,6 个标签,3 个文本框,两个按钮。它们的名称属性均采用


默认值,标签 Label5 和 Label6 的 Border Style 属性设置为 1-Fixed Singl,其他属性读者可根
据图 4-4-2 自行设置。
在该程序中,首先采用辗转相除法求两个数 A 和 B 的最大公约数 Q1,再将两个数 A 和 B
相乘后再除以最大公约数 Q1,即可获得数 A 和 B 的最小公倍数 S1。然后,求 Q1 和 C 的最
大公约数,即求 A、B 和 C 的最大公约数 Q。最后,求数 C 和数 A 和 B 的最小公倍数 S1 的
最大公约数 S2,再将数 C 和 S1 相乘后除以最大公约数 S2,即可获得求三个数 A、B 和 C 的
最小公倍数。该程序如下。
Private Sub Command1_Click()
Dim A, B, C, R, P, Q1,Q As Integer, S, S1 As Long
A = Val(Text1.Text)
B = Val(Text2.Text)
C = Val(Text3.Text)
Rem 求 A 和 B 的最大公约数 Q1
R=1 'R 赋初值 1
While R <> 0
P = Int(A / B): R = A - B * P '求余数 R
If R <> 0 Then A = B: B = R '如果余数 R 不为 0,则产生新的 A 和 B
Wend
Q1 = B 'A 和 B 的最大公约数赋 Q
Rem 求 A 和 B 的最小公倍数 S1
S1 = Val(Text1.Text) * Val(Text2.Text) / Q1
Rem 求 Q1 和 C 的最大公约数,即求 A、B 和 C 的最大公约数
R=1 'R 赋初值 1
While R <> 0
P = Int(C / Q1): R = C – Q1 * P '求商 R 和余数 R
120 中文 Visual Basic 6.0 实用教程—结构化程序设计

If R <> 0 Then C = Q1: Q1 = R '如果余数 R 不为 0,则产生新的 C 和 Q1


Wend
Q = Q1 'A、B 和 C 的最大公约数赋给变量 Q
Label5.Caption = Q '最大公约数赋标签 Label5
Rem 求 S1 和 C 的最大公约数,再求最小公倍数,即求 A、B 和 C 的最小公倍数 S
S = S1
R=1 'R 赋初值 1
While R <> 0
P = Int(S1 / C): R = S1 - C * P '求商 R 和余数 R
If R <> 0 Then S1 = C: C = R '如果余数 R 不为 0,则产生新的 S1 和 C
Wend
S2=C 'S1 和 C 的最大公约数赋给变量 S2
S = Val(S) * Val(Text3.Text) / S2 '求三个数的最小公倍数 S
Label6.Caption = S '最小公倍数赋标签 Label6
End Sub
Private Sub Command2_Click()
End
End Sub

4.5 字符三角形图案

4.5.1 Str 函数和 Format 函数

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 所示。单击“输入行数”按钮后,弹出


一个“输入行数”对话框,该对话框的提示信息是“请输入三角形的行数和 3 到 17 之间的奇
数”,输入文本框中的默认值为 17,如图 4-5-2 所示。不改变该对话框中文本框内的数值,单
击“确定”按钮,又回到窗体,此时各个按钮均变为有效。
第4章 优化算法和程序设计方法 121

单击“字符三角形图案”按钮,可在窗体中显示出由“*”组成的三角形图案,如图 4-5-3 所示。

图 4-5-1 程序运行后的起始画面

图 4-5-2 “输入行数”对话框 图 4-5-3 程序运行后显示的三角形图案

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 所示。

图 4-5-4 程序运行后显示的字符平行四边形图案 图 4-5-5 “字符菱形图案”程序运行后显示的图案

“字符菱形图案”程序的窗体中有 1 个窗体和 3 个按钮对象控件,读者可以参考图 4-5-5


所示自行设计各个对象控件的属性。注意:3 个按钮的名称属性从左到右分别为“输入行数”、
“字符菱形”和“退出”。“字符菱形图案”程序的代码程序如下。
Dim N1, H, H1 As Integer
Private Sub 输入行数_Click()
TS$ = "请输入菱形的行数" + Chr(13) + Chr(10) + "3 到 17 之间的奇数"
H = Val(InputBox(TS$, "输入行数", 17, 5000, 1600)) '调出“输入”对话框
H1 = Int(H / 2) + 1
字符菱形.Enabled = True
End Sub
Rem 显示字符菱形图案
Private Sub 字符菱形_Click()
Cls '清窗体
For N = 1 To H
Print Tab(20 + Abs(H1 - N)); String$((H1 - Abs(H1 - N)) * 2 - 1, "*")
Next N
End Sub
Private Sub 退出_Click()
End
End Sub
在上面的程序中,Tab(20+Abs(H1−N))函数保证菱形图案的上半部分显示字符串的起始
位置向左移一个字符位,下半部分显示字符串的起始位置向右移一个字符位。为了分析该函
数的作用,假设有 5 行,即 H=5,H1=3。在循环中,变量 N 自动加 1。循环结束后,显示字
符串也结束。Tab(20+Abs(H1−N))函数的作用分析如表 4-5-1 所示。
表 4-5-1 Tab(20+Abs(H1 N))函数的作用分析
H H1 N H1−N Abs(H1−N) 20+Abs(H1−N)

5 3 1 2 2 22

5 3 2 1 1 21
124 中文 Visual Basic 6.0 实用教程—结构化程序设计

续表

H H1 N H1−N Abs(H1−N) 20+Abs(H1−N)

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 右图所示。

图 4-5-6 “数字菱形图案 1”程序运行后显示的图案

“数字菱形图案 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”程序运行后的效果与“数字菱形图案 1”程序运行后的效


果基本一样。在“输入行数”对话框中的文本框内输入数值 9,单击“确定”按钮,又回到
窗体,此时各个按钮均变为有效。再单击“显示数字菱形图案”按钮,即可在窗体中显示出
由数字组成的 9 行菱形图案,如图 4-5-7 左图所示。不改变“输入行数”对话框中文本框内
的数值,单击“确定”按钮,又回到窗体,此时各个按钮均变为有效。再单击“显示数字菱
形图案”按钮,即可在窗体中显示出由数字组成的 17 行菱形图案,如图 4-5-7 右图所示。

图 4-5-7 “数字菱形图案 2”程序运行后显示的图案

“数字菱形图案 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 实用教程—结构化程序设计

【实例】 “字母菱形图案”程序运行后的效果与“数字菱形图案 1”程序运行后的效果


基本一样。在“输入行数”对话框中的文本框内输入数值 9,单击“确定”按钮,又回到窗
体,此时各个按钮均变为有效。再单击“显示字母菱形图案”按钮,即可在窗体中显示出由
数字组成的 9 行菱形图案,如图 4-5-8 左图所示。不改变“输入行数”对话框中的文本框内
的数值,单击“确定”按钮,又回到窗体,此时各个按钮均变为有效。再单击“显示字母菱
形图案”按钮,即可在窗体中显示出由字母组成的 17 行菱形图案,如图 4-5-8 右图所示。

图 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 实用教程—结构化程序设计

Print Tab(5); "丁"; Mid$(N$, 6 - D * 5, 5)


End If
End If
Next D
Next C
Next B
Next A
End Sub

图 4-6-2 “猜年龄”程序运行结果 图 4-6-3 “谁第一”程序运行结果

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-1 10 进制数 215 转换为 2 进制数 图 4-7-2 10 进数 0.6875 转换为 2 进制数

(3)任意进制(N 进制)数转换为另一任意进制(M 进制)数:可将 N 进制数转换为十


进制数,再将十进制数转换为 M 进制数。

4.7.2 项目实现

1.程序运行结果和分析
“不同进制数之间的转换”程序运行后,可以实现不同进位计数制的数值之间的相互转
换。程序运行后的画面如图 4-7-3 左图所示。输入 N 和 M 进制数的数,再输入要转换的 N 进
制数原数值,然后单击“转换”按钮,即可将输入的 N 进制数原数值转换为 M 进制数值,
如图 4-7-3 右图所示。

图 4-7-3 “不同进制数之间的转换”程序运行结果

分析:用 N 表示原进制,M 表示转换后的进制,N1$表示 N 进制的数。先将 N1$由 N


进制数转换为 10 进制数,再将该 10 进制数转换为 M 进制数。在分析程序时,要考虑到 0~
9 字符的 ASCII 为 48 至 59,而 A~Z 字符的 ASCII 为 65~90,字符 A 与字符 9 的 ASCII 值
的间隔为 7。不同进位计数制的小数之间的相互转换时精度定为小数点后边 12 位。
2.程序代码
Private Sub Command1_Click()
Dim N, M, Q, L, K, I As Integer
Dim S As Double
Dim N1$, M1$, N2$, M2$, M12$
N = Val(Text1.Text)
M = Val(Text2.Text)
Label7.Caption = ""
Rem 将 N 进制数整数部分 N1$转换为 10 进制数 S
132 中文 Visual Basic 6.0 实用教程—结构化程序设计

N1$ = Text3.Text 'N 进制数的整数部分 N1$


S = 0: Q = 0: K = 1 'S 存储 10 进制数,Q 存储末一位数,K 存储位数
L = Len(N1$) 'L 存储 N1$的长度
For I = L To 1 Step -1
Q = Asc(Mid$(N1$, I, 1)) - 48 '将 N1$的一位数字转换为相应的数值
If Q > 9 Then Q = Q - 7 '当数值 Q>9 时,进行数值调整
S = S + K * Q: K = K * N '转换为 10 进制数
Next I
Rem 将 10 进制数 S 转换为 M 进制数整数部分 M1$
While S > 0 '当商为 0 时,完成 10 进制数转换为 M 进制数
Q = S - Int(S / M) * M '除以 M 取余数
If Q > 9 Then Q = Q + 7 '当数值 Q>9 时,进行数值调整
Q = Q + 48 '将数值 Q 进行数值调整,获得相应的 ASCII
M1$ = Chr(Q) + M1$ '连接 M 进制数 M1$
S = Int(S / M) '求商
Wend
M12$ = M1$ 'M 进制数的整数部分 M1$赋值给 M 进制数 M12$
Rem 将 N 进制数小数部分 N2$转换为 10 进制数 S
S = 0: Q = 0: K = 1 'S 存储 10 进制数,Q 存储末一位数,K 存储位数
N2$ = Text4.Text 'N 进制数的小数部分 N2$
L = Len(N2$) 'L 存储 N2$的长度
For I = 1 To L
Q = Asc(Mid$(N2$, I, 1)) - 48 '将 N1$的一位数字转换为相应的数值
If Q > 9 Then Q = Q - 7 '当数值 Q>9 时,进行数值调整
K = K * N: S = S + Q / K '转换为 10 进制数
Next I
Rem 将 10 进制小数 S 转换为 M 进制数小数部分 M2$
K=1 '变量 K 用来控制 M 进制数的小数位数
While K <= 12 '当商为 0 时,完成 10 进制数转换为 M 进制数
Q = Int(S * M) '乘以 M 取整数
If Q > 9 Then Q = Q + 7 '当数值 Q>9 时,进行数值调整
Q = Q + 48 '将数值 Q 进行数值调整,获得相应的 ASCII
M2$ = M2$ + Chr(Q) '连接 M 进制数 M1$
S = S * M - Int(S * M) '求 S * M 的余数
K=K+1 '变量 K 自动加 1
Wend
M12$ = M1$ + "." + M2$ 'M 进制数的整数和小数部分连接后赋值给 M 进制数 M12$
Label7.Caption = M12$ 'M 进制数数 M12$赋给标签 Label7
End Sub

4.7.3 项目拓展

1.
“最大素数的后 8 位数”程序
【实例】 1984 年时已知的最大素数是 2 的 86243 次方减 1。编写程序求该数的最后 8 位
数字,同时判断这 8 位数字是否是素数。286243−1 超出计算机允许的精确数值的范围,为了显
示 286243−1 的最后 8 位数字,就不能直接计算 286243 数值,可以创建一个循环,乘 86243 次 2,
第4章 优化算法和程序设计方法 133

而且只乘它的后 8 位数字。该程序如下。程序运行结果如图 4-7-4 所示。


Private Sub Form_Activate()
Dim N, M As Long
Dim L, S As Integer
M=1
For N = 1 To 86243
M=M*2
If M >= 100000000 Then
M = M - Int(M / 100000000) * 100000000
End If
Next N
Print "最大的素数 2 的 86243 次方减 1 的后 8 位数是:"; M – 1:Print
L=0
For S = 2 To Sqr(M) '依次用 M 除以 2 到 SQR(M)之间的自然数
If M Mod S = 0 Then L = 1: Exit For '如果能够整除,则给 L 赋 1,并退出循环
Next S
If L = 0 Then '如果 L=1 表示不是质数,变量 L=1 表示不是质数
Print M – 1;"是素数!", '如果 L=0,则显示是素数信息
Else
Print M – 1;"不是素数!", '如果 L=1,则显示不是素数信息
End If
End Sub 程序运行结果是:最大的素数 2 的 86243 次方减 1 的后 8 为数是:33438207。

2.“挑出最大的数和最小的数”程序
【实例】 “挑出最大的数和最小的数”程序运行后,会产生 40 个随机的两位数字,同
时在屏幕上按照一行 8 个数字显示出来,每个数字的左边还标出它出现的位置号码。最后,
显示出这 40 个数字中最大和最小的数字,以及它们第一次出现的位置。“挑出最大的数和最
小的数”程序如下。程序运行后的画面如图 4-7-5 所示。

图 4-7-4 程序的运行结果 图 4-7-5 “挑出最大的数和最小的数”程序运行结果

在程序中,变量 I 用来保存数字的序号,因为变量 I 的初值为 0,所以数字的序号是 I+1;


变量 N 用来保存随机的两位数字,当该数字用 Str$函数转换为字符串式,其右边会有一个空
格,为了删除该空格,使用了 Ltrim$函数;变量 MAX 用来保存最大的数字,变量 MIN 用来
保存最小的数字,变量 MAXW 用来保存最大数字的序号,变量 MINW 用来保存最小数字的
序号。变量 S$用来保存空串或一个 0,其目的是为了使一位和两位数字都能够上下对齐显示,
在显示一位数字时,在它的左边加入一个 0;在显示两位数字时,在它的左边加入一个空串。
134 中文 Visual Basic 6.0 实用教程—结构化程序设计

挑选最大的数字所采用的方法是:一开始将变量 MAX 赋给比一组数中最小的数还要小


的一个数字(例如 0),然后在每次产生新的数字时,都和变量 MAX 和新产生的数字 N 进行
比较,如果,N 比 MAX 大,则将 N 的值赋给 MAX。同时,为了保存该数字的序号,将变
量 I 的值赋给变量 MAXW。因为在比较时使用的是大于号,所以保存的是最大数字第一次出
现的位置(即序号);如果在比较时使用的是大于等于号,则保存的是最大数字最后一次出现
的位置(即序号)。
挑选最小的数字所采用的方法与挑选最大的数字所采用的方法一样,只是将大于号改为
小于号。
Private Sub Form_Activate()
Dim I, N, MAX, MIN, MAXW, MINW As Integer, S$
MAX = 0: MIN = 100: I = 0 '给变量赋初值
Print: Print '空两行
FontSize = 10 '设置窗体中文字的大小
ForeColor = RGB(0, 0, 255) '设置窗体中文字的颜色为蓝色
Randomize '随机种子
While I < 40 '开始循环,循环 40 次,产生 40 个随机数
N = Int(Rnd * 90) + 10 '产生随机的两位数字
S$ = "" '给变量 S$赋一个空串
If I Mod 8 = 0 Then Print: '如果一行已经显示了 8 个数字,则换行
If I < 9 Then S$ = "0" '如果是一位数字,则在文字左边加一个“0”
Print Tab((I Mod 8) * 8 + 1); S$ & LTrim$(Str(I + 1)) & ":" & LTrim$(Str(N));
If N > MAX Then MAX = N: MAXW = I + 1 '进行比较,保存最大的数字和它的序号
If N < MIN Then MIN = N: MINW = I + 1 '进行比较,保存最小的数字和它的序号
I=I+1 '数字序号自动加 1
Wend '结束循环
ForeColor = RGB(255, 0, 0) '设置窗体中文字的颜色为红色
Print: Print Tab(6); "最大的数是:"; MAX, "最大数第 1 次出现的位置是:"; MAXW
Print: Print Tab(6); "最小的数是:"; MIN, "最小数第 1 次出现的位置是:"; MINW
End Sub
3.“求一元 n 次方程的近似根”程序
【实例】 本实例是求一元 n 次(n>2)方程在某区间内
的解,区间和精度要求通过键盘输入,例如:求方程
X 3−X−1=0 在(1,2)区间内的解。某一元 n 次方程式 f (X)
在区间(X 1,X 2)中是否有解,可根据 f (X 1)*f (X 2)<0
是否成立来判断,如果 f (X 1)*f (X 2) <0,则 f (X)在(X 1,
X 2)区间内至少有一个解。求解方法如下 (参看图 4-7-6) 。
(1)取区间中点 X 3=(X 1+X 2)/2。计算 f (X 3),若 f
图 4-7-6 求一元 n 次方程的近似根
(X 1)与 f (X 3)同号,则说明解在(X 3,X 2)区间内,否则
在(X 1,X 3)区间内。
(2)重新定义新区间:若 f (X 1)*f (X 3)>0,则 X 3 代替 X 1,即(X 3,X 1)→(X 1,X 2);否
则,X 3 代替 X 2,即(X 1,X 3)→(X 1,X 2)。
(3)重复上述过程,当|X 2−X 1|≤E(E 为所要求的精度)时,X 3 为方程的解。
第4章 优化算法和程序设计方法 135

“求一元 n 次方程的近似根”程序运行后屏幕显示如图 4-7-7 左图所示,输入数据后,单


击“开始”按钮,即可算出一元 n 次方程的近似根,如图 4-7-7 右图所示。

图 4-7-7 “求一元 n 次方程的近似根”程序运行结果

在“求一元 n 次方程的近似根”程序中,使用了 1 个窗体、5 个标签、4 个文本框和两


个按钮对象。它们的名称属性均采用默认值。窗体对象的 StartUpPosition 属性设置为“2-屏
幕中间”。其他属性的设置,读者可参考图 4-7-7 自行设置。
“求一元 n 次方程的近似根”程序代码如下。
Private Sub Command1_Click()
Dim X1, X2, X3, E As Double
FontSize = 12
E = Val(Text1.Text)
X1 = Val(Text2.Text):X2 = Val(Text4.Text)
While Abs(X2 - X1) > E
X3 = (X1 + X2) / 2
If (X1 * X1 * X1 - X1 - 1) * (X3 * X3 * X3 - X3 - 1) > 0 Then
X1 = X3
Else
X2 = X3
End If
Wend
Text4.Text = (X1 + X2) / 2
End Sub
Private Sub Command2_Click()
End
End Sub
4.“50 位精确加法计算”程序
【实例】 双精度型常量的最大有效数位数是 15,如果输入的数据超过 15 位,将得不到
精确的数值。本实例采用程序的方法,进行超过 15 位的精确加法运算,而且用竖式表示出来。
“50 位精确加法计算”程序的设计思想是将数字解决不了的问题转换成字符来解决,数
据的输入可采用字符串形式输入,用字符串变量 A$、B$、C$分别存放加数、被加数与和数。
每次计算从 A$与 B$中取相同位的字符,转换为数值后再进行加法运算,运算时也要考虑进
位,其和存入 C$中。
程序运行后的屏幕显示如图 4-7-8 所示。在文本框中输入加数和被加数后,单击“计算”
136 中文 Visual Basic 6.0 实用教程—结构化程序设计

按钮,即可精确计算出它们的和,如图 4-7-9 所示。在输入加数和被加数时,它们的位数可以


不一样,最多可输入 50 位数,如要输入更多的位数,需要将 3 个文本框的水平宽度加大即可。

图 4-7-8 “50 位精确加法计算”程序运行起始画面 图 4-7-9 “50 位精确加法计算”程序的计算结果

程序中使用的对象有:1 个窗体、4 个标签、3 个文本框和 3 个按钮,它们的名称属性均


采用默认值。另外,单击选中工具箱中的 Line(线)控件,再在窗体中绘制一条水平直线,
在其“属性”窗口中,设置线粗细(BorderWidth=3)和线颜色(BorderColor 为紫色),如图
4-7-8 所示。窗体对象的 StartUpPosition 属性设置为“2-屏幕中间”。程序如下。
Private Sub Command1_Click()
Dim L1, L2, L, N, I, A, B, C As Integer
Dim A1$, B1$, C1$
A1$ = Text1.Text: B1$ = Text2.Text '将加数和被加数分别赋给 A1$和 B1$
L1=Len(A1$) '将加数 A1$的长度赋给变量 L
L2 = Len(B1$) '将被加数 B1$的长度赋给变量 L2
If L1 > L2 Then '使加数和被加数的长度一样(用左边加空格来补齐)
L = L1
B1$ = Space(L1 - L2) + B1$
Else
L = L2
A1$ = Space(L2 - L1) + A1$
End If
N=0
For I = 1 To L
Rem 每次循环截取一位数字,进行加法计算
A = Val(Mid$(A1$, L - I + 1, 1)): B = Val(Mid$(B1$, L - I + 1, 1))
C =A+B +N
Rem 如果有近位,给变量 N 赋 1
If C > 9 Then C = C - 10: N = 1 Else N = 0
C1$ = Right$(Str$(C), 1) + C1$ '将计算的和连接到和字符串 C$的左边
Next I
If N <> O Then
C1$ = Right$(Str$(N), 1) + C1$ '最高一位补加进位
End If
Text4.Text = C1$ '将计算的和字符串 C$赋给文本框 TEXT1
End Sub
Private Sub Command2_Click()
Text1.Text = ""
Text2.Text = ""
第4章 优化算法和程序设计方法 137

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 实用教程—结构化程序设计

9=3+3+3,15=3+5+7,21=3+5+13。编写程序,将 201 到 251 之间的所有奇数表示成三个素


数的和。编写程序解决该问题。
π 1 1 1 1 1 1
9.根据公式 = 1− + − + − +Λ − ,求π的近似值,精确到单项的绝对
4 3 5 7 9 11 2* n −1
值小于 0.000001。编写程序解决该问题。
10.一个六位数,用 2、3、4、5、6 分别乘该数后,得到的 5 个乘积都是一个六位数,
而且是由原来六个数字组成,只是顺序改变了。编写程序求该数。
11.甲、乙、丙三人各有若干个豆粒,互相赠送,先由甲给乙和丙,所给的豆数分别等
于乙、丙原有的豆数;再由乙给甲和丙,所给的豆数分别等于甲、丙现有的豆数;最后由丙
给甲和乙,所给的豆数分别等于甲、乙现有的豆数。互送完后,每人都有 16 粒豆。编写程序
求三人原有的豆数。
12.编写程序,求 2100 的后 8 位数字。
13.有甲、乙两堆棋子,甲堆比乙堆多,从甲堆取出与乙堆中棋子一样多的棋子放入乙
堆中,再从乙堆取出与甲堆中所剩棋子一样多的棋子放入甲堆中,最后再从甲堆中取出与乙
堆中所剩的棋子一样多的棋子放入乙堆中。这时,甲堆有 16 个棋子,乙堆有 24 个棋子,求
甲、乙两堆棋子原各有多少粒。编写程序解决该问题。
14.大数学家欧拉提出下面的问题:一头猪卖 3.5 个银币,一头山羊卖 1.5 个银币,一
头绵羊卖 0.5 个银币,有人用 100 枚银币买了 100 头牲畜。编程计算,他买了猪、山羊、绵
羊各多少只。
15.某工厂 2004 年年总产值为 500 万元,当年总增长率分别为 15%、10%、8%、5%
时,编写程序,计算多少年后该厂年总产值能翻一番。
16.我国现有人口 13 亿,编程计算当人口自然增长率按每年 1%、0.5%、0.2%、0.1%、
0.05%、0.02%时,多少年后我国人口增加到 15 亿。编写程序解决该问题。
17.如果一个三位数等于它每一位数的立方和,则此数称为水仙花数,如 153=13+53+33。
编写程序,显示所有的水仙花数。
18.编程显示一个用“*”组成的正弦波波形。
19.从 0、1、2、3、4 中取两个数字作为千位和百位数,从 5、6、7、8 中取两个数字作为
十位和个位数,要求百位数小于千位数,个位数小于十位数。编程显示符合上述要求的四位数。
20.在 50~200 的正整数中,有多少个数可以表示成几个连续正整数的积?只取一种表示
法,例如 120=6·5·4 或 120=5·4·3·2 中取一种即可。编写程序,显示这些数以及连续
相乘的几个正整数。
21.把六本不同的书中的两本借给同学,有多少种借法? 编写程序,显示不同的借法和
总数。
22.一个自然数是素数,且它的数字位置任意对换后形成的数仍为素数,这种数叫绝对
素数,例如 37。编写程序,显示 100 以内的所有绝对素数。
23.有算式 ABCD
−) CDC
ABC
其中,A、B、C、D 是正整数,编写程序,求出 A、B、C、D 几个数。
第4章 优化算法和程序设计方法 139

24.编写一个能求 4 个数的最大公约数与最小公倍数的程序。
25.如果一个数从左边读和从右边读都是同一个数,则该数叫回文数,例如 787 是一个
回文数。编程显示出 1000 以内所有既是回文数又是素数的自然数。
26.可以将文本框中的英文大写字母改成小写字母,将英文小写字母改成大写字母,并
在另一个文本框中显示出来的程序。
27.由用户输入行数,然后显示由字符组成的等腰梯形图案。编写程序解决该问题。
28.编写一个可以显示 4 种不同的字母菱形图案的程序。程序运行后,单击“输入行数”
按钮,可调出“输入行数”对话框,在该对话框内的文本框中输入行数后,再单击不同的按
钮,可以显示不同类型的字母菱形图案。几种字母组成的字母菱形图案如图 4-1 所示。

28 题图 1 28 题图 2

图 4-1 28 题图

29.使用循环语句,编写可以显示如图 4-2 所示图案(输入 17 行时)的程序,编写可以


显示如图 4-3 所示图案(输入 19 行时)的程序。

图 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 定义常规数组

在 Visual Basic 中,根据数组占用内存的方式,可以将数组分为常规数组和动态数组两


种类型。常规数组是数组元素个数不可改变的数组,动态数组是数组元素个数可以改变的数
组。数组的下标变量一定要在定义了数组后才可以使用。
1.创建常规数组
常规数组是大小固定的数组,也就是说常规数组中包含的数组元素的个数不变,它总是
保持同样的大小,占有的存储空间也保持不变。
创建常规数组也叫定义数组或说明数组。定义数组语句的格式及功能如下。
【格式】Dim 数组名 [(维数定义)][As 数据类型]……
【功能】创建常规数组,它的名称由“数组名”给出,维数由“维数定义” ,数据类型由
“数据类型”给出。数组名的命名与变量的命名方法一样。可同时定义多个不同维数的数组。
【说明】
① 维数定义:下标变量中的下标个数称为数组的维数,当它被省略时是创建了一个无
下标的空数组。维数定义的格式如下:
[下界 1 To] 上界 1 [,[下界 2 To] 上界 2]……
其中,一组[下界 To 上界 ]即定义了一维,有几项[下界 To 上界]即定义了几维数组。[下
界]和[上界]表示该维的最小和最大下标值,通过关键字 To 连接起来代表下标的取值范围。
下界和关键字 To 可以省略,省略后则等效于[0 To 上界],即下标的下界默认值为 0。下界和
上界可以使用数值常量或符号常量。
② 数据类型:用来定义数组下标变量的数据类型,可以定义所有数据类型。当它省略
后,则相当于定义了一个变体(Variant)数据类型。
③ Dim 语句本身不具备再定义功能,即不能直接使用 Dim 语句对已经定义了的数组进
行再定义。Dim 能够定义说明数组,分配数组存储空间。数组元素在未经赋值前, 数值型
数组元素值为零,字符型数组的元素值为空字符串。
例如:Dim Data(20) As Integer 语句定义了一个名称为 Data 的整型数组,它有 21 个元素:
Data(0),Data(1),…,Data(20);
Dim Number(5 To 20) As Double 语句定义了一个名称为 Number 的双精度型数组,它有
16 个元素:Number(5),Number(6),…,Number(20);
Dim M(2,3 To 5) As Integer 语句定义了一个名称为 M 的二维整型数组, 它有 3×3 个元素:
M(0,3)、M(0,4)、M(0,5)、M(1,3)、M(1,4)、M(1,5)、M(2,3)、M(2,4)、M(2,5)。
④ 可以在一个数组中包含其他已经定义过的数组,被包含的数组类型一般应与该数组
类型一样,但如果是变体型数组除外。
⑤ 使用 Option Base n 语句可以重新设定数组的下界,其中 n 为 0 或正整数,表示数组
下界的数值。
⑥ 使用下标变量时,可以完全像使用简单变量那样进行赋值和读取,下标变量的下标
可以是常量、变量和数值型表达式(长整型数据)。
2.创建动态数组
对于动态数组,只有在程序的执行过程中才给数组开辟存储空间,在程序未运行时,动
第5章 数组和数据结构基础 143

态数组不占用内存,可以将这部分存储空间移作他用。当不需要动态数组时,还可以用 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 所示,要求输入候选人的选号。

图 5-1-1 程序运行后的起始画面 图 5-1-2 输入候选人号码

输入选号后,按回车键或单击“确定”
按钮,又弹出该对话框,再输入候选人的选
号,按回车键或单击“确定”按钮,如此不
断。选举完成后,输入小于等于 0 或大于候
选人个数的数值,按回车键或单击“确定”
图 5-1-3 票数统计结果 按钮,即可显示所有候选人的票数,如图
5-1-3 所示。
2.“选举程序”程序代码
“选举程序”程序代码中,使用了数组 P 来保存各候选人的选票数,一共有 N 个候选
144 中文 Visual Basic 6.0 实用教程—结构化程序设计

人,因此定义一个数组 P(N),它有 N+1 个下标变量 P(0),P(2),…,P(N),分别用来保存


候选人的选票数。定义数组 P(N)使用的语句是:ReDim P(N) As Integer ,它的数据类型是
整型数据。用来统计选票的语句是:P(L) = P(L) + 1。如果要增加候选人,不用修改程序,
这与用简单变量编写的程序有本质的区别,可充分体现出使用数组的优势。“选举程序”
程序代码如下。
Private Sub Form_Activate( )
Dim N, L, S As Integer '声明变量 N 和 R 是整型变量
N = Val(InputBox("请输入候选人的个数", "候选人个数", 10))
ReDim P(N) As Integer '定义一个动态数组 P,数组元素个数为 N+1
L = 1: Print: Print '变量 L 赋初值,以保证进入循环体,再换行两次
Do While L > 0 And L <= N
L = Val(InputBox("请选举人输入候选人的选号", "选举投票", 0))
If L > 0 And L <= N Then '如果是合法选票,则进行统计
P(L) = P(L) + 1 '统计各候选人的选票
End If
Loop
For L = 1 To N '定位显示所有候选人的票数
Print Tab(((L - 1) Mod 2) * 35 + 2); "第" & Str(L) & "个候选人的票数是:"; P(L);
If L Mod 2 = 0 Then Print '一行显示两个候选人的票数后换行
Next L
End Sub

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-4 输入一维数组的元素个数 图 5-1-5 输入一维数组元素的数据


第5章 数组和数据结构基础 145

图 5-1-6 显示一维数组数据

Private Sub Form_Activate( )


Dim N, I, L As Integer '声明变量 N 和 R 是整型变量
N = Val(InputBox("请输入一维数组的元素个数", "数组元素的个数", 10))
ReDim P(1 To N) As Integer '定义一个动态数组 P,数组元素个数为 N 个
Print: Print: Print '换行 3 次
For I = 1 To N
TS$ = "请输入第" + Str(I) + "个数据"
L = Val(InputBox(TS$, "输入数据", 0))
P(I) = L '创建数组元素的数据
Next I
For I = 1 To N '确定数组号码
Print Tab(((I - 1) Mod 4) * 25 + 2); "P" & "(" & Format(I) & ")=:"; P(I);
If I Mod 4 = 0 Then Print '一行显示 4 个数据后换行
Next I
End Sub

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-1-7 输入二维数组的行数 图 5-1-8 输入二维数组的列数


146 中文 Visual Basic 6.0 实用教程—结构化程序设计

图 5-1-9 输入二维数组的数据 图 5-1-10 显示二维数组数据

Private Sub Form_Activate( )


Dim N, I, L As Integer '声明变量 N 和 R 是整型变量
H = Val(InputBox("请输入二维数组的行数", "数组的行数", 10))
L = Val(InputBox("请输入二维数组的列数", "数组的列数", 10))
ReDim P(1 To H, 1 To L) As Integer '定义一个动态二维数组 P
Rem 显示二维数组的数据
For I = 1 To H '确定数组行号
For J = 1 To L '确定数组列号
TS$ = "请输入第" + Str(I) + "行" + "第" + Str(J) + "的数据"
SJ = Val(InputBox(TS$, "输入数据", 0))
P(I, J) = SJ '创建二维数组元素的数据
Next J
Next I
Rem 显示二维数组的数据
Print: Print: Print '换行 3 次
For I = 1 To H '确定数组行号
For J = 1 To L '确定数组列号
Print Tab(((J-1) Mod 5)*20+2);"P"&"(" & Format(I) & "," & Format(J) & ")=:";P(I,J);
Next J
Print: Print '换行 2 次
Next I
End Sub

5.2 改变二维数组

5.2.1 For Each Next 循环语句和数组函数

1.For Each Next循环语句


For Each Next 循环语句与 For Next 循环语句类似,它是对数组中的每一个数组元素重复
执行同一组语句序列。如果不知道一个数组中有多少个数组元素,使用 For Each Next 语句是
非常方便的。
【格式】For Each 变量 In 数组
[循环体语句序列]
Next [变量]
【功能】变量每取数组中的一个元素,都重复执行关键字 For Each 和 Next 之间的循环
语句序列。在循环语句序列中可以使用“Exit For”语句。
第5章 数组和数据结构基础 147

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-2 改变二维数组

Dim A, B, K As Integer '声明三个整型变量 A、B 和 K


Dim N( ) As Integer '声明一个空整型数组 N
Private Sub Form_Activate( )
FontSize = 12 '设置文字大小
ForeColor = RGB(0, 0, 255) '设置文字颜色为蓝色
FontBold = True '设置文字为粗体
ReDim N(3, 1) As Integer '声明一个动态整型二维数组 N
Rem 给数组 N 赋值
Randomize
For I = 0 To 3
For J = 0 To 1
K = Int(Rnd * 90 + 10) '产生随机的两位数
N(I, J) = K '给数组元素赋初值
Next J
Next I
End Sub
Private Sub Command1_Click( )
Rem 输出动态整型二维数组 N 的所有数组元素的值
Print: Print
For I = 0 To 3
For J = 0 To 1
Print "(" + Str$(I) + "," + Str$(J) + ")=" + Str$(N(I, J)) + Space(3);
Next J
Print
Next I
第5章 数组和数据结构基础 149

Command1.Enabled = False '使"显示数组"按钮无效


End Sub
Private Sub Command2_Click( )
ReDim Preserve N(3, 3) As Integer '改变数组的大小,同时保留原数据
Rem 输出动态整型二维数组 N 的所有数组元素的值
Print
For I = 0 To 3
For J = 0 To 3
Print "("+Str$(I)+","+Str$(J)+")="+Str$(N(I, B))+Space(3);'输出二维数组
Next J
Print
Next I
Command2.Enabled = False '使"改变数组"按钮无效
End Sub
Private Sub Command3_Click( )
ReDim N(3) As Integer '改变数组的大小,同时不保留原数据
Print
For Each I In N '一维数组循环
Print N(I); " "; '输出一维数组元素的值
Next I
Command3.Enabled = False '使"清除数组"按钮无效
End Sub
Private Sub Command4_Click( )
End
End Sub

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

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(6 - A, B) + Space(3);
Next B
Print:
Next A
End Sub
Private Sub Command2_Click(Index As Integer)
End
End Sub
3.“矩阵列颠倒”程序
【实例】 “矩阵列颠倒”程序运行后的画面如图 5-2-3 左图所示。
单击“矩阵列颠倒”按钮后,可以在窗体内显示
出矩阵列颠倒后的数据(即第 1 列数据变为第 5 列数
据,第 2 列数据变为第 4 列数据……第 5 列数据变为
第 1 列数据)的变换效果,如图 5-2-5 所示。
“矩阵列颠倒”程序代码如下。注意:矩阵列颠
倒的关键是显示矩阵时,使用的是 Print N(A, B)语句;
显示列颠倒后的矩阵时,使用的是 Print N(A, 6 - B)
语句。 图 5-2-5 “矩阵列颠倒”程序运行后的画面

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 实用教程—结构化程序设计

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(A, 6 - B) + Space(3);
Next B
Print
Next A
End Sub
Private Sub Command2_Click(Index As Integer)
End
End Sub

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

曹永东(caoyongdong) 65789891 曹永东(caoyongdong) 65789891

安辉乔(anhuiqiao) 85432341 李键友(lijianyou) 69871234

李键友(lijianyou) 69871234 王 强(wangqiang) 63390843

赵晓红(zhaoxiaohong) 63387302 赵晓红(zhaoxiaohong) 63387302

…… …… …… ……

在这个例子中,为了提高查找效率,必须了解待处理对象之间的关系,以及如何存储和
表示这些数据。表 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 通讯录表
编 号 姓 名 性 别 电 话 号 码 手 机 号 码 邮 编 地 址

1 王泽 男 63390823 13681387100 100051 广外大街 201 号

2 李志勇 男 68893215 13781367210 100061 宣外大街 2 号楼 601 号

3 赵明元 男 56789232 13881397310 100510 珠市口大街 809 号

4 李慧芳 女 64487345 13986587110 202028 西藏大街 3 号楼 906 号

…… …… …… …… …… …… ……

一般情况下,一组数据元素并不是杂乱无章的,而是具有某种结构形式。这里,结构形
式是指数据元素间的相互关系,这种相互关系可以用对数据元素的一些运算来表示。
(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
……

所示。其中,l 表示每个数据元素占 l 个单元,内存中的首


地址为 adr(ai)。因此,线性表中第 i 个元素的存储地址为
an–1 adr(ai)=adr(a1)+(i−1)*l 。
an 这种存储结构只要知道元素序号就很容易找到第 i 个
图 5-3-1 存储线性表在内存中的存放形式 数据元素,且无论序号 i 为何值,找到第 i 个元素所需的时
间相同。故这种存储结构亦称为随机存储结构。

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

图 5-3-3 线性表插入 00 的过程

(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

a1 a2 … ai–1 ai+1 … an–1 an

图 5-3-4 线性表中删除第 i 个元素的过程

图 5-3-5 显示了对长度为 9 的线性表(11,22,33,44,55,66,77,88,99)要删除


第 5 个元素 55 的过程。

11 22 33 44 55 66 77 88 99

11 22 33 44 66 77 88 99

图 5-3-5 删除线性表中第 5 个数据 55 的过程

2.“线性表插入数据”程序设计
“线性表插入数据”程序运行后的画面如图 5-3-6 所示,可以看到在窗体内显示出线性
表(11,22,33,44,55,66,77,88,99)。单击“插入数据”按钮后,即可调出“确定位
158 中文 Visual Basic 6.0 实用教程—结构化程序设计

置”对话框,输入要插入数据的位置号(此处输入 5)后,单击“确定”按钮,又可调出“确
定数据”对话框,输入要插入的数据(此处为 00),再单击“确定”按钮,即可在原数据的
下边显示插入数据后的线性表效果,如图 5-3-7 所示。

图 5-3-6 “线性表插入数据”程序运行结果 图 5-3-7 在 5 号位置插入“00”

重复上述操作,分别再在 5 号位置插入“AA”、“BB”,在 7 号位置插入“CC”,在 8 号


位置插入“DD”,最终效果如图 5-3-8 所示。
“线性表插入数据”程序代码如下。
Dim I, N As Integer
Dim P( ) As String '定义一个空数组 P
Rem 产生线性表和显示线性表
Private Sub Form_Activate( )
ReDim P(1 To 9) As String '定义一个动态数组 P,数组的元素个数为 9
FontSize = 12
ForeColor = RGB(0, 0, 255)
Print: Print: Print: Print
Rem 显示线性表上边的表头序号,控制各序号之间的空格个数
For N = 1 To 16
If N < 10 Then
Print LTrim$(Str(N)); " ";
Else
Print LTrim$(Str(N)); " ";
End If
Next N : Print
Rem 显示线性表
For N = 1 To 9
Q$ = LTrim$(Str(N))
P(N) = Q$ + Q$
Print P(N) + " ";
Next N
Print
End Sub
Rem 在线性表中插入数据
Private Sub Command1_Click( )
I = Val(InputBox("请输入要插入数据的位置", "位置数是:", 5))
S$ = InputBox("请输入要插入的数据", "插入的数据是:", "00")
ReDim Preserve P(1 To UBound(P, 1) + 1) As String '将数组 P 的元素个数增加 1
Rem 在线性表中将第 n 个元素到第 i+1 个元素向后移一位
第5章 数组和数据结构基础 159

For N = UBound(P, 1) To I + 1 Step -1


P(N) = P(N - 1)
Next N
P(I) = S$
For N = 1 To UBound(P, 1)
Print P(N) + " "; '显示新的线性表
Next N
Print
End Sub
Private Sub Command2_Click( )
End
End Sub
3.“线性表删除数据”程序设计
“线性表删除数据”程序运行后的画面如图 5-3-9 所示,可以看到在窗体内显示出线性
表(AA,BB,CC,DD,EE,FF,GG,HH,II,JJ,KK,LL,MM,NN,OO,PP)。

图 5-3-8 在其位置插入数据 图 5-3-9 “线性表删除数据”程序运行结果

单击“删除数据”按钮后,即可调出“确定位置”对话框,输入要删除数据的位置号(此
处输入 5)后,单击“确定”按钮,即可在原数据的下边显示删除数据后的线性表效果,如
图 5-3-10 所示。
重复上述操作,分别再将第 1 号位置处的“AA”,将第 10 号位置处的“LL”,将第 11
号位置处的“NN”删除,最终效果如图 5-3-11 所示。

图 5-3-10 删除第 5 号位置处的“EE” 图 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-12 “线性表数据的删除和添加”程序运行后的画面 图 5-3-13 单击“开始”按钮后的画面

图 5-3-14 “删除或添加的数据”对话框

示出来。如果删除了线性表中的数据(例如删除了 11),效果如图 5-3-15 所示。如果接着在


线性表中添加了数据(例如添加了 16),效果如图 5-3-16 所示。

图 5-3-15 删除数据后的画面 图 5-3-16 添加数据后的画面

单击“开始”按钮后,会创建一个一维数组 N,用来保存随机产生的 30 个互不相同的两


位数据。产生互不相同数的方法是在每产生一个新的随机数后,将此数字与前面产生过的数
字逐一比较,如果有相同的数据时,则重新产生新的随机数。
“线性表插入和删除”程序如下。
Dim N( ) As Integer
Dim A, I, J, BJ As Integer
Rem 开始时创建一个有 30 个数据元素的数组
Private Sub Form_Activate( )
ReDim Preserve N(1 To 30) As Integer
End Sub
Rem 显示一个有 30 个数据元素的线性表
Private Sub Command1_Click( )
ReDim Preserve N(1 To UBound(N, 1)) As Integer
Cls
Print: Print
Rem 创建 30 个互不相同的随机两位数
Randomize
162 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 “显示杨辉三角形”程序运行结果

杨辉三角形的特点是:第一行为 1,以后各行的第一个和最后一个数字为 1,其余各数


等于它上一行左上边和右上边的两个数之和。可以认为第一行 1 的两边的数据为 0,其他各
行中左边 1 的左边的数据为 0,右边 1 的右边的数据为 0。
在编写程序时,可将杨辉三角形各位置上的数赋给一个二维数 A,第一个下标表示行数,
第二个下标表示该行第几个数字。因此,从第二行开始,各行非 1 的数可利用 A(1,J)=A(I−1,
J−1)+A(I−1,J)式子获得。显示杨辉三角形的关键是如何定位每一行数据的显示位置,这是
由下边的语句来完成。其中,Tab(65−4 * I + 8 * (J−1))用来定位,其中的数值可以通过程序调
试来确定。
Print Tab(65 - 4 * I + 8 * (J - 1)); LTrim$(Str$(A(I, J)));
如果要显示更多的行数,可以通过增大窗体,以及调整显示数据的位置来实现。
“显示杨辉三角形”程序代码如下。
Dim A( ) As Integer
Dim N, I, J As Integer '声明各变量
Rem 创建和显示杨辉三角形
Private Sub Form_Activate( )
N = Val(InputBox("请输入杨辉三角形的行数(1-15)", "输入行数", 15))
ReDim A(N, N) As Integer '定义一个动态一维数组
Cls
Print: Print: Print
A(1, 1) = 1 '赋初值
Rem 创建杨辉三角形数据
For I = 2 To N
For J = 1 To I
A(I, J) = A(I - 1, J - 1) + A(I - 1, J) '求杨辉三角形数据
Next J
Next I
Rem 显示杨辉三角形
For I = 1 To N
164 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 4 52 36 18 29 40 N(2)与 N(4)互换

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 实用教程—结构化程序设计

每个数 N(I+1)到最后的数据元素 N(5)进行比较,如果 N(I)小,也不进行换位操作,仅记下比


N(I)大的数的序号。一轮比较完后,找到最大数的序号,然后再与 N(I)进行一次的换位。例
如:N(1)分别与 N(2)到 N(5)数据元素进行比较,N(1)=18 比 N(3)=52 小,记下 N(3)的序号 3,
一轮比较完后,再将 N(1)与 N(3)数据元素互换,使 N(1)=52 和 N(3)=18。在相应的程序中,
需要使用一个变量(例如:MAXS)来保存比 N(I)大的数据元素,以及使用一个变量(例如:
MAXH)来保存比 N(I)大的数据元素的序号。
3.冒泡排序法
冒泡排序(升序排序)是每一次只进行相邻两个数据比较,较大数据每次只向上移动一
位,逐步升到顶部,就像气泡逐渐上升一样。这种排序方法的做法是:先将序列的第 1 个数
据元素和第 2 个数据元素比较,若前者大于后者,则两个元素交换位置。然后第 2 个数据元
素与第 3 个数据元素比较,第 3 个数据元素与第 4 个数据元素比较,直到第 n−1 个数据元素
与第 n 个数据元素比较。每次比较之后,大的向前换,小的向后换,第一轮排序之后,最大
的数据元素定位在第 n 个数据元素所在的位置处。第二轮从第 1 个元素到第 n−1 个元素相邻
的两两比较,仍然是把较大的向后交换。第二轮排序之后,第 2 大的数据元素移到了第 n−1
数据元素的位置上。第 n−1 轮排序时,只需第 1 个数据元素与第 2 个数据元素比较。冒泡排
序经 n−1 轮排序操作,获得了升序的序列。
在某一轮排序中,如果两两比较之后,不需做元素交换,则表明序列已经排列好了,没
有必要再进行后面的各轮排序了。为此,可以设置一个变量 BS 用于标志,在某轮排序之前,
令变量 BS 为 False。在本轮排序中只要出现了数据元素交换,就将 BS 的值改为 True,并表
明有必要进行下一轮的排序。有了这个标志,就可随时监视序列是否已排序好。如果开始时
线性表中的数据元素已经按降序或升序排序好了,只需作 n−1 次比较,就结束排序。如果排
序中每一轮都有数据元素交换,则要做(n−1)+(n−2)+…+2+1=n(n−1)/2 次比较。一般情况下,
冒泡排序的比较次数在 n−1 至 n(n−1)/2 次之间。前面的选择排序,不论序列的初始状态如何,
都要作 n(n−1)/2 次比较。尽管冒泡排序算法与选择排序算法的时间复杂度是一样的,但从实
用效果看,冒泡排序法要好一些。
假设有一个数组 N 中的 5 个数据元素 N(1)=49、N(2)=36、N(3)=52、N(4)=19,N(5)=28
进行升序排序,按照冒泡排序法排序的过程如表 5-4-2 所示。
表 5-4-2 冒泡排序法排序过程(从小到大升序排序)
第一轮 第二轮 第三轮 第四轮
次数 开 1 2 3 4 5 6 7 8 9 10
I=5 I=5 I=5 I=5 I=4 I=4 I=4 I=3 I=3 I=2
变量 始 J=2 J=3 J=4 J=5 J=2 J=3 J=4 J=2 J=3 J=2
N(5) 28 28 28 28 52 52 52 52 52 52 52
N(4) 19 19 19 52 28 28 28 49 49 49 49
N(3) 52 52 52 19 19 19 49 28 28 36 36
N(2) 36 49 49 49 49 49 19 19 36 28 28
N(1) 49 36 36 36 36 36 36 36 19 19 19
注:每一次均是 N(J)与 N(J−1)两项比较,如果 N(J)>N(J-1),则相互换位。外循环变量为 I,其初值为 5,内循环变量为 J,
其初值为 2。外循环变量 I 用来确定每一轮中变量 J 取值的终值 I,每次比较后变量 J 取值加 1,直到 I 为止;每轮过后,变量 I
取值减 1,直到变量 I 取值为 2 止。
第5章 数组和数据结构基础 167

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

N(MAXH) = N(I): N(I) = MAXS


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
3.“冒泡排序”程序
【实例】 “冒泡排序”程序运行后,依
次单击窗体中的按钮后,即可在窗体中分三
行显示一个线性表的 30 个数据元素,再分三
行按从小到大升序排序显示线性表中的 30 个
数据元素,分三行按从大到小降序排序显示
线性表中的 30 个数据元素,如图 5-4-3 所示。
窗体中的按钮从上到下,其名称分别为
图 5-4-3 “冒泡排序”程序运行后的画面
Command1 到 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
172 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 = 30 To 2 Step -1
For J = 2 To I
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
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 30 To 2 Step -1
For J = 2 To I
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

5.4.4 项目拓展

1.
“穿梭排序”程序
【实例】 “穿梭排序”程序运行后,依次单击窗体中的按钮后,即可在窗体中分三行
第5章 数组和数据结构基础 173

显示一个线性表的 30 个数据元素,再分三行按从小到大升序排序显示线性表中的 30 个数据


元素,分三行按从大到小降序排序显示线性表中的 30 个数据元素,如图 5-4-4 所示。

图 5-4-4 “穿梭排序”程序运行后的画面

窗体中的按钮从上到下,其名称分别为 Command1 到 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
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 = 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
174 中文 Visual Basic 6.0 实用教程—结构化程序设计

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

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 30
Q=1
For J = 1 To 30
If N(I) > N(J) Then '如果 N(I) > N(J),则用变量 Q 统计个数
Q=Q+1
End If
Next J
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
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 1 To 30
Q=1
For J = 1 To 30
If N(I) < N(J) Then '如果 N(I) < N(J),则用变量 Q 统计个数
Q=Q+1
End If
Next J
176 中文 Visual Basic 6.0 实用教程—结构化程序设计

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

If I Mod 10 = 0 Then Print


Next I
Print
End Sub
Rem 将 30 个互不相同的随机两位数按照从小到大升序排序
Private Sub Command2_Click( )
For I = 1 To 30
MINS = N(I): MINH = I
For J = 1 To 30
If MINS > N(J) Then '如果 MINS > N(J),则保存小的数和它的序号
MINS = N(J): MINH = J
End If
Next J
M(I) = MINS: N(MINH) = 100
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
Rem 将 30 个互不相同的随机两位数按照从大到小降序排序
Private Sub Command3_Click( )
For I = 1 To 30
MAXS = S(I): MAXH = I
For J = 1 To 30
If MAXS < S(J) Then '如果 MAXS < N(J),则保存、大的数和它的序号
MAXS = S(J): MAXH = J
End If
Next J
M(I) = MAXS: S(MAXH) = 0
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
178 中文 Visual Basic 6.0 实用教程—结构化程序设计

思考与练习

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 实用教程—结构化程序设计

Private Sub Form_Activate( )


For I = 1 To 5
For J = 1 To 5
N(I, J) = LTrim$(Str$(I)) + LTrim$(Str$(J))
If I = J Then N(I, J) = "00"
Print N(I, J); " ";
Next J
Print
Next I
Print: Print
For I = 5 To 1 Step -1
For J = 1 To 5
Print N(6 - I, 6 - J); " ";
Next J
Print
Next I
End Sub
(6)程序 6
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))
If I <> 6 - J Then N(I, J) = "00"
Print N(I, J); " ";
Next J
Print
Next I
Print: Print
For I = 5 To 1 Step -1
For J = 1 To 5
Print N(J, 6 - I); " ";
Next J
Print
Next I
End Sub

3.根据下面的要求编写 Visual Basic 程序


(1)使用数组,编写一个“学分统计”程序。该程序运行后,要求用户输入多个学生的
数学成绩,再进行累加统计,然后显示他们的数学总分、平均分、最低分和最高分。要求平
均成绩四舍五入保留一位小数。
(2)修改本章中的选举程序,使它具有边输入候选人的号码,边显示每个候选人的票数。
(3)编写一个程序,该程序运行后,将两个 5×5 矩阵的对应元素相加,再获得一个新的
5×5 矩阵。
第5章 数组和数据结构基础 181

(4)编写一个程序,该程序运行后,随机产生一组互不相同的两位随机整数,然后两次
通过键盘输入两个两位整数,如果输入的数据与数组中的数据相同,则删除数组中的相应数
据,如果输入的数据与数组中的所有数据均不相同,则在数组的最后插入不相等的数据。
(5)某班第 1 小组学生的期末考试成绩如下表所示。编写程序,输入学生的学号、姓名
和各科成绩,并保存在二维数组 N 中。然后,统计每个学生的总分和平均分,再按照总分从
大到小排序显示出每个学生的学号、姓名、各科成绩、总分和平均分。
学 习 成 绩
学 号 姓 名
数 学 语 文 外 语 物 理

001 张颖 70 68 89 93

002 李华清 77 88 99 100

003 沈芳盈 100 98 99 100

004 丰金茹 98 89 100 98

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-1 在代码编辑器中输入的程序代码是用来添加一个 Sub 子过程

• Static:用来设置局部静态变量。“静态”是指在调用结束后仍保留 Sub 过程的变量值。


Static 对于在 Sub 外声明的变量不会产生影响,即使过程中也使用了这些变量名。
• Private 和 Public:用来声明该 Sub 过程是局部的(私有的)还是全局的(公有的) ,
系统缺省为 Public。
• 子过程名:它与变量名的命名规则相同,不能与 Visual Basic 中的关键字和 Windows API
函数名同名,不能与同一级别的变量重名。在同一模块中,同一名称不能既用于 Sub 过程又用于
Function 过程。一个程序只能有惟一的过程名。无论有无参数,过程名后面的( )都不可省略。
• 局部变量和常数声明:用来声明在过程中定义的变量和常数,可用 Dim 等语句声明。
• 程序段:过程执行的操作,也称为子程序语句体或过程语句体。
186 中文 Visual Basic 6.0 实用教程—结构化程序设计

• Exit Sub 语句:使执行立即从一个 Sub 过程中退出,程序接着从调用该 Sub 过程语句


的下一句继续执行。在 Sub 过程的任何位置都可以有 Exit Sub 语句。
• End Sub:用于结束本 Sub 过程。当程序执行 End Sub 语句时,退出该过程,并且立
即返回调用处,继续执行调用语句的下一句。
(2)自定义函数过程的格式和格式中各选项的含义如下:
[Static][Public|Private] Function 函数名([形参列表])[As 数据类型]
[局部变量和常数声明]
[程序段]
[函数名=表达式]
[Exit Function]
[程序段]
[函数名=表达式]
End Function
例如:如图 6-1-2 所示,在代码编辑器中输入的程序代码用来添加一个自定义函数过程。
其中,函数名为 HSMC,函数值的数据类型为 Integer,函数的形参为 A 和 B,返回值的数据
类型也为 Integer。

图 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 所示。

图 6-1-4 Sub 子过程 图 6-1-5 函数过程


188 中文 Visual Basic 6.0 实用教程—结构化程序设计

(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 程序运行起始画面 图 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 实用教程—结构化程序设计

从程序可以看出,在子过程中定义形参时,使用了 ByVal 关键字,这是按值传递数据。


2.“调函数求组合数”程序
【实例】 在“调函数求组合数”程序中,把求阶乘的程序内容定义为函数过程,然后通
过多次调用函数过程来计算出结果。程序运行的画面如图 6-1-8 所示,输入 N 和 M 的数值之
后,单击“调函数计算”按钮,即可显示计算结果,如图 6-1-9 所示。

图 6-1-8 程序运行起始画面 图 6-1-9 计算结果

“调函数求组合数”程序的窗口设计可参看图 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

从程序可以看出,在函数中定义形参时,使用了 ByVal 关键字,这是按值传递数据。


第6章 过程和自定义数据类型 191

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-10 程序运行起始画面 图 6-1-11 计算结果

Rem 调用子过程 ZCHGS 的主过程


Private Sub 调子程序_Click( ) '调用子过程的主过程
Dim A, B, Q, GS As Integer, S As Long
A = Text1.Text '将文本框 Text1 中的数字赋给变量 N
B = Text2.Text '将文本框 Text2 中的数字赋给变量 M
Call ZCHGS(A, B, GS): Q = GS '调求 M 和 N 最大公约数的子过程,并赋给 Q
S =A* B/ Q
Label6.Caption = Str$(Q)
Label7.Caption = Str$(S)
End Sub
Rem 求最大公约数的子过程 ZCHGS
Public Sub ZCHGS(ByVal N As Integer, ByVal M As Integer, GS1 As Integer)
Dim I, R As Integer
R = M Mod N
Do While R <> 0
M = N: N = R
R = M Mod N
Loop
GS1 = N
End Sub
192 中文 Visual Basic 6.0 实用教程—结构化程序设计

Rem 调用函数过程 HSGS 的主过程


Private Sub 调函数_Click( ) '调用函数过程的主过程
Dim A, B, Q As Integer, S As Long
A = Text1.Text '将文本框 Text1 中的数字赋给变量 N
B = Text2.Text '将文本框 Text2 中的数字赋给变量 M
Q = HSGS(A, B) '调求 M 和 N 最大公约数的函数过程,并赋给 Q
S =A* B/ Q
Label6.Caption = Str$(Q)
Label7.Caption = Str$(S)
End Sub
Rem 求最大公约数的函数过程 HSGS
Public Function HSGS(ByVal N As Integer, ByVal M As Integer)
Dim I, R As Integer
R = M Mod N
Do While R <> 0
M = N: N = R
R = M Mod N
Loop
HSGS = N
End Function
Private Sub 退出_Click( )
End
End Sub
程序代码中,自定义的函数名称为“HSGS”,自定义的 Sub 子过程名称为“ZCHGS”。
2.“哥德巴赫猜想证明”程序
【实例】 哥德巴赫猜想的一个命题是:任何一个大于 2 的偶数都是两个素数之和。例如,
4=2+2,10=3+7…编写一个程序,能够将键盘输入的任何大于 2 的偶数表示为两个素数之和。
分别用子过程和函数过程来编写。
在程序中,首先选择第一个数 3 作为第一个加数 I,判断它是否是素数。如果 I 是素数,
则再判断第二个加数(S=N−I)是否是素数。如果 S 是素数,则显示结果。如果 S 不是素数,
再继续选择比 3 稍大的数 5 作为第一个加数 I,继续重复上述过程……直至找到两个符合要
求的素数为止。判断是否为素数的程序可以编写为 Sub 子过程或函数过程。
程序运行后的起始画面如图 6-1-12 所示。在文本框中输入一个偶数后,单击“函数计算”
或者“子过程计算”按钮,即可计算出哥德巴赫猜想的命题式子。此时的窗体如图 6-1-13 所示。

图 6-1-12 程序运行起始画面 图 6-1-13 程序运行结果


第6章 过程和自定义数据类型 193

程序的窗口设计可参看图 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

Rem 调用函数过程 HSGS 的主过程


Private Sub 调函数_Click() '调用函数过程的主过程
Dim A, B, Q, GS As Integer, S As Long

…… 返回函数值
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 参数的传址与传值

在 Visual Basic 中传递参数数据有按值传递(Passed By Value)和按址传递(Passed By


Reference)两种方式。其中,按值传递简称为传值,按址传递简称为传址,也称为“引用”。
1.按值传递
按值传递使用 ByVal 关键字。按值传递参数时,Visual Basic 给形参分配一个临时的内存
单元,将实参的值传递到这个临时单元。
实参向形参传递是单向的。当调用一个子过程或函数过程时,系统将实参的值复制给形
参,实参与形参断开了联系。如果在被调用的过程中改变了形参值,则只是临时的存储单元
中的值变动,不会影响实参变量本身。当过程调用结束时,Visual Basic 将释放这些形参所占
用的存储单元。因此在过程中对形参的任何操作不会影响到实参。
本章前面介绍的“两个自然数的最大公约数和最小公倍数”实例就是采用了按值传递。
程序执行时,数据的传递过程如下:
通过函数调用,给形参 N 和 M 分配临时内存单元,将实参 A 和 B 的数据传递给形参 N
和 MD 的临时内存单元。在被调函数 HSGS 中,N 和 M 取值不断变化,但实参 A 和 B 不会
发生变化。调用函数过程结束后,实参单元 A 和 B 仍保留原值。可见参数的传递是单向的。
2.按址传递
在定义子过程或函数过程时,如果没有 ByVal 关键字,用 ByRef 关键字指定按址传递参
数,缺省关键字时也是按址传递参数。按址传递参数,是指把形参变量的内存地址传递给被
调用过程。形参和实参具有相同的地址,即形参和实参共享同一段存储单元。因此,在执行
一个过程时,它将实参的地址传递给形参。在被调的子过程或函数过程中,对形参的任何操
作都变成了对相应实参的操作,因此实参的值就会随着形参的变化而改变。
在被调子过程或函数过程中改变形参的值,则相应的实参值也会随之改变。也就是说,
第6章 过程和自定义数据类型 197

按地址传递参数可在被调过程中改变实参的值。
当参数是字符串或数组时,使用传址传递直接将实参的地址传递给过程,会使程序的效
率提高。使用传址方式时,对应的实参不能是表达式和常数,只可以是变量。
为了使程序可靠和便于调试程序,减少各过程间的关联,一般采用传值方式。当希望实
参的值随着被调过程中形参的变化而改变时,可采用传址方式。
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 程序运行后单击窗体产生的效果

Rem 调函数过程 HSJC 的主程序(单击窗体后产生事件)


Private Sub Form_Click( )
Dim Sum, Q As Integer
198 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 实用教程—结构化程序设计

Print "传址子过程 CZ2 中互换变量值后的变量数据:"; "X2="; X; " "; "Y2="; Y


Print
End Sub
2.“命名传递验证”程序
【实例】 设计一个“命名传递”程序。要求编写一个交换
两个字符型变量数据( “Hello”和“你好”
)的子过程 MM,
通过主过程调用该子过程。通过这个小实例,可以帮助读者进
一步了解命名传递数据的特点。程序运行后,窗体内显示的结
果如图 6-2-6 所示。
图 6-2-6 “命名传递”程序运行结果
“命名传递”程序代码如下。
Private Sub Form_Activate( )
Dim N, M As String
FontSize = 12
N = "Hello": M = "你好"
Print "N="; N, "M="; M: Print
Call MM(N1:=N, M1:=M)
Print "N="; N, "M="; M: Print
End Sub
Public Sub MM(N1, M1 As String)
Dim S As String
S = N1: N1 = M1: M1 = S
Print "N1="; N1, "M1="; M1: Print
End Sub
由程序和程序的运行结果可以看出,此程序首先在窗体 Form 的 Activate 事件过程中声
明了两个字符型变量 N、M,接着分别给其赋值“Hello”和“你好” ,并显示它们的值。
然后调用子过程 MM,将实参 N 的值传递给形参 N1,实参 M 的值传递给形参 M1。因
实参 N 和 M 均为变量,所以是按址传递。在子过程中形参 N1 和 M1 的值互换了。调用结束
后,又将形参 N1 的值“你好”传递给实参 N,形参 M1 的值“Hello”传递给实参 M,所以
再显示实参 N 的值变为“你好”,实参 M 的值变为“Hello”。

6.3 求 2 的 N 次方精确值

6.3.1 窗体模块和标准模块

在创建 Visual Basic 工程时,可以将程序代码保存在窗体模块、标准模块和类模块三种


不同的模块中。在这三种模块中都可以包含各种声明和过程。它们形成了工程的一种模块层
次结构,有利于组织工程和便于维护。“工程资源管理器”窗口显示出了一个工程的组成模块,
如图 6-3-1 所示。
其中,扩展名为.frm 的文件为窗体模块文件,扩展名为.bas 的文件为标准模块文件,扩
展名为.cls 的文件为类模块文件。如果这些模块已进行了保存,则在“工程资源管理器”窗
口内会显示出它们的扩展名。在“工程资源管理器”窗口内,每一个模块的名称由两部分组
第6章 过程和自定义数据类型 201

成,括号内的是相应的文件名称(例如:Form11.frm),它在存储文件时被确定;括号外的是
该模块的名称(例如:Form11),可以在其“属性”窗口的“名称”栏内修改。

图 6-3-1 “工程资源管理器”窗口 图 6-3-2 “添加窗体” 对话框

1.窗体模块
每个窗体对应一个窗体模块,在窗体模块内可以包含窗体和其控件对象的属性设置、各
种声明和各种过程等。窗体模块在前面已作过介绍,下面总结有关内容。
(1)添加窗体。单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框,
如图 6-3-2 所示。选中“新建”选项卡,再选中“窗体”图标,然后单击“打开”按钮,即
可在当前工程中创建一个新的窗体模块。也可以双击该对话框中的“窗体”图标来创建窗
体模块。
(2)利用记事本等软件可以打开窗体模块文件(也可以打开工程文件、标准模块和类模
块文件),在窗体模块文件中可看到窗体及其控件对象的有关描述,包括它们的属性设置等。
2.标准模块
简单的应用程序一般只有一个窗体,在较大的应用程序中常需要多个窗体。在多窗体结
构的应用程序中,常常会有多个不同的窗体都使用的过程,为了减少工程的代码量和读写方
便,就需要创建标准模块,在标准模块内创建这些公用的过程。任何窗体或模块中的事件过
程或其他过程,都可以调用标准模块内的过程。
在标准模块的代码窗口内可以创建公用的通用
过程,但不能创建事件过程。默认时,标准模块中
的代码是全局的。从一个模块中调用另一个模块的
全局 Sub 子过程时,要在过程名前加模块名字。
在工程中添加标准模块的方法如下。
(1)单击“工程”→“添加模块”菜单命令,打
开“添加模块”对话框,如图 6-3-3 所示。
(2)选中“添加模块”对话框“新建”选项卡,
选中“模块”图标,再单击“打开”按钮,即可在
图 6-3-3 “添加模块”对话框
当前工程中创建一个新的标准模块,同时打开标准
模块的代码窗口。也可以双击该对话框中的“模块”图标来创建新的标准模块。
(3)模块的默认名称为 Module1,可以在其“属性”窗口的“名称”栏中进行修改。
202 中文 Visual Basic 6.0 实用教程—结构化程序设计

(4)单击“文件”→“保存 Module1”菜单命令,可将 Module1 标准模块保存为标准模


块文件,此时的“工程资源管理器”窗口显示出了这个工程的组成模块,如图 6-3-1 所示。
3.类模块
在 Visual Basic 中,类模块是面向对象编程的基础。可以在类模块中编写代码建立新对
象,这些新对象可以包含自定义的属性和方法,可以在应用程序内的过程中使用。实际上,
窗体本身正是这样一种类模块。类模块与标准模块的不同之处在于:标准模块仅仅含有代码,
而类模块既含有代码又含有数据。
在工程中添加类模块的方法是:单击“工程”→“添加类模块”菜单命令,打开“添加类
模块”对话框(与“添加窗体”对话框类似) ,选中“新建”选项卡,再选中“类模块”图标,
然后单击“打开”按钮,即可在当前工程中创建一个新的类模块,同时打开类模块的代码窗口
(它与窗体的代码窗口类似) 。也可以双击该对话框中的“类模块”图标来创建新的类模块。

6.3.2 变量的作用域和变量的生存期

在 Visual Basic 中,应用程序由多个过程组成,这些过程一般均保存在窗体文件(.frm)


和标准模块文件(.bas)中。在各种过程中都可以定义自己的变量(也包括自定义常量)。这
样就存在一个问题,这些变量和过程是否在所有过程中都可以使用呢?
在 Visual Basic 中,变量和过程会随着它所处的位置不同,可被访问的范围也不同,变
量可被访问的范围叫变量的作用域,过程可被访问的范围称为过程的作用域。
和变量声明一样,常量也有作用域,也遵从与变量作用域相似的规则。
1.变量的作用域
变量的作用域就是变量的作用范围,也叫变量的有效范围。变量的作用域决定了哪些子
过程和函数过程可以访问该变量。根据定义变量的位置和定义变量的语句不同,在 Visual
Basic 中,变量可分为过程级变量(即局部变量) 、模块级变量和全局变量。表 6-3-1 中列出
了三种变量的作用范围及其使用规则。
表 6-3-1 三种变量的作用范围及使用规则
过程级变量 模块级变量 全局变量

作用范围 所在的过程 所在的窗体或模块 整个应用程序

声明关键字 Dim、Static Dim、Private Public、Global

声明的位置 在过程中 在窗体/模块的通用声明段 在窗体/模块的通用声明段

被本模块的其他过程存取 不可以 可以 可以

被其他模块的过程存取 不可以 不可以 可以

(1)过程级变量:它指在过程内用 Dim 语句声明的变量(或不加声明直接使用的变量)。


只有该过程内部的代码程序才能访问或改变局部变量的值,别的过程不可以读取局部变量。
局部变量的作用范围限制在该过程。在主过程中建立的过程级变量,也不能在子过程中使用。
要声明一个过程级变量,可以在过程内部,使用 Dim 或 Static 关键字定义(声明)变量。
定义过程级变量的语句格式如下。
Dim 变量名 As Integer
Static 变量名 As Single
第6章 过程和自定义数据类型 203

例如:
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

* Log(2) / Log(10)) + 1 来确定。程序中,用 W=1 表示各位数中有大于 9 的数,需进位。外循


环用来控制 N 个 2 相乘,内循环决定 2 与几位数相乘。再用一个子过程 JWJS 来完成数的进
位计算。
2.程序中的窗体模块程序设计
程序中使用许多变量,它们的作用是:A 是数组,它的下标变量用来保存各位的数值;
N1 用来保存 2N 的位数,N 用来保存文本框 Text1 中的数;I、J、T、H 是循环变量;K 用来
保存乘以 2 的过程中,已经有数的位数;L 用来保存一个已经显示的数字个数,以便确定换
行显示。
“求 2 的 N 次方精确值”的窗体模块程序如下。
Private A( ) As Integer '声明一个模块级数组 A
Public W As Integer '声明一个全局变量 W
Rem 求 2 的 N 次方的主过程
Private Sub Command1_Click( )
Rem 调整窗体内光标的位置,即几次回车换行,将光标移到 Label3 标签的下边
Form1.Cls '清窗体后,用 Print 方法显示的内容被清除,光标移到第一行起始位置
IF Q=0 THEN
Rem 第一次单击"计算"按钮后调整光标的位置
Print: Print: Print: Print: Print: Print: Print: Print: Print
Q=1
Else
Rem 第一次以后再单击"计算"按钮后调整光标的位置
Print: Print: Print: Print: Print: Print: Print
End If
Rem 求 2 的 N 次方的过程
Dim N1, N, I, J, K, H, T, L As Integer '声明各过程级变量
N = Val(Text1.Text) '将文本框 Text1 中的数赋变量 N
Label3.Caption = "2 的" & N & "次方等于" '给标签赋值
N1 = Int(N * Log(2) / Log(10)) + 1 '计算 2 的 N 次方的位数
ReDim A(N1 + 1) As Integer '定义一个动态一维数组
第6章 过程和自定义数据类型 207

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 实用教程—结构化程序设计

If A(K + 1) > 0 Then K = K + 1 '如果最高位有进位,则将变量 K 的值加 1


Next H
W=0 '变量 W 赋初值 0,表示没有需要进位的数
End Sub
4.通过Sub Main过程启动应用程序
当应用程序启动时不加载任何窗体,可在标准模块中创建一个 Sub Main 的子过程(不能
在窗体模块中创建 Sub Main 的子过程),然后在 Sub
Main 的过程中输入启动时需要执行的代码。每个工
程只能有一个 Sub Main 的子过程。当工程中含 Sub
Main 子过程时,应用程序装载窗体之前总是先执行
Sub Main 子过程。
单击“工程”→“工程 1 属性”菜单命令,调
出“工程 1-工程属性”对话框,选中“通用”选项
卡,再从“启动对象”下拉列表框中选择“Sub Main”
选项,如图 6-3-6 所示。单击该对话框中的“确定”
图 6-3-6 “工程 1-工程属性”对话框设置 按钮,即可设置 Sub Main 子过程为启动对象。

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

图 6-3-7 程序运行结果之一 图 6-3-8 程序运行结果之二

图 6-3-9 程序运行结果之三 图 6-3-10 程序运行结果之四

分析:用 RS 表示总人数,GZ 数组存放每个职工的实发工资数,N 表示工资总数,Y100、


Y50、Y20、Y10、Y5、Y2、Y1 分别表示 100 元、50 元、20 元、10 元、5 元、2 元、1 元人
民币的数量,J5、J2、J1 分别表示 5 角、2 角、1 角人民币的数量,F5、F2、F1 分别表示 5
分、2 分、1 分人民币的数量。
由于统计元、角、分(除了百元)各种面值人民币数量的工作是相同的,所以可用一个
子过程 TGGZ 来完成。
“发工资方案”程序中窗体模块内的程序代码如下。
Dim N As Single, K As Integer
Rem 显示窗体后产生的事件过程
Private Sub Form_Activate( )
Command1.Enabled = False '使“统计”按钮无效
Text1.SetFocus '定位光标到文本框 Text1
K=1 '变量 K 用来保存人的序号
Label1.Caption = RS '显示人数
Label2.Caption = "输入第 1 个人的工资:" '给 Label2 标签赋提示信息
End Sub
Rem 在 Text1 文本框中输入数据时的事件过程
Private Sub Text1_KeyPress(KeyAscii As Integer)
Rem 如果按了回车键(其 KeyAscii 值为 13),则执行 If Then 下面的程序
If KeyAscii = 13 Then
GZ(K) = Val(Text1.Text) '用数组下表变量保存个人工资
N = N + GZ(K) '工资累计
Label3.Caption = N '显示工资和
K=K+1
Text1.Text = "" '清文本框 Text1
Label2.Caption = "输入第" + Str$(K) + "个人的工资:" '给 Label2 标签赋提示信息
End If
210 中文 Visual Basic 6.0 实用教程—结构化程序设计

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

然后,单击“工程”→“工程 1 属性”菜单命令,调出“工程 1-工程属性”对话框,选


中“通用”选项卡,再从“启动对象”下拉列表框中选择“Sub Main”选项,如图 6-3-6 所
示。单击该对话框中的“确定”按钮,即可设置 Sub Main 子过程为启动对象。

6.4 统计学生成绩

通常,在数组中各个数组元素的数据类型应该是相同的,但在实际应用中,所处理的对
象往往由一些互相联系的、不同类型的数据项组合而成。虽然可以把数组声明为 Variant 型,
从而使各个数组元素存放不同类型的数据。但是,这会降低应用程序的运行速度。为了既能
够表示和处理不同类型的数据,又不至于降低应用程序的运行速度,可以将这些描述同一对
象的各种类型数据声明为用户自定义数据类型。用户自定义数据类型,又叫记录类型。

6.4.1 自定义数据类型的定义方法

自定义类型也必须先定义,然后才可以使用。自定义数据类型通过 Type 语句来实现,


语句的格式和功能如下。
1.自定义数据类型的定义格式与功能
【格式】
[Public|Private]Type 自定义型名称
数据项名 1 As 类型名
……
[数据项名 n As 类型名]
End Type
【功能】声明了自定义数据类型,它的名称由 Type 关键字右边的“自定义型名称”来确定。
【说明】
① 关键字 Private 表示声明模块级自定义数据类型,Public 表示声明全局级自定义数据
类型,默认是 Public。该语句必须置于模块的声明部分,而不能置于过程内部。
② 自定义型名称和数据项名的命名规则与变量名的命名规则完全相同。
③ 数据项名是记录中所包含的一个数据的名称,它可以有下标,表示数组。类型名用
来说明记录中数据项的数据类型,它是基本数据类型的类型说明关键字(如 Inetger、Long
等),或者是其他已定义的记录数据类型的名称。类型名是字符串时,必须是定长字符串。
④ 自定义型名称和该类型的变量名容易混淆,前者表示了如同 Integer、Single 等的类型
名,后者则由 Visual Basic 根据变量的类型分配所需的内存空间,存储数据。
212 中文 Visual Basic 6.0 实用教程—结构化程序设计

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 所示。

图 6-4-1 “输入学号”对话框 图 6-4-2 “统计学生成绩”程序运行结果


第6章 过程和自定义数据类型 213

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

Rem 使用标准模块文件中的全局变量 QJBL1


Private Sub Command1_Click( )
Module1.TESTJBGC '调用 Modulel 中的子过程 TESTJBGC
Rem 显示标准模块文件中的全局变量 SJBL1
TS$ = Module1.SJBL1 & Chr(13) & Chr(10) & "QJBL1=" & Module1.QJBL1
N = MsgBox(TS$, vbOKOnly, "标准模块 Module1 中的变量值")
End Sub
Rem 使用窗体模块文件中的全局变量 QJBL
Private Sub Command2_Click( )
TESTJBGC '调用 Forml 中的子过程 TESTJBGC
Rem 显示窗体模块文件中的全局变量 SJBL1
TS$ = SJBL1 & Chr(13) & Chr(10) & "QJBL1=" & QJBL1
N = MsgBox(TS$, vbOKOnly, "窗体模块 Forml 中的变量值")
End Sub
第6章 过程和自定义数据类型 215

在窗体中有“标准模块全局变量”和“窗体模块全局变量”两个按钮,它们的名称分别
是 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 右图
所示。

图 6-4-3 “使用同名变量 1”程序运行结果

(2)控件对象名称与变量同名
窗体的属性、控件对象、符号常数和过程都被视为窗体模块中的模块级变量。如果窗体
中的控件名与模块级变量名、符号常数和过程名相同是不合法的,因为它们的作用范围相同。
因此,在窗体模块中应当尽量使变量名和窗体中的控件名不一样,养成对不同的变量使用不
同的名称的编程习惯。
在窗体模块内,如果控件对象的名称与它的局部变量名称相同,局部变量名将遮住同名
控件。因此,必须引用窗体名称或 Me 关键字来限定控件
对象,才能设置或得到该控件的属性值。例如,在窗体
(Form1)有一个文本框 Textl,也有一个局部变量 Textl,
则使用文本框 Textl 时应采用:Form1.Textl 或 Me.Textl。例
如下边的程序的运行结果如图 6-4-4 所示。 图 6-4-4 “使用同名变量 2”程序运行结果

Private Sub Form_Activate( )


Dim Label1 '定义局部变量 Label1
Me.Label1.Caption = "设置标签控件的位置" '控件可以用 Me 限定
Me.Label1.Left = 0 '设置窗体内控件 Label1 的 Left 属性
Form1.Label1.Top = 0 '设置窗体内控件 Label1 的 Top 属性
Label1 = "控件名称与变量名同名" '给局部变量 Label1 赋值
Print: Print: Print: Print Label1 '显示局部变量 Label1 的值
End Sub

(3)全局变量与局部变量同名
当全局变量与局部变量同名时,全局变量和局部变量在不同的范围内有效。在过程内,
局部变量有效;而在过程外,全局变量有效。
216 中文 Visual Basic 6.0 实用教程—结构化程序设计

2.启动时快速显示窗体
如果应用程序在启动时有一个较长的执行过程(从数据库中装入大量数据或者需要装入
一些加大的图像等),可在启动时给出一个快速显示窗体,它通常显示的是应用程序的名称、
设计单位或个人名字、版权信息和一些简单的图像等内容。启动 Visual Basic 程序时开始所
显示的窗口就是一个快速显示窗体。快速显示窗体能吸引用户的注意,造成应用程序装载很
快的错觉。当启动完成并且装入第一个窗体的同时卸载快速显示窗体。快速显示窗体应尽量
设计的简单一些。
Visual Basic 提供了一些常用的窗体模板,其中有一个“展示屏幕”,可在这个模板的基
础上创建快速显示窗体。创建快速显示的方法如下。
(1)单击“工程”→“添加窗体”菜单命令,调出“添加窗体”对话框。
(2)在“添加窗体”对话框中选择“展示屏幕”图标,如图 6-4-5 所示。
(3)单击“打开”按钮,创建快速显示窗体的模板,如图 6-4-6 所示。然后,在该窗体
内添加需要的相关信息。

图 6-4-5 “添加窗体”对话框 图 6-4-6 快速显示窗体的模板

(4)建立标准模块,创建 Sub Main 过程作为启动对象,在 Sub Main 过程中用 Show 方


法来调出快速显示窗体。再用 Show 方法显示主窗体,用 Unload 语句卸载快速显示窗体。
例如:
Private Sub main( )
frmSplash.Show
……
Form1.Show
Unload frmSplash
End Sub

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*24 F(4)=4*6 F(3)=3*2 F(2)=2*1

回归阶段

F(5)=5! F(1)=1

5*F(4) 4*F(3) 3*F(2) 2*F(1)

递推阶段

图 6-5-1 5!递归算法的递推和回归两个阶段
218 中文 Visual Basic 6.0 实用教程—结构化程序设计

6.5.2 项目实现

1.界面设计
“求 N!”程序运行后,显示的窗体如图 6-5-2 所示。在文本框内输入 N 的数值,再单击
“求阶乘”按钮,即可求出 N!,如图 6-5-3 所示。

图 6-5-2 程序运行起始画面 图 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 所示。

图 6-5-4 程序运行的初始效果 图 6-5-5 程序运行后的结果

“利用递归算法求斐波那契数列的第 N 号数”程序的程序代码如下。
Private Sub Command1_Click( )
220 中文 Visual Basic 6.0 实用教程—结构化程序设计

Dim M As Long, N As Integer


N = Val(Text1.Text)
If N = 0 Then
M=0
Else
M = FACT(N)
End If
Label3.Caption = "斐波那契数列的第" & N & "号数是:"
Label4.Caption = Str$(M)
End Sub
Rem 求第 N 个斐波那契数列的数的函数过程
Public Function FACT(ByRef N As Integer) As Long
If N = 1 Or N = 2 Then
FACT = 1
Else
FACT = FACT(N - 1) + FACT(N - 2) '递归算法
End If
End Function
Private Sub Command2_Click( )
End
End Sub

2.“Hanoi(汉诺)塔问题”程序
【实例】 Hanoi 塔相传是一种古印度所罗门教徒玩的游戏。它的内容是:古代有一个梵
塔,塔内有 A,B,C 座,开始时 A 座上有 N 个大小不等、中心有孔的圆形金盘,这些圆形
金盘都穿过 A 座上的针,小片金盘在上,大片金盘在下,形成金盘宝塔形状,如图 6-5-6 所
示。要求将 A 座上的 N 片金盘全部移至 B 座。限制每次只移一个金盘,并且不允许将大的
金盘放在小金盘的上面,但移动时可以将金盘放在 C 座上。任何时候,任一座上的金盘只能
小片金盘压大片金盘,不能大片金盘压小片金盘。试给出移动的方法。

1
2
3
A B C

图 6-5-6 Hanoi(汉诺)塔问题示意图(3 片金盘)

将金盘按直径大小依次编号 1,2,3,…,N,称由 1 号至 N 号金盘组成的金盘塔,金盘


塔的高度为 N。高度为 N(N>1)的塔相当于一个高度为 N−1 的塔下面压了一个金盘 N。于是,
利用 C 座,将 A 座上的 N 片金盘全部移至 B 座(递归地)的问题可递归定义(即移动方法)
如下。递归脱离的条件是 N<=0。
(1)先利用 B 座,将 A 座上的 N−1 个金盘移到 C 座(递归地);
(2)把 A 座上惟一的一个金盘(金盘 N)移到 B 座;
第6章 过程和自定义数据类型 221

(3)再利用 A 座,把 C 座上的 N−1 个金盘移到 B 座(递归地)。


例如:N=3 时,将 A 座上的三个金盘 1,2,3 移到 B 座的步骤如图 6-5-7 所示。
“Hanoi 塔问题”程序运行后的窗体如图 6-5-8 所示,在文本框中输入 N 的值后,单击“开
始移动金盘”按钮,即可显示移动的步骤,如图 6-5-9 所示。

移动第 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座

图 6-5-7 N=3 时,将 A 座上的三个金盘 1,2,3 移到 B 座的步骤

图 6-5-8 程序运行的初始效果 图 6-5-9 程序运行后的结果

程序是利用递归算法求解 Hanoi 塔问题的程序。程序可以将输出移动高为 N 的 Hanoi 塔


的动作序列显示出来。程序中,N 表示金盘的个数,解决 Hanoi 塔问题,并显示移动步骤的
子过程名称是 FACT。
“Hanoi 塔问题”程序的程序代码如下。
Private Sub Command1_Click( )
Dim A, B, C As String
Dim N As Integer
N = Val(Text1.Text)
Cls
Print: Print
Call FACT(N,"A","B","C") ‘调子过程 FACT,利用 C 座,将 A 座上的 N 片金盘移至 B 座(递归地)
End Sub
Rem 解决 Hanoi(汉诺)塔问题的子过程 FACT
Public Sub FACT(ByRef N As Integer, ByRef A As String, ByRef B As String, ByRef C As String)
If N > 0 Then
Call FACT(N-1,A,C,B) '先利用 B 座,将 A 座上的 N-1 个金盘移到 C 座(递归地)
Rem 把 A 座上惟一的一个金盘(金盘 N)移到 B 座
Print "移动第" & N & "个金盘: 从 " & A & "座" & " 移到 " & B & "座"
Call FACT(N-1,C,B,A) '再利用 A 座,把 C 座上的 N-1 个金盘移到 B 座(递归地)
End If
End Sub
222 中文 Visual Basic 6.0 实用教程—结构化程序设计

Private Sub Command2_Click( )


End
End Sub
3.“精确计算 N!的值”程序
【实例】 编写一个能精确计算 N!的程序,要求能显示出计算结果的每位数字。程序运行后,
在文本框中输入 N 的值后,按回车键或单击“计算”
按钮,可获得 N!的精确值,如图 6-5-10 所示。
计算 N!=1*2*3*…*(N−1)*N 可用程序完成
N 个 1 到 N 的正整数相乘,并把每位数存放在数
组 A 的各下标变量中,A(1)存放个位数、A(2)存
放十位数、A(3)存放百位数……数组 A 的下标最
图 6-5-10 程序运行结果 大值一开始定为 2,是考虑到有进位。程序中,用
W=1 表示各位数中有大于 9 的数,需进位。外循环用来控制 N 个 1 到 N 的正整数相乘,内
循环决定正整数与几位数相乘。再用一个子过程 JWJS 来完成数的进位计算。该程序要特别
考虑的是,某一位数进行了一次进位计算后,还可能存在某位数仍然大于 9 的情况,所以要
使用递归子过程,再次调用进位子过程,进行进位计算。
“精确计算 N!的值”程序的程序代码如下。
Dim A( ) As Integer
Rem 单击“计算”按钮后产生事件,计算 N!
Private Sub Command1_Click( )
Dim N1, N, I, J, K, H, T, L, W As Integer
N = Val(Text1.Text)
ReDim A(2) As Integer '定义动态数组 A 的下标上界为 2,考虑到有进位
Cls
Print: Print: Print: Print: Print: Print: Print: Print: Print
A(1) = 1: K = 1: W = 0
For I = 1 To N
For J = 1 To K
A(J) = A(J) * I '给各位数乘 I 值
If A(J) > 9 Then W = 1 '如果某位数大于 9,则变量 W 赋 1,表示有需要进位的数
Next J
If W = 1 Then Call JWJS(K, W, A( )) '如果有某位数大于 9,则调进位子过程 JWJS
Next I
If N <> O Then
FontSize = 12
ForeColor = RGB(0, 0, 255)
L=1
For T = K To 1 Step -1
Print RTrim$(Right$(Str(A(T)), 1));
If L Mod 60 = 0 Then Print
L=L+1
Next T
Print: Print
第6章 过程和自定义数据类型 223

Print LTrim$(Str$(N)) + "!的位数是:" + LTrim$(Str$(K)) '显示位数


End If
End Sub
Rem 创建进位计算子过程 JWJS
Public Sub JWJS(K, W, A( ) As Integer)
Dim H 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
If A(K + 1) > 0 Then '如果最高位有进位,则
K=K+1 '则将变量 K 的值加 1
Rem 重新定义动态数组 A,K+1 定为数组上界是因为考虑到有进位
ReDim Preserve A(K + 1) As Integer
End If
Next H
W=0
For H = 1 To K '重新检查各位是否还有大于 9 的数
If A(H) > 9 Then W = 1: Exit For '如果有大于 9 的数,则重新进行进位计算
Next H
If W = 1 Then Call JWJS(K, W, A( )) '再调进位子过程 JWJS,形成递归
End Sub
Private Sub Command2_Click( )
End
End Sub

思考与练习

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

(4)Write 语句与 Print 语句的区别


• Write 语句通常采用紧凑格式输出,即各数据项之间用“,”分割,在写入文件时,数
据项之间会自动用逗号作为分界符分隔开;而 Print 语句中的表达式之间因所用分隔符逗号或
分号的不同,其数据项间的位置不同,且不会自动加入定界符。
• Write 语句通常与 Input#读语句配合使用;Print 语句常与 Line Input#读语句配合使用。
• Write 语句通常用于数据写入文件后还要用 VB 程序读出时;而 Print 语句通常用于写
入文件的数据以后要被显示或打印出来时,作为格式输出语句。
2.关闭顺序文件
在对文件进行完各种操作以后,必须要将文件关闭,否则会出现文件中数据丢失等现象。
因为将数据写入文件的实质只是将数据写入缓冲区,关闭文件是将缓冲区的剩余数据全部写
入文件内。
【格式】Close [[#]文件号][,[#]文件号,…,[#]文件号]
【功能】将指定的文件一次性关闭。如果 Close 后未跟任何参数,表示将所有打开的文件
全关闭。Close 语句会执行清除缓冲区的动作,释放全部与关闭的文件有关的 VB 缓冲区空间。
例如:Close #1,#2,#3,#4
该语句表示关闭了 1 号、2 号、3 号和 4 号顺序文件。

7.1.4 项目实现

常上网聊天的人都知道,在聊天的过程中最担心的就是信息泄露,也就是聊天的内容被
其他人看见。为了解决这个问题,可以制作一个文本加密器和一个文本解密器,当要输入信
息的时候使用文本加密器对文本进行加密,要察看信息的时候使用文本加密器对文本进行解
密。该程序只限于对英文文本文件和 ASCII 文本文件进行加密和解密。
加密的原理是将需要加密的所有字符依次转换为 ASCII,然后对其中字符的 ASCII 依次
进行减 9 的操作。最后将加密后的信息保存到程序目录下的 WJBC.TXT 文件中。
程序初始时的显示效果如图 7-1-1 所示。在“加密前的文本”文本框中输入需要加密的
文字后,单击“加密”按钮,可在“加密后的文本”文本框中显示出加密后的文本,如图 7-1-2
所示。单击“保存”按钮,即可将加密后的信息保存到 WJBC.TXT 文件中。

图 7-1-1 程序运行后的显示效果 图 7-1-2 输入需要加密的信息并进行加密

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

图 7-1-3 程序运行后的显示效果 图 7-1-4 打开加密的信息并进行解密

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 实用教程—结构化程序设计

ASCIIN 中。将解密后的字符依次加到变量 MWJ 的尾部,直到遇到“回车”时结束。最后,


将解密后的文本显示在“解密后的文本”文本框中。

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

记录的最大长度,即字节的最多个数。“记录长度”参数的默认值为 128 字节。


② 因为随机文件是按记录进行操作的,所以在对随机文件进行打开操作时,读模式均
相同,无需指明输入、输出和追加模式。随机文件只要打开一次就可同时进行读操作。
③ 在程序中只要定义了访问随机文件的记录类型并为记录申请了内存空间,便可打开
文件,对文件进行读操作。
系统同时能打开多少个文件受 CONFIG.SYS 文件的限制,可通过修改该文件中 Flies 命
令来设置打开文件的个数。
2.读取随机文件
【格式】Get #文件号,[记录号],变量
【功能】从打开文件中将“记录号”参数指定的记录读出来,并存入相应的变量中。
【说明】
① “记录号”参数是从 1 开始的整数,表示对第几条记录进行读操作,如果省略记
录号,则表示从当前位置的下一个字节开始读数据,当记录号省略时,它前后的逗号不能
省略。
② 从文件中读取多少个字节的数据取决于变量类型,一次读取数据的字节数与变量在
内存中所占字节数相同,所以程序中定义变量的长度可决定每次从文件中读取数据的字节数。
例如:将随机文件 XSDA 的第 3 条记录读出的程序如下。
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)
Get #1,3, XSJL1 '读出第 3 号记录的内容
Print XSJL1.XH,XSJL1.XM,XSJL1.NL '输出读出的记录内容
Close #1

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-1 “学生档案管理”程序运行后的画面之一

在“查询”按钮右边的文本框中输入一个记录号,再单击“查询”按钮,即可显示出该
记录的内容,如图 7-2-2 所示。如果查询的记录号为 1,则“上一个”按钮为无效。单击“下
一个”按钮,即可显示下一条记录的内容,同时“上一个”按钮变为有效;单击“上一个”
按钮,即可显示上一条记录的内容。如果在查询时要修改记录的内容,单击“修改”按钮,
即可将该记录进行修改。追加记录的功能是将考生信息作为一条记录添加到随机文件末尾,
查询的功能是在窗体内显示“查询”按钮右边文本框中记录号指定的记录内容。
1.设置对象的属性
在窗体中,加入一些标签,用来输入提示信息;再加入两个标签,用来显示总分和平均
分;加入一些文本框,用来显示学生档案的有关内容;加入两个组合框,用来选择学生的籍
贯和年龄(也可以输入新内容);加入两个单选钮,分别用来表示男女性别;加入一个复选框,
用来确定是否获过奖;在控制栏内加入 6 个按钮,用来进行相应的操作。为了使画面好看和
第7章 文件管理 235

规整,加了 3 个框架,用来分别放置不同类型的对象。注意:一定要先加入框架对象,再加
入框架内的对象。

图 7-2-2 “学生档案管理”程序运行后的画面之二

用于显示学生成绩的 10 个文本框,组成了一个对象数组,名字为 TextCJ。在对象数组


中,TextCJ(1)文本框用来显示语文成绩,TextCJ(2)文本框用来显示数学成绩……TextCJ
(10)文本框用来显示生物成绩。为了操作方便,将需要操作的对象,按从左到右,从上到下
的顺序,依次将它们的 TabIndex 属性设置为 1,2,3…
对象的名称如表 7-2-1 所示。程序中用到一些文件的函数,可参看本章第 5 节。
表 7-2-1 窗体中对象的名称
对 象 名 称 对 象 名 称 对 象 名 称

编号文本框 TextBH 电话文本框 TextDH 追加按钮 CommandZJ

姓名文本框 TextXM 家庭地址文本框 TextDZ 修改按钮 CommandXG

籍贯组合框 ComboJG 邮编文本框 TextYB 查询按钮 CommandCX

年龄组合框 ComboNL 获奖复选框 CheckHJ 号码文本框 TextHM

出生日期文本框 TextRQ 成绩文本框数组 TextCJ 上一个按钮 CommandSY

性别男单选钮 OptionXB1 总分标签 LabelZF 下一个按钮 CommandXY

性别女单选钮 OptionXB2 平均分标签 LabelPJ 退出按钮 CommandQUIT

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 实用教程—结构化程序设计

XSNL As String * 2 '学生年龄


XSRQ As String * 10 '学生出生日期
XSYB As String * 6 '学生邮编
XSDH As String * 12 '学生电话
XSDZ As String * 30 '学生地址
XSHJ As Boolean '学生获奖
XSCJ(1 To 10) As Integer '学生成绩
XSZF As Integer '学生总分
XSPJ As Single '学生平均分
End Type
Dim XSDATYPE As XSDADATATYPE '将变量 XSDATYPE 定义为自定义类型
Dim I As Integer
Rem 追加记录
Private Sub CommandZJ_Click()
XSDATYPE.XSBH = TextBH.Text '学生编号文本框内容存 XSDATYPE.XSBH 变量
XSDATYPE.XSXM = TextXM.Text '学生姓名文本框内容存 XSDATYPE.XSXM 变量
XSDATYPE.XSJG = ComboJG.Text '学生籍贯组合框内容存 XSDATYPE.XSJG 变量
XSDATYPE.XSNL = ComboNL.Text '学生年龄组合框内容存 XSDATYPE.XSJG 变量
XSDATYPE.XSRQ = TextRQ.Text '学生出生日期文本框内容存 XSDATYPE.XSRQ 变量
If OptionXB1.Value Then '学生性别单选钮数据存 XSDATYPE.XSXB1 变量
XSDATYPE.XSXB1 = True
Else
XSDATYPE.XSXB1 = False
End If
XSDATYPE.XSZF = 0
For I = 1 To 10 '学生成绩保存 XSDATYPE.XSCJ 数组
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:\邮电职高\VB2\素材\XSDA.TXT" For Random As #1 Len = Len(XSDATYPE) '打开文件
JLH = LOF(1) / Len(XSDATYPE) + 1 '将追加的记录号保存到变量 JLH 中
Put #1, JLH, XSDATYPE '将变量 XSDATYPE 的内容写入文件
Close #1 '关闭文件
End Sub
Rem 查询记录
第7章 文件管理 237

Private Sub CommandCX_Click()


JLH = Val(TextHM) '将编号文本框 TextHM 的内容存变量 JLH 中
If JLH > 1 Then '当编号大于 1 后,使[上一个]按钮有效
CommandSY.Enabled = True
End If
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 '在 LabelZF 标签中显示总分
LabelPJ = XSDATYPE.XSPJ '在 LabelPJ 标签中显示平均分
If XSDATYPE.XSHJ Then '将 XSHJ 变量数据存学生获奖复选框
CheckHJ.Value = 1
Else
CheckHJ.Value = 0
End If
TextDH.Text = XSDATYPE.XSDH '将 XSDATYPE.XSDH 变量内容存学生电话文本框
TextYB.Text = XSDATYPE.XSYB '将 XSDATYPE.XSYB 变量内容存学生邮编文本框
TextDZ.Text = XSDATYPE.XSDZ '将 XSDATYPE.XSDZ 变量内容存学生地址文本框
End Sub
Rem 修改记录
Private Sub CommandXG_Click()
XSDATYPE.XSBH = TextBH.Text '学生编号文本框内容存 XSDATYPE.XSBH 变量
XSDATYPE.XSXM = TextXM.Text '学生姓名文本框内容存 XSDATYPE.XSXM 变量
XSDATYPE.XSJG = ComboJG.Text '学生籍贯组合框内容存 XSDATYPE.XSJG 变量
XSDATYPE.XSNL = ComboNL.Text '学生年龄组合框内容存 XSDATYPE.XSJG 变量
XSDATYPE.XSRQ = TextRQ.Text '学生出生日期文本框内容存 XSDATYPE.XSRQ 变量
If OptionXB1.Value Then '学生性别单选钮数据存 XSDATYPE.XSXB1 变量
XSDATYPE.XSXB1 = True
Else
XSDATYPE.XSXB1 = False
End If
XSDATYPE.XSZF = 0
For I = 1 To 10 '学生成绩保存 XSDATYPE.XSCJ 数组
238 中文 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

TextYB.Text = XSDATYPE.XSYB '将 XSDATYPE.XSYB 变量内容存学生邮编文本框


TextDZ.Text = XSDATYPE.XSDZ '将 XSDATYPE.XSDZ 变量内容存学生地址文本框
End Sub
Rem 查询上一个记录
Private Sub CommandSY_Click()
JLH = JLH - 1 '将编号变量 JLH 的数值自动减 1
If JLH=1 Then CommandSY.Enabled=False '当编号为 1 后,使[上一个]按钮无效
TextHM.Text = JLH '给 TextHM 文本框赋编号
Open "F:\VB\素材\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 '在 LabelZF 标签中显示总分
LabelPJ = XSDATYPE.XSPJ '在 LabelPJ 标签中显示平均分
If XSDATYPE.XSHJ Then '将 XSHJ 变量数据存学生获奖复选框
CheckHJ.Value = 1
Else
CheckHJ.Value = 0
End If
TextDH.Text = XSDATYPE.XSDH '将 XSDATYPE.XSDH 变量内容存学生电话文本框
TextYB.Text = XSDATYPE.XSYB '将 XSDATYPE.XSYB 变量内容存学生邮编文本框
TextDZ.Text = XSDATYPE.XSDZ '将 XSDATYPE.XSDZ 变量内容存学生地址文本框
End Sub
Rem 退出
Private Sub CommandQUIT_Click()
Reset : End '关闭所有文件,退出程序运行
End Sub

7.2.5 项目拓展——“员工工作时间管理”程序

“员工工作时间管理”程序的显示效果如图 7-2-3 所示。在该界面中输入信息后,单击“追


加”按钮,即可插入一个新的数据。在“查询”按钮前面的文本框中输入一个数值后,单击
“查找”按钮,即可打开该记录号的数据,如图 7-2-4 所示。对信息进行修改后,单击“修改”
按钮,即可更改该信息。单击“<<”按钮或“>>”按钮,可向前或向后查找纪录。
240 中文 Visual Basic 6.0 实用教程—结构化程序设计

图 7-2-3 程序运行后的显示效果 图 7-2-4 对数据进行查找

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-3-1 所示。可以将该程序看作“文本文件加


密器”和“文本文件解密器”的组合。在“文本文件加密器”和“文本文件解密器”中只能
对英文字符进行加密,而在“中文文件加密/解密”程序中不但能对英文字符进行加密,还可
以对中文字符进行加密。
该程序的加密方法 2 是从文件头取一个汉字,再从文尾取一个汉字,以后重复进行,
直到将文字全部取完。单击“打开”按钮,即可将加密后的文件内容显示在上边的文本
框中,再单击“解密 2”按钮,即可在下边的文本框中显示出解密后的文字内容,如图
7-3-2 所示。

图 7-3-1 程序运行后的显示效果 图 7-3-2 对打开的文件进行加密

在程序中,将汉字文件作为二进制文件处理,特别要注意汉字文件的保存,以及一个汉
字占用两个字节。
第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 实用教程—结构化程序设计

SM = SM + Mid$(SY, I, 1) + Mid$(SY, FLEN1 + 1 - I, 1)


Next I
If FLEN1 / 2 <> Int(FLEN1 / 2) Then
SM = SM + Mid$(SY, I, 1)
End If
Text2.Text = SM
For I = 1 To FLEN
Put #1, I * 2 - 1, Mid$(SM, I, 1)
Next I
Close #1
End Sub
Rem 解密 2
Private Sub CommandJM22_Click( )
Dim I As Long, N As Integer
Dim SM, SM1, SM2 As Variant
Open "ZWT1.TXT" For Binary As #1
SM = "": N = 1
FLEN1 = FLEN / 2
If FLEN1 / 2 <> Int(FLEN1 / 2) Then
N=2
End If
For I = 1 To FLEN1 Step 2
SM1 = SM1 + Mid$(SY, I, 1)
SM2 = SM2 + Mid$(SY, FLEN1 + N - I, 1)
Next I
SM = SM1 + SM2
Text2.Text = SM
For I = 1 To FLEN
Put #1, I * 2 - 1, Mid$(SM, I, 1)
Next I
Close #1
End Sub
Rem 退出
Private Sub CommandQUIT_Click( )
Reset
End
End Sub
第一种加密方法是将文本中的前 4 个字移到尾部,只是加密方法的一种示范。
第二种加密方法是从文件头取一个汉字,再从文尾取一个汉字,以后重复进行,直到将
文字全部取完。使用 FOR 循环语句,在每次循环中分别开头和结尾向后或向前取一个字符,
将结果添加到变量 SM 中。
解密的方法和加密类似,使用 FOR 循环语句,在每次循环中从开始处隔一个字向后取一
个汉字,从结尾处隔一个字向前取一个汉字,分别存在变量 SM1 和变量 SM2 中,最后将这
两个变量相加,即可还原加密的文字。
第7章 文件管理 247

7.3.4 项目拓展

1.设定文件指针指向的位置
在随机文件和二进制文件中,可通过记录号和字节位置来确定需要访问的数据,那么
在 VB 中有一条移动文件指针的语句,它可设定在打开的文件中下一次进行读/写操作的
位置。
【格式】Seek[#]文件号,位置
【功能】在文件号指定的已打开的文件中,将文件指针移到指定的位置处,然后再对文
件进行读写操作。
【说明】“位置”参数是数值型表达式,它的取值范围为 1~2147483647。对于随机文件,
“位置”参数是记录号,对于二进制文件或顺序文件,“位置”参数是相对于文件头的字节
位置。
2.获取被打开文件的格式
使用 Open 语句可以打开顺序文件、随机文件和二进制文件。如果想知道打开的文件是
何种格式,可使用 FileAttr 函数进行判断。
【格式】FileAttr([文件号]、[文件属性])
【功能】获取被打开文件的模式或操作系统文件句柄的信息,即文件类型信息。在使用
该函数的时候,应注意以下几个问题。
① “文件号”参数是用 Open 语句打开文件时给定的文件序号,以指明该函数获取哪个
被打开文件的属性。
② “文件属性”参数为整型数据,该参数用以规定函数获取什么样的文件类型信息。
当该值为 1 时,函数获取该文件被打开时设定的模式,如表 7-3-1 所示。当该值为 2 时,函
数获取一个由 Windows 环境分配给该文件的文件句柄号,可以将此文件句柄用于 Windows
应用程序接口(Apl)函数中。

表 7-3-1 文件属性参数为 1 时的函数获取值


函 数 值 文件的打开模式 函 数 值 文件的打开模式

1 Input 输入模式 8 Append 追加模式

2 Output 输出模式 32 Binary 二进制模式

4 Random Access 随机访问模式

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 指定无属性的系统文件

8 vbVolume 指定卷标文件。如果指定了其他属性,则忽略 vbVolume

16 vbDirectory 指定无属性文件及其路径和文件夹

注:“文件属性”参数的取值可以相加使用。

④ 在第一次调用 Dir 函数时,必须指定“路径名”参数,否则会产生错误。以后再调用


Dir 函数时可省略参数。
⑤ 若想得到其他匹配“文件属性”参数的文件名,再一次调用 Dir,且不要使用参数。
如果已没有合乎条件的文件,则 Dir 函数会获取一个零长度字符串("")。一旦获取值为零长度
字符串,并要再次调用 Dir 时,就必须指定“路径名”参数,否则会产生错误。
8.CurDir函数
【格式】CurDir[$](驱动器名)]
【功能】获取指定驱动器的当前路径。驱动器名为字符型表达式,指定所列目录为哪个
驱动器的;如果省略该参数,函数获取当前驱动器下的路径。
9.FreeFile函数
【格式】FreeFile[(范围)]
【功能】提供一个尚未使用的文件号,即空闲的文件通道号。
【说明】
① 可选的“范围”参数是一个变量,它指定一个范围,以便返回该范围之内的下一个
可用文件号。指定 0(缺省值)则返回一个介于 1~255 的文件号。指定 1 则返回一个介于 256~
511 的文件号。
② 不可以在 Open 语句中直接使用该函数,应将该函数赋值给一个变量,然后在 Open
语句中使用该变量。函数值是整型数据。
10.FileAttr函数
【格式】FileAttr(文件号、文件属性)
【功能】获取被打开文件的模式或操作系统文件句柄的信息,即文件类型信息。
【说明】
① “文件号”参数是用 Open 语句打开文件时给定的文件序号,以指明该函数获取哪个
被打开文件的属性。
② “文件属性”参数为整型数据,该参数用以规定函数获取什么样的文件类型信息。
当该值为 1 时,函数获取该文件被打开时设定的模式,如表 7-4-2 所示。当该值为 2 时,函
数获取一个由 Windows 环境分配给该文件的文件句柄号,可以将此文件句柄用于 Windows
应用程序接口(Apl)函数中。
250 中文 Visual Basic 6.0 实用教程—结构化程序设计

表 7-4-2 文件属性参数为 1 时的函数获取值


函 数 值 文件的打开模式 函 数 值 文件的打开模式

1 Input 输入模式 8 Append 追加模式

2 Output 输出模式 32 Binary 二进制模式

4 Random Access 随机访问模式

11.GetAttr函数
【格式】GetAttr(文件名)
【功能】获取“文件名”参数指定的文件、目录和卷标的属性,如表 7-4-3 所示。
【说明】函数获取值可以是上述值的相加组合,表示文件具有几个属性的组合。如只读
隐含文件,函数获取值为 3。文件名为字符串表达式,包含文件名、路径名或卷标。该函数
值为整型数据。
表 7-4-3 函数获取值及对应文件属性
值 文 件 属 性 常量表示(CONSTANT.XT)

0 Normal 普通文件 ATTR—NORMAL

1 ReadOnly 只读文件 ATTR—READONLY

2 Hidden 隐含文件 ATTR—HIDDEN

4 System 系统文件 ATTR—SYSTEM

8 Volume Label 卷标号 ATTR—VOLUME

16 MS-DOS directory 目录 ATTR—DIRECTORY

32 Archive 存档文件 ATTR—ARCHIVE

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 对文件操作的语句

VB 中有一些与 DOS 有关,模拟操作系统命令的语句,它们是程序语句,允许用户在编


程中使用这些语句代码对磁盘文件系统进行操作。程序执行这些语句时直接访问操作系统,
相当于在 DOS 环境下键入相应的 DOS 命令一样。
1.ChDrive语句
【格式】ChDrive [驱动器名]
【功能】将当前驱动器改为语句中指定的驱动器。如果[驱动器名]参数为空字符,表示不
改变当前驱动器。
2.ChDir语句
【格式】ChDir“路径”
【功能】改变当前默认的路径。其数据类型是字符型。
【说明】“路径”参数是一个字符串表达式,它给出要改变的当前路径,可以包含驱动器,
它必须少于 128 个字符。如果没有指定驱动器,则 ChDir 在当前的驱动器上改变默认目录。
该语句只能改变默认目录,不能改变默认的驱动器。
3.MkDir语句
【格式】MkDir“路径”
【功能】创建一个由“路径”参数指明的新的目录或文件夹。
【说明】“路径”参数是一个字符型表达式,它可以包含驱动器。如果没有指定驱动器,
则 MkDir 会在当前驱动器上创建新的目录或文件夹。
4.RmDir语句
【格式】RmDir“路径”
【功能】删除一个“路径”参数指定的存在的目录或文件夹。其值是字符型数据。
【说明】“路径”参数是一个字符型表达式,它可以包括驱动器。如果没有指定驱动器,
则 RmDir 语句会在当前驱动器上删除目录或文件夹。要删除的目录必须是空的,仅包含工
作目录(“.”)和父目录(“..”),否则会产生错误。
5.Kill语句
【格式】Kill “文件名”
【功能】删除“文件名”参数指定的磁盘文件。
【说明】“文件名”参数是一个字符型表达式,它可以包含目录、文件夹和驱动器。文件
名参数可以是任何类型的磁盘文件,在该字符串表达式中可包含路径及通配符。
该语句只能删除文件,Kill 语句不能删除打开的文件,否则会出错。
6.Name语句
【格式】Name “旧文件名”As “新文件名”
【功能】将磁盘文件或目录改成新名字。
【说明】文件名字符串中可包含路径名,当新、旧路径名相同,文件名不同时,将文件
改名,当新、旧路径名不同时可将一个文件从一个目录移至另一个目录。注意:新旧文件名
必须在同一驱动器中,否则会出错。对当前打开的文件不能使用该语句。
7.FileCopy语句
【格式】FileCopy“源文件名”,“目的文件名”
252 中文 Visual Basic 6.0 实用教程—结构化程序设计

【功能】将源文件拷贝到目的文件,文件名可包含路径名。不能拷贝已打开的文件。
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 所示。在“文本的路径和文件名”文本框


中输入一个文件的路径和文件名后,单击“打开”按钮,即可在第一个文本框中显示出该文
件的信息。在“文本的路径和文件名”文本框中更改路径和文件名后,单击“保存”按钮,
即可将第一个文本框中的信息保存到该文件中。在“文本的路径和文件名”文本框中输入一
个已经存在的文件的路径和文件名后,单击“删除”按钮,即可将该程序删除。在“文本的
路径和文件名”文本框中输入一个已经存在的文件的路径和文件名,在“更名”明面的文本
框中输入一个新的文件名后,单击“更名”按钮,即可更改该文件的名称。

图 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

FLEN = LOF(1) '获得文件的长度


SY = Input(FLEN, #1)
Text1.Text = SY
Close #1
End Sub
Rem 删除
Private Sub Command2_Click( )
Dim SM As Variant
SM = Text2.Text
Kill SM
End Sub
Rem 改名
Private Sub Command3_Click( )
Dim SM, NM As Variant
SM = Text2.Text:NM = Text3.Text
Name SM As NM
End Sub
Rem 保存
Private Sub Command4_Click( )
Dim SM, SY As Variant
Dim FLEN As Long,i As Integer
SM = Text2.Text
Open SM For Binary As #1
SY = Text1.Text
FLEN = Len(SY) '这里的 SY 长度是文件长度的一半
For i = 1 To FLEN
Put #1, i * 2 - 1, Mid$(SY, i, 1) '一个汉字占两个字节
Next i
Close #1
End Sub
Private Sub Command5_Click( )
End
End Sub
在程序中,打开二进制文件和写入二进制文件的语句前面已经介绍过,这里就不再描述。
在使用 Kill 语句删除文件时,要确保该文件未被打开,否则会出现错误。使用 Name 语句对
文件进行改名操作时要注意新文件的扩展名要与老文件的扩展名相同,同时也要注意该文件
应该是未打开的。

7.4.4 项目拓展——“文本文件察看器”程序

“文本文件察看器”程序的运行效果如图 7-4-2 所示。在“打开文件”栏中包含一个下拉


列表框,在该列表框中选择一个要打开的文件名称后单击后面的“打开”按钮,即可打开该
文件。打开“文本文件 2”文件后,该程序的显示效果如图 7-4-3 所示。在“指定程序”文本
框中输入要打开的文件的路径,单击“打开”按钮,可打开指定的文件。
254 中文 Visual Basic 6.0 实用教程—结构化程序设计

1.“文本文件察看器”程序对象属性设置
创建窗体如图 7-4-2 所示。在窗体中,有 1 个标签对象、两个框架、1 个下拉列表框、两
个文本框对象和 3 个按钮对象。标签对象用于显示程序的标题“中文文件察看器”。两个框架
分别用于显示下拉列表框和制定程序。第 2 个文本框用于显示打开文件的内容。

图 7-4-2 程序运行后的显示效果 图 7-4-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 应用程序类型的名称和说明
应用程序类型名称 应用程序的说明

标准 EXE 程序 标准 EXE 程序(Standard EXE)是典型的应用程序,这类应用程序可以使用 VisualBasic 以前的版本进


行开发

ActiveX EXE 和 ActiveX 这类项目只在专业版和企业版中才有。ActiveX 控件是支持 OLE 的自动化服务器程序。这两种程序


DLL 程序 在功能上是一致的,只是包装不同。ActiveX EXE 程序包装成可执行文件,ActiveX DLL 程序包装
成动态链接库

ActiveX 控件 这类项目在专业版和企业版中才有,主要用于开发编程人员自己定义的 ActiveX 控件

VB 应用程序向导 使用应用程序向导可以在开发环境中直接建立新的应用程序框架。在开发自己的项目时,可以使用
这个工具,并参考它所提供的应用程序原始类型

数据工程 为编程人员提供开发数据报表应用程序的框架。自动打开数据环境设计器和数据报告设计器

IIS 应用程序 这类项目是专业版和企业版中添加的新内容。可以使用 Visual Basic 代码书写服务器方的 Intenet 应


用程序,用来响应来自浏览器的用户需求

外接程序 选择外接程序项目类型后,可以创建自己的 Visual Basic 外接程序,并在开发环境中自动打开连接


设计器

ActiveX 文 档 EXE 和 ActiveX 文档实际上是可以在支持超链接环境中运行的 Visual Basic 应用程序,简单地说就是 Web


ActiveX 文档 DLL 程序 浏览器。例如,Microsoft Intenet Explorer

DHTML 应用程序 这个项目是专业版和企业版中所特有的。使用 DHTML 应用程序工程,允许编程人员编写响应


HTML 页面上动作的 Visual Basic 代码,并且还需要将处理过程传递到服务器上

VB 企业版控件 这类项目是企业版所特有的,用于开发企业版应用程序。如果使用的是专业版软件,将会有“专业
版控件类型”
主菜单中各类菜单命令的作用
附录 2
附表 2-1 “文件”菜单
序 号 菜单项名称 菜单项功能

1 新建工程 建立一个新的工程文件

2 打开工程 打开一个已存在的工程文件

3 添加工程 在打开的工程组中增加一个新工程

4 移除工程 移除指定的工程

5 保存工程 保存当前正在编辑的工程

6 工程另存为 将工程按指定名称重新保存

7 保存窗体 保存当前窗体

8 窗体另存为 将窗体按指定名称重新保存

9 保存选择 仅保存选择的内容

10 保存更改的脚本 将更改后的脚本进行保存

11 打印 打印窗体或代码

12 打印设置 设置打印信息

13 生成工程 1.exe 生成当前工程(组)的 exe、dll、ocx 文件

14 生成工程组 对工程组中的每一个工程生成一个 exe、dll、ocx 文件

15 文件 1、2、3、4 最近打开的四个工程(.vbp)或工程组(.vbg)的名字

16 退出 退出 Visual Basic

附 表 2-2 “编辑”菜单
序 号 菜单项名称 菜单项功能

1 撤消 取消最近的一次操作

2 重复 重复最近的一次操作

3 剪切 将被选中的内容删除并放到剪贴板中

4 复制 将被选中的内容拷贝到剪贴板中

5 粘贴 将剪贴板中的内容粘贴到光标所在处

6 粘贴链接 把链接粘贴到一个有效的 DDE 源上

7 移除 将表从数据库中移除

8 删除 删除被选中的控件、文本或查看表达式等

9 从数据库删除表 将数据库表从数据库中物理删除
附录 2 主菜单中各类菜单命令的作用 259

续表
序 号 菜单项名称 菜单项功能

10 全选 选中代码窗口中所有内容

11 选择全部列 选择数据库表的全部列

12 表 对数据库表进行设置主键、插入和删除列等操作

13 查找 查找指定的字符串等内容

14 查找下一个 查找指定的内容下一次出现的位置

15 替换 查找指定的内容并用新的内容替换

16 缩进 使选择的文本行向右移一个 Tab 位置

17 凸出 使选择的文本行向左移一个 Tab 位置

18 插入文件 把一个已打开的文件代码插入到当前位置

19 属性仿法列表 在“代码”窗口中用下拉式列表框显示对象的属性和方法

20 常数列表 列出属性的有效值

21 快速信息 显示“代码”窗口中选择的变量等信息

22 参数信息 显示函数或语句的参数信息

23 自动完成关键字 输入一个能推测的单词的前几个字母后,VB 自动输入后面的字母

24 到行 移动数据库表的行

25 书签 建立或取消占位符,移动到下一个或前一个书签,清除所有书签

附表 2-3 “视图”菜单
序 号 菜单项名称 菜单项功能

1 代码窗口 激活相应对象的“代码”窗口

2 对象窗口 显示激活的对象

3 定义 显示光标所在处的变量或过程的定义

4 最后位置 在“代码”窗口中使光标回到上一次的位置

5 对象浏览器 显示对象浏览器,列出有关信息

6 立即窗口 在“立即”窗口中显示调试语句和输入命令的结果

7 本地窗口 在“本地”窗口中显示当前栈中的所有变量及它们的值

8 监视窗口 在“监视”窗口中显示当前观察表达式的值

9 调用堆栈 显示“调用堆栈”对话框,在中断模式下列出一个过程正在调用的其他过程

10 工程资源管理器 显示“工程资源管理器”窗口

11 属性窗口 显示“属性”窗口

12 窗体布局窗口 显示“窗体布局”窗口,可以用来预览和改变窗体的初次显示位置

13 属性页 显示用户控件的属性页

14 表 显示数据库表的列属性、引名称、关键字等

15 缩放 选择显示的比例

16 显示窗格 设置数据库表、查询设计网格、SQL 语句内容和结果等是否显示


260 中文 Visual Basic 6.0 实用教程—结构化程序设计

续表
序 号 菜单项名称 菜单项功能

17 工具箱 显示标准 Visual Basic 控件

18 数据视图窗口 显示数据视图窗口

19 调色板 激活并调用调色板

20 工具栏 显示工具栏

21 Visual Component Manager 显示可视化部件管理器

附表 2-4 “工程”菜单
序 号 菜单项名称 菜单项功能

1 添加窗体 在工程中加入一个窗体

2 添加 MDI 窗体 在工程中加入一个 MDI 文档界面窗体

3 添加模块 在工程中加入一个模块

4 添加类模块 在工程中加入一个类模块

5 添加用户控件 在工程中加入一个用户控件

6 添加属性页 在工程中加入一个新的或现有的属性页

7 添加用户文档 在工程中加入一个新的或现有的用户文档

8 添加 DHTML Page 在工程中加入一个新的 DHTML 页面

9 添加 Data Report 在工程中加入一个新的数据报表

10 添加 Web Class 在工程中加入一个新的 Internet Web 类

11 添加 Microsoft User Connection 在工程中加入一个新的用户连接

12 添加 ActiveX 设计器 显示可用的 ActiveX 设计器,并从中选择一种,加入到工程中

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 重新启动 在中断之后重新开始执行应用程序

附表 2-8“查询”菜单 (仅限于企业版和专业版中对 SQL Seiver 或 Orade 数据库)


序 号 菜单项名称 菜单项功能

1 运行 运行设计的数据库查询语句

2 消除结果 消除数据库查询结果

3 验证 SQL 语法 验证 SQL 语法的正确性

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 菜单编辑器 显示“菜单编辑器”对话框

4 选项 显示“选项”对话框,设置 Visua Basic 的编程环境

5 发布 发布应用程序

6 Source Safe 基于 Visual Basic Source Safe 数据库的操作

附表 2-11 “外接程序”菜单
序 号 菜单项名称 菜单项功能

l 可视化数据管理器 打开后可以访问或操作数据

2 外接程序管理器 装入或卸载 VisualBasic 的外接程序

附表 2-12 “窗口”菜单
序 号 菜单项名称 菜单项功能

1 拆分 用水平线分隔或取消代码窗口

2 水平平铺 在 MDI 模式中使“对象”、“代码”窗口和对象浏览器上下排列

3 垂直平铺 在 MDI 模式中使“对象”、“代码”窗口和对象浏览器左右排列

4 层叠 在 MDI 模式中使“对象”、“代码”窗口和对象浏览器层叠排列

5 排列图标 在窗口左下角排列最小化窗口的图标

6 窗口列表 显示所有打开的窗口

附表 2-13 “帮助”菜单
序 号 菜单项名称 菜单项功能

1 内容 运行帮助,显示帮助的目录和索引

2 索引 打开帮助系统
附录 2 主菜单中各类菜单命令的作用 263

续表

序 号 菜单项名称 菜单项功能

3 搜索 打开在线文档

4 技术支持 运行帮助系统,显示 Visual Basic 产品的支持信息

5 Web 上的 Microsoft 显示一个包含 Internet 网址的菜单

6 关于 Microsoft Visual Basic 显示“关于”对话框


工具箱中基本控件工具的名称和功能
附录 3
附表 3 工具箱中基本控件工具的名称和功能
图 标 名 称 功 能

Pointer(指针) 这是工具箱中惟一没有控制功能的对象。在某—控件被加入到窗体中后,可以移动它的位置,
改变大小。当指针对象被选定后,只能移动控件以及改变大小。当向窗体中添加某一控件后,
指针对象将被自动选定

PictureBox(图片框) 用来显示一幅图画。也可作为一个容器,接收图片方式的输出,还可以像窗体一样作为其他
控件的载体

Label(标签) 用来显示不想让其他用户改变的文本,例如一幅画的标题

TextBox(文本框) 用来显示可以进行编辑的文本。与 Label(标签)控件相比,用户可以改变文本框中的内容

Frame(框架) 用来建立一个组合的功能框架。可以把某些控件放入其中,实现某个特定功能。当 Frame 框


移动时,放置在里面的控件也跟着移动,并且控件不能从 Frame 框中移出

CommandButton(命 这是一个比较常用的控件,用来建立实现命令的按钮
令按钮)

CheckBox(复选框) 也叫复选按钮。该控件给用户一个 True/False(真/假)或者 Yes/No(是/否)的选择。使用复


选框控件组可以实现多重选样。从复选框控件组中,用户能选择一个或多个选项,也能在程
序中设置它们的值

OptionButton( 选 项 也叫单选框或单选按钮。这个控件是对话框中常见的组成部分,当在对话框中放置了多个选
按钮) 项按钮控件后,程序运行时用户只能从中选中一个

ComboBox( 组 合 用于将 TextBox(文本框)与 ListBox(列表框)组合在一起,能在文本框中输入信息或选取列


框) 表框中的内容

ListBox(列表框) 用来显示可做单一或多个选择的列表项。如果列表项太多,一个滚动条将自动加到列表框中

Hscrollbar( 水 平 滚 提供一个可视的工具,用它可以快速浏览一个具有很多条目的列表框或拥有大量信息的文本
动条) 框,也可以作为一个输入的指示设备,例如控制电脑游戏中的声音

Vscrollbar( 竖 直 滚 它的功能和水平滚动条基本相同,只是显示的方向不同
动条)

Timer(时钟) 实现以规则的时间间隔执行程序代码来触发某种事件,它在程序运行阶段是不可见的

DriveListBox( 驱 动 使用这个控件能够显示在系统中所有可用驱动器的列表,用户可以在运行阶段选择一个可用
器列表框) 的驱动器

DirListBox( 目 录 列 它和驱动器列表框的作用很相似,用于显示目录及路径
表框)

FileListbox(文件列 用于显示当前目录中所有文件的列表框,它和驱动器列表框、目录列表框结合起来使用,将
表框) 实现文件的查询功能
附录 3 工具箱中基本控件工具的名称和功能 265

续表
图 标 名 称 功 能

Shape(形状) 在设计程序时可以在 Form 窗口中绘制各种图形,例如长方形、正方形、椭圆、圆、带有圆角


的矩形和正方形等

Line(直线) 在设计程序时可以在 Form 窗体中画线

Image(图像框) 可以在窗口中显示一个位图或图标。与 Picture(图片框)相比,图像框中的 Stretch(伸展)属性


可以使图片适应图像框的大小而做全幅显示

Data(数据) 通过 Form 窗口的约束控制,从数据库中存取数据

OLEContainer(OLE 可以在某一应用程序中嵌入其他应用程序对象
容器)
Visual Basic 6.0 试卷
附录 4
试卷(A)

班级_____________ 姓名______________ 成绩___________

一、填空(40 分,每个填空 1 分)

1.Visual Basic 语言是在________语言的基础之上推出的。


2.启动中文 Visual Basic 的方法通常有________种。
3.工程文件的后缀是________,窗体文件的后缀是________,标准模块文件的后缀是
_________,类模块文件的后缀是________。
4.对象属性的设置可以有两种方法,一种是_________,另一种是_________。
5.在 VB 中,属性是对象的________,方法是对象的_______。事件是对象的_______。
6.Int(−10/3)的值是________,Fix(−10/3)的值是________,12\5 的值是________,12 Mod
7 的值是________。
7.产生三位正整数的式子是________。从一个四位正整数(N)中获取个位数字的式子
是________。
8.VB 中变量、符号常量、自定义函数、对象、类和模块的名称以_______或________
开头,变量名称不可以超过________个字符。一个汉字相当于________个字符。
9.一行语句允许最多_______个字符,一行中的多条语句之间必须用________分隔。
10.一行语句可以分多行书写,在续行的前一行末尾应加入_______。
11.Visual Basic 中的数据类型可分为________和________两大类。
12.如果没有声明变量的数据类型,则该变量将被默认为是________类型。
13.Abs(−8.8)=________,Asc(“Cde”)=________,Chr(68)= ________,Len(“A 好 4”)=
________,Str$(−12)+Str$(12)= ________。
14.Val(“52”)+Val(“32abc”)=________,Len(Space(8))=________,String$(3,“中国”)=
__________。
15.Left(“中华人民共和国",4)= ________,Right(“中华人民共和国",3)= _________,
Mid(“中华人民共和国"”,2,3)= _________,”ABC”&567=_________。
16.3 * 2 = 6 Or 5 <= 3 的 值 是 _________。
附录 4 Visual Basic 6.0 试卷 267

二、回答问题(10 分)

1.表达式有几种?算术运算符包括哪些?它们的运算顺序是怎样的?
答:(4 分)

2.将下列 Visual Basic 表达式转化为数学代数式。


(1)N1*x^2+2*N2*X+N3+15*Abs((6−3/2)+4)−20
(2)1−1/(1− (1/(1−1/X)))
答:(4 分)
(1)

(2)

3.控件对象的 Enabled 属性和 Visible 属性有什么不同?


答:(2 分)
(1)

(2)

三、分析程序运行结果(30 分)

1.Private Sub Form_Load()


Show
If "AB">="ABC" Then Print "1" Else Print "2"
If 3 Mod 2=1 And Int(10/2)= 10/2 Then Print "1" Else Print "2"
If 5 Mod 3=Int(7/2) Then Print "1" Else Print "2"
End Sub
答:(3 分)

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 分)

5.Dim R As Single, L As Single, S As Single, V As Single


Const PI As Single = 3.1415926
附录 4 Visual Basic 6.0 试卷 269

Private Sub Command1_Click()


L= 2 * PI * R
Label1.Caption = "圆周长是:"
Label2.Caption = L
Command5.Enabled = True
Command1.Enabled = False
End Sub
答:(7 分)
(1)
(2)
(3)
(4)
(5)
(6)
(7)
(8)
(9)
6.For A=4 To 1 Step -2
For B=1 TO 4 STEP 2
If A=B Then Exit For
Print A,B
Next B
Next A
答:(4 分)

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 分)

1.Visual Basic 语言是在________语言的基础之上推出的。


2.启动中文 Visual Basic 的方法通常有________种。
3.工程文件的后缀是________,窗体文件的后缀是________,标准模块文件的后缀是
________,类模块文件的后缀是________。
4.对象属性的设置可以有两种方法,一种是________,另一种是________。
5.在 VB 中,属性是对象的________,方法是对象的________。事件是对象的________。
6.Int(8/5)的值是________,Fix(−8/3)的值是________,17\5 的值是________,16 Mod 7
的值是________。
7.产生二位正整数的式子是________。从一个五位正整数(N)中获取个位数字的式子
是________。
8.VB 中变量、符号常量、自定义函数、对象、类和模块的名称以________或________
开头,变量名称不可以超过________个字符。一个汉字相当于________个字符。
9.一行语句允许最多________个字符, 一行中的多条语句之间必须用________分隔。
10.一行语句可以分多行书写,在续行的前一行末尾应加入________。
11.Visual Basic 中的数据类型可分为________和________两大类。
12.如果没有声明变量的数据类型,则该变量将被默认为是________类型。
13.Abs(−10.6)=________,Asc("ABC")=________,Chr(66)=________,Len("ABCDEFG")=
________,Str$(65)+Str$(−32)=________。
14.Val("26")+Val("12AB")=________,Len(Space(6))=________,String$(3,”非典”)=
________。
15.Left("2008 年北京奥运",5)= ________,Right("2008 年北京奥运",4)= ________,
Mid("2008 年北京奥运",6,2)= ________,"北京"&2008=________。
16.5−2 =4 Or 5>= 3 的 值 是 ________。

二、回答问题(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 分)

6.For A=1 To 4 Step 2


For B=5 TO 2 STEP -2
If A=B Then Exit For
Print A,B
Next B
Next A
答:(3 分)

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

程序的窗体中有多个控件对象:1 个窗体、2 个按钮、4 个时钟和 2 个标签,如图 3 所示。


它们的主要属性设置如表中所示。对象的序号按从上到下、从左到右的顺序依次排号。
窗体对象的序号为 1。窗体对象的 StartUpPosition 属性设置为“2−屏幕中间”。

图3

控件对象的属性设置如下:
序 号 类 别 名 称 Caption 文字特点或 Interval Enabled

1 窗体 Form1 字母水平来回移动 12 号、黑色 True

2 时钟 Timer1 无 Interval=80 False

3 时钟 Timer2 无 Interval=80 False

4 时钟 Timer3 无 Interval=3000 False

5 时钟 Timer4 无 Interval=3000 False

6 按钮 Command1 开 始 12 号 True

7 标签 Label1 空 16 号、红色 True

8 标签 Label2 空 16 号、红色 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程序的运行结果

程序 1 运行结果 程序 2 运行结果 程序 3 运行结果

程序 4 运行结果 程序 5 运行结果 程序 6 运行结果

第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/

You might also like