第六章数组【学习目的和要求】1.掌握静态数组的定义和程序设计方法2.掌握动态数组的定义和程序设计方法3.熟悉控件数组的创建和使用4.掌握数组常用算法的程序设计【学习要点】一.何时需要使用数组?在程序设计过程中,如果需要对一组同类型的很多数据进行处理时,就必须使用数组进行程序设计。比如求某班级80个学生某门课成绩的平均分,再统计所有高于平均分成绩的学生人数。如果不用数组,通过简单变量,要么定义80个变量来保存学生的成绩,光赋值语句就得写80行,要么采用循环程序设计,定义一个变量,通过80次循环来接收每个学生的成绩,并计算平均分。程序段如下:DimcjAsInteger,sumAsInteger,aveAsSingleDimiAsIntegerFori=1To80cj=InputBox(请输入第&i&个学生的成绩)sum=sum+cj'求总分Nextiave=sum/80'求平均分问题是:当求出平均分后,还需要统计成绩高于平均分的学生人数,而变量cj只能存放一个值,在本循环结束后,cj中存放的是最后一个学生的成绩,它无法同时保存80个学生的成绩,只能再编写程序重新输入80个学生的成绩,依次与平均分进行比较,程序段如下:Fori=1To80cj=InputBox(请输入第&i&个学生的成绩)IfcjaveThenn=n+1'统计成绩高于平均分的人数NextiPrint成绩高于平均分的人数有&n&个这样处理会带来2个问题:1.数据的输入量变为原来的2倍2.数据量很大,在第二次输入过程中很可能出现与第一次不一致的情况,造成数据统计的错误。在类似的问题上,如果采用数组处理就可以有效解决上述问题。数组在形式上可以看成为一组同类型的数据集合,每个数组元素拥有相同的名称,但根据其在数组中的位置分配一个唯一标识的序号,如本例中,可以定义一个数组cj(80)来表示成绩,数组名为cj,cj(1)表示第1个学生的成绩,cj(2)表示第2个学生的成绩,……,这样只要一次输入,就可以有效解决上面的问题。二.数组的形式1.一维数组在上例中,只要用一个下标就可以标识一个数组元素,这样的数组称为一维数组。比如定义一个一维数组a(10),表示数组名为a,数组中有11个元素(注意:VB中数组的下标默认为从0开始),分别是a(0)、a(1)、a(2)、……、a(10)。2.二维数组从形式上看,可以把一维数组看成是一个数列,适合于类型相同的一组数据的处理,但有的时候用一维数组处理就不能满足要求了。比如处理一个班50个人4门课的成绩,将其按总分从高到低的顺序进行排序。很显然,这是一张二维表,每个人的4门课成绩构成表中的一行,要表示其中每个人的成绩,都需要指定行和列两个下标才能唯一的确定,这时就需要定义一个二维数组。如定义一个数组cj(50,4),用cj(1,1)表示第一个人的第一门课成绩,cj(2,3)表示第二个人的第三门课成绩。象这样,需要两个下标才能确定一个数组元素在数组中的位置,这样的数组称为二维数组。从形式上看,二维数组就是一张二维表格。比如定义一个二维数组a(1To3,1To4),共有12个元素,分成3行4列,其中每个元素的分布如下表5-1所示:表5-1a(1,1)a(1,2)a(1,3)a(1,4)a(2,1)a(2,2)a(2,3)a(2,4)a(3,1)a(3,2)a(3,3)a(3,4)3.多维数组如果数组中的每个元素需要2个或2个以上的下标才可以标识,这样的数组统称为多维数组。比如三维数组a(3,4,2)中的每个元素都需要3个下标才能够唯一的确定。以后我们进行程序设计时,定义的数组一般不会超过三维,所以应重点掌握一维和二维数组的使用。三.数组的定义程序中用到的变量,可以不定义就使用,如果没有定义,系统会自动定义其类型为变体型。但数组不可以直接使用,所有的数组只有先定义才可以使用。VB提供了两类数组可以定义。1.固定大小的数组定义如果在程序设计时可以确定其大小和维数,这样的数组称为固定大小数组。比如:Dima(20)AsInteger,表示定义一个固定大小的数组a,有21个元素,下标从0到20。固定大小的数组一经定义,以后在程序中就不能再改变其大小和维数。例6-1以下定义数组的语句错误的是______。A.Dima(-3to5)AsIntegerB.Dima(1to6.7)AsSingleC.Dima(n)AsIntegerD.Dima(-2to3,2*3)AsInteger分析:选项A中定义一个整型的一维数组,分别为a(-3)、a(-2)、……、a(5),共9个元素;在VB中如果数组下标不是整数,系统会自动四舍五入取整,所以选项B等价于Dima(1To7)AsInteger;选项D表示定义一个整型的二维数组,其中第一维的下标从-2到3,第二维的下标从0到6,一共有6*7=42个元素;选项C是错误的,因为VB不允许用变量来定义数组,如果不能确定数组大小,定义时数组名后的()中也不能是变量,必须将其定义成动态数组:Dima()AsInteger,数组名后的()中不写任何内容。考虑以下定义数组的语句是否正确?1)ConstnAsInteger=6Dima(n)AsInteger2)Dima(n)AsIntegerConstnAsInteger=63)Dima(5To-3)AsInteger分析:定义1是正确的,这时n是符号常量,相当于常量6,所以Dima(n)AsInteger等价于Dima(6)AsInteger;定义2是错误的,因为在执行Dima(n)AsInteger之前并没有定义符号常量n,VB不允许用变量定义数组;定义3是错误的,因为定义数组时不允许其下界高于上界。2.动态数组定义如果在程序设计时不能确定数组的大小和维数,就必须定义动态数组。动态数组的大小和维数可以在程序运行时根据需要改变。动态数组的定义和固定大小数组不同,它一般分两个步骤进行:1)用数组名加()来定义动态数组比如需要定义一个整型的动态数组b,只能按以下格式定义:Dimb()AsInteger表示b是一个数组,但数组的大小和维数都不确定,以后在程序运行时可根据需要定义。注意:只能用数组名后加()来定义,不能写成b(n)或b(m,n)或b(,)等形式。2)用Redim重新定义动态数组大小动态数组只有用Redim重新定义后才可以使用。比如上面定义的数组b,如果在程序运行时需要定义其为10个元素的一维数组,则可以执行语句Redimb(1to10),若需要定义其为3行4列的二维数组,则可以执行语句Redimb(1to3,1to4)。一旦用Redim重定义动态数组后,该数组就可以象固定大小数组一样地使用。3.OptionBase1数组默认的下标下界是0,如果希望定义数组的下标从1开始,可以在模块的通用声明段中用OptionBase1说明。注意:1)OptionBase后面只可以是0或1,不能是其他数字。比如不能通过OptionBase2让数组的下标从2开始。2)OptionBase语句只可以出现在模块的通用声明段,不可以出现在过程中。四.数组的使用1.数组元素的引用数组定义后,可以通过下标来引用数组的每个元素。和数组的定义不同,引用数组元素时下标可以是变量、常量或表达式。例6-2以下引用数组元素的语句中正确的是_______。A.Dima(2,3)AsIntegera(1)=10B.Dima(3To6)AsSinglea(1)=1C.a(n+3)=a(n-1)+a(n)D.Dima(5)AsSinglea=1分析:选项A中定义一个3行4列的二维数组(注意:每一维的下标下界默认为0),每个数组元素必须用两个下标表示,比如,第一个元素应该为a(0,0),第2行第2列的元素应该为a(1,1)。不允许通过a(1)企图引用二维数组中的某个元素,所以选项A是错误的;选项B中定义一个单精度型一维数组,规定下标的范围从3到6,不存在下标为1的元素,所以引用a(1)会出现“下标越界”的错误;选项D中定义一个一维数组,数组名为a,拥有6个元素,分别是a(0)到a(5),对数组赋值只能分别对每个元素赋值,而不能通过给a赋值来达到给所有数组元素赋值的目的,程序中并不存在名称为a的变量,所以选项D是错误的;由于引用数组元素时允许下标是变量和表达式,所以选项C的含义是计算a(n-1)+a(n)的值,并将其赋给数组元素a(n+3),比如,当n为2时,该语句的功能是计算a(1)+a(2)的值,并将其赋给数组元素a(5),很显然,选项C是正确的。归纳一下:1)引用数组元素时要注意,下标不能越界,即数组元素的下标不允许比定义数组时的上界大,也不允许比下界小。2)一维数组元素用1个下标引用,二维数组元素必须用2个下标引用,依次类推。3)引用数组元素时,下标可以是变量和表达式。4)对数组元素操作时,不可以直接引用数组名,只可以引用单个数组元素。2.数组的相关函数数组的相关函数只需要掌握以下三个:1)LBound:获得数组某一维下标的下界格式:LBound(数组名)或LBound(数组名,维数)比如Lbound(a)表示返回数组a第一维下标的下界;Lbound(a,2)表示返回数组a第二维下标的下界。2)UBound:获得数组某一维下标的上界格式:UBound(数组名)或UBound(数组名,维数)例6-3执行以下程序段,输出结果是_______。Dima(-3To5)AsSingleDimb(3,4)AsIntegerPrintUBound(a),UBound(b,1)PrintLBound(a),LBound(b,2)分析:根据UBound和LBound函数的功能可以知道,第一行的输出结果是53,第二行的输出结果是-30。3)Array函数利用Array函数可以将一个变体型变量创建成一维数组,同时实现数组元素的赋值。例6-4执行以下程序段,第一行输出结果是_______,第二行输出结果是_______。PrivateSubForm_Click()DimaDimiAsIntegera=Array(1,2,3,4,5,6,7,8,9)Fori=0To3Printa(5-i);NextPrinta=Array(abc,123,def)Printa(1)EndSub分析:根据Array函数的功能,赋值语句a=Array(1,2,3,4,5,6,7,8,9)将变体型变量a创建成一个整型的一维数组,有9个元素,下标从0到8(注意:默认下标的下界为0),其中a(0)的值为1,a(1)的值为2,……,a(8)的值为9。For循环的功能是分别输出a(5)、a(4)、a(3)、a(2)的值,所以第一行输出结果为6543;执行赋值语句a=Array(abc,123,def)后,a被创建成一个字符串型的一维数组,有3个元素,下标从0到2,a(1)的值为123,所以第二行输出结果为123。例6-5执行以下程序段,输出结果是_______。PrivateSubForm_Click()Dima(9)AsVariantDimiAsIntegera=Array(1,2,3,4,5,6,7,8,9)Printa(2)EndSub分析:由于Array函数只能给变体型简单变量或变体型动态数组赋值,虽然程序中定义的a(9)是变体型数组,却是固定大小的数组,所以上述程序运行时会出错。考虑一下:如果将上述程序改成以下程序段,输出结果是多少?Dima()AsVariantDimiAsIntegera=Array(1,2,3,4,5,6,7,8,9)Printa(2)注意:Array函数只能生成一维数组,不能生成多维数组;Array函数只能给变体型变量和变体型动态数组赋值,赋值时有多少个数值,生成的一维数组就有多少个元素,数组的类型由数值的类型决定。3.数组相关语句对于数组的相关语句,只需要大家掌握Erase语句的功能。例6-6执行以下程序段,输出结果是_______。OptionBase1PrivateSubCommand1_Click()Dima,b(5