第5章 数组 5.1 数组概述 5.2 静态数组和动态数组 5.3 数组的基本操作 5.4 控件数组 5.5 数组在自定义数据类型中的应用
5.1 数组概述 例5.1 计算50个职工的平均工资,统计并显示高于平均值的人数。 用简单变量和循环,求平均工资的程序段如下: 分析: 5.1 数组概述 例5.1 计算50个职工的平均工资,统计并显示高于平均值的人数。 用简单变量和循环,求平均工资的程序段如下: 分析: (1)S只能存放一个职工的基本工资,无法统计高于平均分的人数 (2)若用简单变量保存50个职工的基本工资,则需定义50个变量和使用50句输入语句 sum = 0 For i = 1 To 50 S = val(InputBox(“请输入基本工资:”)) sum = sum + S Next i Print “平均工资是:”;sum/50
用数组编写的程序 Private Sub Form_Click() Dim S(50) As Single,I%,sum!,n% ' 声明数组s sum = 0 For I = 1 To 50 ' 输入成绩,求分数和 S(I) = Val(InputBox(“请输入基本工资:”)) sum = sum + S(I) Next I Print “平均工资是:”;sum/50 n = 0 For I = 1 To 50 ‘ 统计高于平均值的人数 If S(I) > sum/50 Then n = n + 1 Print “高于平均工资的人数是:”; n End Sub 本章目录
5.1.1 数组的概念 数组: 一组相同类型的变量的集合。 作用: 使用:必须先显式声明后使用 分类: 用一个数组名代表逻辑上相关的一批数据,用下标表示该数组中的各个元素,和循环语句结合使用,使得程序书写简洁。 使用:必须先显式声明后使用 分类: 一维数组和多维数组,取决于下标的个数 静态(定长)数组和动态(可变长)数组 本章目录
5.1.2 一维数组及声明 一维数组的声明格式: Dim 数组名(下标) [As 类型] 作用:声明数组名、类型、维数、数组大小,并在内存分配一块连续的区域 说明: 下标:指明数组的大小,声明时必须为常数,不可以为表达式或变量 下标的形式:[下界 To] 上界,下标下界最小可为-32768,最大上界为32767,通常可省略下界,其默认值为0,可通过Option Base n语句重新设定 数组大小为:上界-下界+1 可以用类型符代替[AS 类型],类型符必须写在数组名之后。 Dim A(10) AS Integer 可以写成:Dim A%(10) 本章目录
Dim mark(99) As Integer 声明了一维整型数组mark,共有100个元素,下标范围为0 ~ 99 mark数组的各元素是mark(0),mark(1),…,mark(99); mark数组内存分配如下: mark(99) mark(98) … mark(2) mark(1) mark(0) 每个数组元素有一个唯一的顺序号,下标不能超出声明时的上、下界范围,否则会产生“下标越界”错误 数组元素的使用规则与同类型的简单变量相同 本章目录
5.1.3 多维数组及声明 Dim 数组名(下标1[,下标2,…]) [As 类型] 说明: 例:Dim x(2,4) As Long 下标个数:决定了数组的维数 数组大小:各维大小的乘积 每一维的大小为上界-下界+1 例:Dim x(2,4) As Long 声明了一个长整型的二维数组 x;共占据3×5个长整型变量的空间 x(1,4) x(1,3) x(1,2) x(1,1) x(1,0) x(2,4) x(2,3) x(2,2) x(2,1) x(2,0) x(0,4) x(0,3) x(0,2) x(0,1) x(0,0) Dim Array(1 to 3,0 to 4) as integer Dim N%(2,1 to 3,4) 本章目录
5.1.5 与数组有关的语句及函数 1.Option Base语句 Option Base 0|1 2.UBound|LBound函数 作用:重新定义数组下标的起始值为0或者1 说明:该语句一定要在窗体模块的通用段或者标准模块中声明。 2.UBound|LBound函数 UBound|LBound(<数组名>[,数组维序号]) 作用:返回指定数组的下标上界(下标最大值)或下标下界(下标最小值)。 Dim a%(100,0 to 3,-3 to 4) Print LBound(a,1),UBound(a,1) Print LBound(a,3),UBound(a,3)
3. Array函数 格式: 作用:先计算各个表达式的值,然后将表达式1、表达式2、表达式3等的值依次赋值给数组的各个元素。 说明: 例如: Dim A( ) As Variant “表达式列表”可以是任意基本类型数据,各个表达式之间用逗号分隔。 用Array函数给数组赋值时,数组名后面的括号可以省略 Array函数只能对一维数组进行初始化。 Option Base 1 Private Sub Form_Click() Dim A() As Variant, B() As Variant, I% A() = Array(1, 2, "AB", #7/2/2010#, 5.6) B = Array("abc", "123", "t56") For I = 1 To UBound(A) Print A(I); " "; Next I Print For I = 1 To UBound(B) Print B(I); " "; End Sub
4. Join函数 格式: 作用:将指定“数组”的各个元素按指定的“分隔符(或空格)”连接成字符串。 说明: (1)函数的返回值是字符型。 (2)只需要给出数组名的名称,不需要加括号和下标。 (3)分隔符是字符型,一定要加引号“""”
5. Split函数 格式: 作用:将“字符串”按指定的“分隔符”分隔成一个个数组元素,赋值给字符数组。 说明: (1)“字符串”:可以是多个字符串表达式,各个字符串表达式之间用逗号分隔。 (2)“分隔符”:可以是任何字符型,分隔符两边要加双引号“""”。 (3)Split函数与Join函数互为反函数。
6. For Each-Next语句 专门用于数组或对象集合,其格式为: 循环体 Next [成员] 说明 For Each 成员 In 数组名 循环体 Next [成员] 说明 (1)“成员”是一个变体型变量,它是为循环提供的,可以是任意的合法变量名。 (2)“数组名”后面没有括号和下标。 Dim MyArray(1 to 5),x For Each x In MyArray Print x; Next x
5.2 静态数组和动态数组 静态数组 动态数组 声明数组时给出数组的下标上界 也叫定长数组 编译时开辟内存区域 声明数组时不给出数组的下标上界,需要的时候用ReDim语句临时定义 也叫可变长数组 运行时开辟内存区域
5.2.1 静态数组及其声明 一维静态数组的声明格式: ① Dim 数组名(下标上界) [AS 数据类型名称] ② Dim 数组名(下标下界 To 下标上界) [AS 数据类型名称] 例5.1 利用随机函数产生20个[0~100]之间的随机整数作为学生考试成绩,以每行5个成绩打印在窗体上,并统计出最高分、最低分和平均分。
Option Base 1 Private Sub Command1_Click() Dim S(20) As Integer, i%, Max!, Min!, Total!, avgS! For i = 1 To 20 S(i) = Int(Rnd * 101) Print S(i), If i Mod 5 = 0 Then Print Next i Max = S(1): Min = S(1) Total = S(1) For i = 2 To 20 Total = Total + S(i) If S(i) > Max Then Max = S(i) If S(i) < Min Then Min = S(i) avgS = Total / 20 Print Print "最高分:"; Max, "最低分:"; Min Print "平均分:"; avgS End Sub
5.2.2 动态数组及其声明 建立动态数组要分两步: 1、用Dim 语句声明数组,但不能指定数组大小 Dim 数组名( ) As 数据类型 2、用ReDim语句动态地分配元素个数 ReDim 数组名 (下标1[,下标2…]) [As 类型] 例:Dim A ( ) As Single Sub Form_Load( ) … ReDim A(4,8) End Sub 本章目录
定义动态数组的注意事项 Dim是说明性语句,可出现在程序的任何地方,而ReDim是可执行语句,只能在过程中 在过程中可多次使用ReDim语句来改变数组的大小,但不能改变维数和类型,且每次使用ReDim语句都会使原来数组中的值丢失 可在ReDim后加Preserve参数保留数组中的数据 本章目录
例5.3 编程输出fibonacci序列的前n个数,其中 n在程序运行时由用户输入,要求每行输出5个。 Private Sub Command1_Click() Dim a() As Single, n%, i% n = Val(InputBox("请输入大于2的值:")) ReDim a(1 To n) a(1) = 1: a(2) = 1 '给前2个元素赋值 For i = 3 To n a(i) = a(i - 1) + a(i - 2) '计算序列中第3项到第n项的值 Next i For i = 1 To n Print a(i), '打印序列中的值 If i / 5 = i \ 5 Then Print '每行打印5个数,换行 End Sub
例5.4 输入整数n,显示出具有n行的杨辉三角形。 Private Sub Command1_Click() Dim s() '声明动态数组s Dim i%, j%, n% n = Val(Text1.Text) ReDim s(1 To n, 1 To n) '重新声明数组大小 Picture1.Cls For i = 1 To n s(i, 1) = 1 '第一列元素都为1 s(i, i) = 1 '对角线元素都为1 Next i For i = 3 To n For j = 2 To i - 1 s(i, j) = s(i - 1, j - 1) + s(i - 1, j) Next j For j = 1 To i Picture1.Print Spc(4 - Len(Str(s(i, j)))); s(i, j); '输出各元素,每个元素占4列 Picture1.Print '换行 End Sub
5.3 数组的基本操作 5.3.1 数组的输入 可通过TextBox控件或InputBox函数逐一输入 在输入大量数据时,一般不使用InputBox()函数,而是使用TextBox控件,再加某些技术处理。 Dim s(3,4) As Single For i = 0 To 3 For j = 0 To 4 s(i,j) = Val(InputBox(“输入” & i &“,” & j & “元素的值”)) Next j Next i 本章目录
例5.5 在文本框中输入一系列的数据,输入的数据只能为数值(包括0~9、小数点、负号等组成的字符串),不同数之间以逗号为分隔符,对输入的数据允许修改和自动识别非数字数据。输入结束后单击“确定”按钮,将输入的数据分离出来,放入数组中。分离的结果在图形框中打印出来。
5.3.2 数组的赋值 在VB中,将一个数组的值赋给另一个数组,只要一条简单的赋值语句即可,例如: 在数组对数组赋值时,要注意下面几点: (1)赋值号两边的数据类型必须一致。 (2)如果赋值号左边是一个动态数组,则赋值时系统自动将动态数组ReDim成右边同样大小的数组。 (3)如果赋值号左边是一个定长的数组,则数组赋值出错。 Dim a() As Variant, b() As Variant, i% a = Array(1, 3, 5, 7) b = a '将数组a的各元素赋给数组b对应的元素 For i = 0 To 3 Print b(i); Next i
5.3.3 数组的输出 一维数组的输出使用单层For-Next循环,二维数组的输出使用双重For-Next循环。 对于方阵或者矩阵的输出,必须用双重循环的固定模式,内循环控制每一行的元素,外循环控制行数,在内循环外部用一条Print语句表示换行。 For i = 1 To 2 For j = 1 To 4 Print x(i, j); '输出数组元素的值 Next j Print '换行 Next i
5.3.4 求数组极值及数组元素交换 求数组最大值 数组元素交换 一般先取第一个数为最大值的初值,然后依次将每一个数与最大值比较,若该数大于最大值,则将最大值修改为该数。 数组元素交换 如果要将最大值与数组中元素交换,还需要在求最大值时保留最大值元素的下标,最后再交换。
t = a(0): a(0) = a(imin): a(imin) = t 举例:求最小值并交换 imin 下标 1 2 3 4 5 6 7 8 9 初值 26 43 61 87 33 19 37 59 76 69 下标 1 2 3 4 5 6 7 8 9 交换 19 43 61 87 33 26 37 59 76 69 t = a(0): a(0) = a(imin): a(imin) = t 本章目录
例5.6 求一维数组中各元素之和、最小元素,并将最小元素与数组中最后一个元素交换。 Private Sub Form_Click() Dim arrN(), Min%, i%, Sum%, imin%, temp% arrN = Array(12, 4, -72, 6, -3, 6, 82, 57) Print "初始数组元素为:" For i = LBound(arrN) To UBound(arrN) Print arrN(i); Next i Min = arrN(0): imin = 0 '设置最小值初始值,记下最小值下标 Sum = arrN(0) For i = LBound(arrN) + 1 To UBound(arrN) Sum = Sum + arrN(i) '求数组元素之和 If arrN(i) < Min Then Min = arrN(i): imin = i ‘将最小值与最后一个元素交换 If imin<>UBound(arrN) then temp = arrN(UBound(arrN)) arrN(UBound(arrN)) = arrN(imin) arrN(imin) = temp End if …… End Sub
5.3.5 数组排序 排序 将一组数按递增或递减的次序排列 常用的排序算法 选择法 冒泡法 插入法 合并排序 本章目录
1. 选择法排序 基本思想 对于有n个数的数组,按递增次序排序的步骤 每次在若干个无序数中找最小(大)数,并放在相应的位置 2) 除去已排好序的数,在其余数中选出最小的数,与未排序数中的第1个数交换位置。 3) 重复步骤 2),最后构成递增序列。 本章目录
例5.7 对已知存放在数组中的6个数,用选择法按递增顺序排序。 原始数据 8 6 9 3 2 7 a(0) a(1) a(2) a(3) a(4) a(5) 第1轮比较 2 6 9 3 8 7 第2轮比较 2 3 9 6 8 7 第3轮比较 2 3 6 9 8 7 第4轮比较 2 3 6 7 8 9 第5轮比较 本章目录
2. 冒泡法排序 基本思想 1)从第一个元素开始,对数组中两两相邻的元素比较,将值较小的元素放在前面,值较大的元素放在后面,一轮比较完毕,一个最大的数沉底成为数组中的最后一个元素,一些较小的数如同气泡一样上浮一些位置。 2)n个数,经过n-1轮比较后完成排序。 本章目录
例5.8 用冒泡排序法实现例5.7的问题。 原始数据 8 6 9 3 2 7 a(0) a(1) a(2) a(3) a(4) a(5) 例5.8 用冒泡排序法实现例5.7的问题。 原始数据 8 6 9 3 2 7 a(0) a(1) a(2) a(3) a(4) a(5) 第1轮比较 6 8 3 2 7 9 第2轮比较 6 3 2 7 8 9 第3轮比较 3 2 6 7 8 9 第4轮比较 2 3 6 7 8 9 第5轮比较 本章目录
5.3.6 插入数据 在一组有序数据中插入一个数,使这组数据仍然有序。 基本思想: 首先要查找待插入数据在数组中的位置k; 然后从最后一个元素开始往前直到下标为k的元素依次往后移动一个位置; 第k个元素的位置空出,将数据插入; 例5.9 要在有序数组a中插入数值x(x值通过文本框获得,假定为15)的过程如图5.15所示。 图5.15 插入元素示意图
5.3.7 删除数据 删除数据操作首先要找到欲删除数组元素的位置k,然后从第k+1到第n个位置各向前移动一位,最后将数组元素个数减1。 例5.10 要从数组a中将与变量x(假定值为10)的值相同的数组元素删除。 图5.17 删除数据操作示意图
5.4 控件数组 5.4.1 控件数组的基本概念 控件数组由一组相同类型的控件组成,这些控件具有相同的名称和同样的属性设置。 控件数组的名称由Name属性指定,而数组中的每个元素则由Index属性指定。Index属性值一般从0开始。 和普通数组一样,控件数组的下标也放在圆括号内,例如Command1(0)、Command1(1)。 控件数组不但具有相同的名称、相同的属性,而且共享同样的事件过程。
Private Sub Command1_Click( Index As Integer ) … End Sub 通过判断Index的值,可以判定单击了控件数组中的哪一个命令按钮 第一个命令按钮的Index值为0,第二个命令按钮的Index值为1
5.4.2 建立控件数组 设计时建立控件数组的步骤如下: (1)在窗体上画出某个控件。 (2)选中该控件,进行“复制”和“粘贴”操作,系统会提示:“已有了命名的控件,创建一个控件数组吗?” 单击“是”按钮后,就建立了控件数组元素,进行若干次“粘贴”操作,就建立了所需个数的控件数组元素。 (3)进行事件过程的编码。 例5.11 建立含有4个命令按钮的控件数组,当单击某个命令按钮时,分别显示不同的图形或结束操作。
5.4.2 建立控件数组 运行时建立控件数组的步骤如下: 例5.12 建立一个图片展示的程序,当单击窗体时,可在窗体上显示不同的图片。 1)在窗体上画出某控件,设置该控件的Index属性值为0,表示该控件为数组,也可以对该控件的其他属性进行设置,这是建立的第一个元素。 2)编程时,通过Load方法添加其余的若干个元素,也可以通过Unload方法删除某个添加的元素。 3)加载控件数组的新元素时,大多数属性值将从数组中的第一个元素复制,但不会自动把Visible、Index和TabIndex数组值复制到控件数组的新元素中。为了使新添加的控件可见,必须将其Visible属性设置为True。 例5.12 建立一个图片展示的程序,当单击窗体时,可在窗体上显示不同的图片。
用户定义数据类型(P58) 将不同类型信息作为一个整体来描述 Type 自定义类型名 元素名1 As 数据类型名 … 元素名n As 数据类型名 End Type 【举例】 Type StudType ' StudType为自定义类型名 Name As String*5 ' 姓名 Sex As String*1 ' 性别 Telephone As Long ' 电话 School As String*10 ‘ 学校 End Type 自定义类型不能在过程内定义,一般放在标准模块文件中,默认为Public; 若在窗体模块的通用声明段定义,必须加Private 本章目录
自定义类型变量的声明和使用 定义了自定义类型,就可在变量的声明时使用 Dim 变量名 As 自定义类型名 例如: Dim S1 As StudType,S2 As StudType 声明S1、S2为两个同种类型的变量 本章目录
注 意 不要混淆StudType和S1,前者如同Integer等类型名,后者根据该类型分配所需的内存空间,存储各成员数据。 自定义类型变量和数组的区别 相同之处:它们都是由若干个成员组成; 不同之处:前者的成员代表不同性质、不同类型的数据,以各个不同的成员名表示;而数组一般存放的是同种性质、同种类型的数据,以下标表示不同的元素。 本章目录
自定义类型变量元素的引用(P118) With 变量名 引用自定义类型变量中的某个成员,形式如下: 自定义类型变量名.成员名 【举例】S1.Name ‘S1变量中的姓名 S1.Sex ‘性别 可利用With语句简化成员引用 With 变量名 语句块 End With With S1 .Name = "张华" .Sex = "男" .School="同济大学" End With 本章目录
5.5 数组在自定义数据类型中的应用 自定义类型数组就是数组中的每个元素都是自定义类型 例5.13 利用自定义数据类型,声明一个职工数据类型,该数据类型包括的元素有:EmpNo(职工号)、Name(姓名)、Salary(工资)。要求实现功能如下: 输入:单击“输入”按钮,输入一个职工的信息,最多不超过50个职工。 显示:单击“显示”按钮,在Picture1上显示已经输入职工的全部信息。 排序:单击“排序”按钮,则按工资递减的顺序排列,并在Picture2上显示有关信息。