第5章 数组 5.1数组的基本概念 5.2静态数组与动态数组 5.3数组的基本操作 5.4综合应用程序举例
5.1数组的基本概念 在实际应用中,常常要遇到处理相同类型的大量相关数据的情况。例如:处理N个学生某门课程的考试成绩,若用简单变量来表示,只能用n个变量X1,X2,X3,…,XN来分别代表每个学生的成绩,但这样变量太多将给编程带来许多不便,显然用相同的名称辅以序号来代表这些学生的成绩,将要方便得多,VB程序设计语言提供了这样一种数据表示机制——数组。数组是由一定数目的同类元素按一定顺序排列而成的结构类型数据。
5.1 . 1数组的定义 在VB中把一组具有同一名字、不同下标的下标变量称为数组,一个数组可以含有若干个下标变量,下标用来指出某个数组元素在数组中的位置。 数组应当先定义后使用,这点与其他类型的变量一样,目的是通知计算机为该数组分配一定内存区域,数组的名也就是这个区域的名,该区域的每个单元都有自己的地址,该地址用下标表示。 数组有一维数组和多维数组。下面介绍如何定义一维数组与二维数组。 一维数组定义格式: Dim 数组名([下标下界To]下标上界) As 类型名称 二维数组定义格式 Dim 数组名([第一维下标下界To]第一维下标上界,[第二维下标下界To]第二维下标上界) As 类型名称
5.1 . 1数组的定义 说明: 数组名的命名必须满足合法标识符的命名规则。类型名可以是任何VB所定义的合法类型:基本类型和用户自定义类型。 数组先定义后使用,未定义不能使用。 下标为整型常量,系统的下标下界默认值为0,可以在通用代码段用Option Base 1/0来设置下标的默认值为1/0。 当用Dim语句定义数组时,该语句把数组元素初始化为0或空字符串。 在定义数组时,下标可以是常数或常量表达式。
5.1 . 1数组的定义 例:定义一个能够存放6个整数的数组。 Dim A(5) As Integer ' 上面数组的定义语句给出了3各方面的信息: 规定的数组的名字: 数组名为A,即数组变量名为A; 规定数组的下标变化范围:下标下界默认值是0,下标上界在此定为5,这就是说数组A中有六个元素,这些数组元素的名字分别是A(0)、A(1)、A(2) 、A(3) 、A(4) 、A(5),括号中的数字称为下标; 规定了数组中可以存放的数据的类型: Integer为数组类型名(整型),它表示数组中每个元素的类型都是整型。 数组变量A的各数组元素在内存中连续排列: A(0) A(1) A(2) A(3) A(4) A(5)
5.1 . 1数组的定义 例:定义一个二维数组及概念释义。 Dim A(-3 To 1, 1 To 5) As Integer 该数组共有5×5=25个数组元素,这些数组元素按5行5列排列: A(-3,1) A(-3,2) A(-3,3) A(-3,4) A(-3,5) A(-2,1) A(-2,2) A(-2,3) A(-2,4) A(-2,5) A(-1,1) A(-1,2) A(-1,3) A(-1,4) A(-1,5) A(0,1) A(0,2) A(0,3) A(0,4) A(0,5) A(1,1) A(1,2) A(1,3) A(1,4) A(1,5)
5.1 . 2多维数组和数组下标界值 一个数组,如果只用一个下标就能确定一个数组元素在数组中的位置,那么它就是一维数组,即只有一个下标的下标变量所组成的数组称为一维数组。如果在数组中只能通过两个或两个以上的下标才能确定数组元素在数组的位置称为多维数组。两个下标为二维数组,三个下标为三维数组等等,多维数组的定义方法: Dim 数组名([第一维下标下界 To]第一维下标上界,[第二维下标下界To]第二维下标上界,[第三维下标下界To]第三维下标上界,…) As 类型名 多维数组在内存中所占的空间大小为:(所占空间长度应小于64kB) 维数1×维数2×维数3×维数4×…×类型字节数(长度) 如:Dim x(4,3,2,5) As Integer定义一个四维整型数组,该数组所占内存长度=5×4×3×6×2=720(字节)。
5.1 . 2多维数组和数组下标界值 在程序中,可能需要知道数组的上界值和下界值,VB提供确定下标上界、下界值的函数为LBound和UBound。其格式为: LBound(数组[,维]) UBound(数组[,维]) LBound返回一个数组中指定维的下界,UBound返回指定维的上界,其中“数组”是一个数组名,“维”是指要测试的维。 对于一维数组,参数“维”可以省略,如果要测试多维数组,则“维”不能省略。如: Dim A(-3 To 4,1 To 2, 3 To 5, -1 To 6 )As Integer LBound(A,1)返回数组A第一维的下界,值为-3 UBound(A,3)测试数组A第三维的上界,值为5。
5.2静态数组与动态数组 上一节,我们已学习了数组的定义及基本基本概念,在本节中我们将重点讲述静态数组与动态数组。 所谓静态数组是指在编译阶段给数组分配内存空间,该数组没有运行时已有了相应的内存区间,静态数组变量的值在定义该变量的程序运行结束后,该变量所拥有的内存空间不释放,变量的值仍在内存中,再次运行时,将上次运行的结果作为该变量的初始值,在定义静态数组时要求在编译阶段便知道该数组的元素个数。只有当整个应用程序退出时,所占内存才会被释放。 与静态数组相反,动态数组在定义时并不知道数组的大小,要求在运行期确定,并根据需要在运行期可改变数组的大小,这便是动态数组。
5.2.1静态数组 在VB中静态数组定义方式有三种: 在全局模块中使用Global语句定义,说明该数组为全局数组。 在窗体模块级或标准模块级用Dim定义。此时的数组可理解为局部数组。 在过程中用Static语句直接定义数组,或者用Static定义过程,而在过程中使用Dim语句定义数组,这样的数组仍然是静态数组。
5.2.1静态数组 例 静态与非静态数对比: 运行结果如上图,从图中可以看出,静态数组的数组元素的值在退出运行后仍然保留上次运行结果。 例 静态与非静态数对比: Private Sub Command1_Click() Static a(4) As Integer,start As Integer ‘a为静态数组,start为静态变量 Dim b(4) As Integer, i As Integer If start = 0 Then Print "静态数组:",,"非静态数组:" For i = 0 To 4:b(i) = b(i) + I: Next i For i = 0 To 4:a(i) = a(i) + I:Next i For i = 0 To 4:Print a(i);:Next i Print , For i = 0 To 4:Print b(i);:Next i Print start = 1 End Sub 运行结果如上图,从图中可以看出,静态数组的数组元素的值在退出运行后仍然保留上次运行结果。
5.2.2动态数组 (1)动态数组的定义通常分两步完成: 在窗体、标准模块和过程中用Dim或Public声明一个没有下标的数组(括号不能省略)。 在需要使用该数组前用Redim语句定义数组的大小(数组元素个数),下标可为常量、变量或表达式,但变量或表达式此时必须有值。称为数组重定义。 (2)动态数组定义格式如下: Dim 数组名()As类型 '定义数组名 Redim[Preserve]变量名(下标) '重定义数组大小 重定义时,按新上下界重新分配存储单元。重新定义动态数组时,数组中的内容将被清除,如果在Redim语句中使用了可选项Preserve,则不清除原数组中的内容,但只能改变最后一维的大小(即不能改变数组的维数)。
5.2.2动态数组 (3)在使用动态数组时应注意以下几点: 使用Redim可重新定义数组的大小和维数,但不能改变数组的类型,如: Dim A() As Integer Sub Command1_Click() Redim A (4) Redim A(3,2) Redim A(6) A(1)=”Visual Basic” '此句有错,企图改变数组类型 End Sub 在建立局部动态数组时,可省略Dim语句。由Redim语句直接定义数组,使用Dim时,所定义数组的维数不超过8,直接用Redim定义数组,其维数可达60维。 在同一过程中,可多次使用Redim语句定义同一个数组,以改变数组大小和维数。
5.2.2动态数组 例 在窗体上显示杨辉三角形(如图所示)。 程序清单如下: Private Sub Form_Click() 例 在窗体上显示杨辉三角形(如图所示)。 程序清单如下: Private Sub Form_Click() Const max = 9, pos = 27 Dim i As Integer, j As Integer, n As Integer,triang() , '说明动态数组 Do n = InputBox("请输入杨辉三角的行数:") Loop Until n >= 1 And n <= max '合法性检查 ReDim triang(n) ‘数组重定义 triang(1) = 1 '生成第一行 Print Tab(pos - 2); triang(1) For i = 2 To n triang(i) = 1 For j = i - 1 To 2 Step -1 '生成第I行 triang(j) = triang(j - 1) + triang(j) Next j For j = 1 To i '显示第I行 Print Tab(pos - 2 * i + 4 * (j - 1)); triang(j); Print Next i End Sub
5.3 数组的基本操作 数组是一种结构类型,数组名通常表示该数组整体,但对数组的操作实际上是针对每个数组元素进行,对数组元素的访问是通过“数组名(下标)”的方式进行访问的,而下标是可以变化的,可用下标变量来表示,因此,程序中常常将数组元素的下标变量与循环语句结合。数组的基本操作包括数组和数组元素赋值、读取数组中的元素以及数组的输出等。
5.3.1数组和数组元素的赋值 (1)直接给指定数组元素赋值、或使用数组元素的值: A(5)=100 '给数组元素A(5)赋值 Temp=A(5) '读取数组元素A(5)的值,并将值赋给变量Temp (2)使用数组元素时要注意下标不能出界。是多维数组时,下标之间用逗号隔开。 (3)在VB中对数组的赋值就是对数组中的每个元素一一地赋值。可通过循环来实现。 例 给可存放10个整数的数组元素一次赋值为10,9,8,7,6,5,4,3,2,1。 Dim A(1 to 10) as Integer,I as Integer For i=1 to 10 A(i) = 11-i Next i
5.3.2 数组的输出 数组的输出同样是以数组元素为操作对象,一般也可通过循环来实现。 例 对上例中数组先赋值后,然后再输出。 例 对上例中数组先赋值后,然后再输出。 Private Sub Form_Click() Dim A(1 to 10) as Integer,I as Integer For I=1 to 10 A(i) = 11-i Next I Print A(I); '简单的输出 Print '起换行作用,接下来的输出在下一行中 Print "A(" & I & ")=" & A(I) & ","; '稍复杂的输出,结果更明了 End Sub
5.3. 3 For Each…Next语句 For Each…Next语句:目的是扫描整个数组的所有元素或集合中的所有成员,以便对这些成员或数组元素进行必要的处理。成员的取值顺序与数组元素在数组中的排列顺序一致,不需指明循环条件。它类似于循环语句,两者都指对某一组操作重复执行指定次数,但For Each…Next专门用于数组或对象“集合”,格式为: For Each 成员 in 数组 … [Exit For] Next [成员] 此处的“成员”必须是一个变体变量类型,为循环而设,表示某个数组元素的值,“数组”仅为一个数组名,不需括号,上、下界等。
5.3. 3 For Each…Next语句 例 For Each…Next使用实例。 Private Sub Form_Click() Dim a(8) As Integer, i As Integer Dim x_ELEM As Variant For i = 0 To 8 a(i) = i * 7 Next i Print For Each x_ELEM In a Print x_ELEM; Next x_ELEM End Sub
数组变量名=Array(数组元素初始值) 5.3.4 一维数组初始化 对数组元素进行初始化是任何程序语言都必须考虑的问题,在VB中,对数组元素进行初始化有多种方法,如:给元素赋值、通过InputBox从键盘上接收等,但这些方法都要占用运行时间,影响效率。为此,VB特提供函数Array。利用该函数可使数组在编译阶段(程序运行之前)被初始化,即得到初始值。 Array函数的使用可将一个数据集读入某个数组,格式: 数组变量名=Array(数组元素初始值)
5.3.4 一维数组初始化 说明: 数组变量名为在此之前定义的数组名。 初始值与相应数组元素一一对应,初始值相互之间用逗号隔开。 在初始化前对数组变量的定义不能是具体的数据类型,只能是Variant型,或为默认类型。 对于该数组变量可以不定义而直接由Array函数来确定数值变量如: A=Array(1,2,3,4) ,此时数组A为变体类型(Variant) 注意,这种初始化方法只能用来初始化一维数组,不能用来初始化多维数组。
5.3.4 一维数组初始化 例 程序举例如下: Private Sub Form_Click() Dim A As Variant Dim N1 As String, N2 As String Dim i As Integer number = Array("one", "Two", "Three") '未定义而直接使用数组变量 N1 = number(0) N2 = number(1) A = Array(1, 2, 3) '初始化A For i = 0 To 2 Print A(i); Next i Print N1; N2 End Sub 运行结果
5.4 综合应用程序举例 例1 统计某年级100名学生的成绩个分数段的人数,分段:0~9,10~19,20~29,……,90~99,满分。(学生的成绩由计算机机值产生) 分析:本问题可用多分支的IF或Select case语句来实现。在此我们用另一种方法来实现:注意到它的分段很有规律,每个分数段中的数值除以10再取整数部分的结果相同。如0~9之间的数值除以10再取整数部分的结果都是0,10~19之间的数值除以10再取整数部分的结果都是1。而这个整数部分正好可以作为计数数组的下标。 在下面的程序中,我们将成绩放在Score数组中,将个分数段的人数记在result数组中,数组元素result(0)中统计的是第一个分数段中的人数,即成绩在0~9的人数,数组元素result(1)中统计的是第二个分数段中的人数,即成绩在10~19的人数,以此类推。
5.4 综合应用程序举例 代码如下: Private Sub Form_Click() Dim score(1 To 100) As Single Dim result(0 To 10) As Integer Dim i As Integer, Index As Integer Print "100名学生的分数如下:" For i = 1 To 100 '给成绩数组赋随机值,并输出 score(i) = Int(Rnd * 101) '随机产生学生成绩[0-100] Print score(i); Tab((i Mod 10) * 5); '每行10列,列间距为5 Next i For i = 1 To 100 Index = score(i) \ 10 '算出该分数落在第Index段 result(Index) = result(Index) + 1 '该Index段中的人数增加1 Print "各分数段的人数如下:" For i = 0 To 10 Print result(i); End Sub
5.4 综合应用程序举例 例2 输入一个4×5的二维整数数组,输出数组元素的平均值及该数组。 例2 输入一个4×5的二维整数数组,输出数组元素的平均值及该数组。 Private Sub Form_Click() Dim A(1 To 4,1 To 5) As Integer, i As Integer, j As Integer Dim Average As Integer, Sum As Integer Sum=0 For i=1 To 4 For j=1 To 5 A(i, j)=Val(InputBox(″请输入A(" & Str(i) & "," & Str(j) & ")的值")) Sum=Sum+A(i,j) Next j Next i Average=Sum/20 Print "数组元素的平均值是:"; Average Print A(i, j); Print End Sub
5.4 综合应用程序举例 例3 比较法排序(升序排列)。 例3 比较法排序(升序排列)。 分析:设有10个数存放在数组A中,分别表示为:A(1),A(2),A(3),A(4),A(5),A(6),A(7),A(8),A(9),A(10)。 第1轮:先将A(1)与A(2)比较,若A(2)<A(1),则将A(1),A(2)中的值互换,A(1)存放较小者。再将A(1)与A(3),…,A(10)比较,并依次做出同样的处理,10个数中的最小者放入A(1)中。 第2轮:将A(2)与A(3),…,A(10)比较,并依次做出同样的处理,第1轮余下的9个数中的最小者放入A(2)中。 继续进行第3轮、第4轮……直到第9轮后,余下的A(10)自然就是10个数中的最大者。
5.4 综合应用程序举例 Private Sub Form_Click() Dim A(1 To 10) As Integer, temp As Integer,i As Integer, j As Integer Print "排序前:" For i = 1 To 10 '随机产生10个[10,99]的整数,并输出 A(i) = Int(Rnd * 90) + 10 Print " A(" & Str(i) & ")="; A(i);:If i Mod 5 = 0 Then Print Next i For i = 1 To 9 For j = i + 1 To 10 If A(i) > A(j) Then temp = A(i): A(i) = A(j): A(j) = temp End If Next j Print:Print "排序后:" For i = 1 To 10 End Sub
本章小结 本章介绍了数组的数组的基础知识及基本操作,并以实例介绍了数组的应用。数组的应用非常广泛,读者对数组的理解可能有一些困难,但只要认真学习和练习,这点困难是可以很容易克服的。