第四章数组.docx
《第四章数组.docx》由会员分享,可在线阅读,更多相关《第四章数组.docx(67页珍藏版)》请在冰豆网上搜索。
第四章数组
第4章数组
4.1引言
在程序中处理数据时,对于输入的数据、参加运算的数据、运行结果等临时数据,通常使用变量来保存,由于变量在一个时刻只能存放一个值,因此当数据不太多时,使用简单变量即可解决问题。
但是,有些复杂问题,利用简单变量进行处理很不方便,甚至是不可能的。
例如:
(1)输入50个数,按逆序打印出来。
(2)输入100名学生某门课程的成绩,要求把高于平均分的那些成绩打印出来。
(3)统计高考中各分数段的人数。
(4)某公司有近万名职工,搞一个工资报表。
(5)窗体上的几个同类型控件,有着某种关系。
这就需要我们构造新的数据结构——数组。
4.2数组的概念
4.2.1数组的定义
数组是一组具有相同类型的有序变量的集合,可用于存储成组的有序数据。
根据数组的定义,我们必须明确以下几点:
(1)数组的命名与简单变量的命名规则相同。
(2)数组中的元素是有序排列的。
(3)数组的元素个数是有限的,数学中的无限数组不能表示。
(4)数组的类型也就是该数组的下标变量的数据类型。
VB中,可以说明任何基本数据类型的数组(包括用户自定义类型),但是一个数组中的所有元素应该具有相同的数据类型,只有当数据类型为Variant型时,各个元素的数据类型可以不同。
4.2.2数组的概念
1.数组的声明
数组必须先声明后使用,声明的格式为:
Dim|Private|Public|static数组名(<维数说明>)[As类型]
对数组进行声明应该包括:
数组名、维数、大小、类型以及作用域。
数组的命名规则和变量的命名规则一致。
Dim:
用于在过程(Procedure)、窗体模块(Form)或标准模块(Module)中声明数组变量。
在过程中使用Dim时,所声明的数组变量的作用域为过程级(作用范围为数组声明所在过程)、在窗体模块或标准模块的通用声明段中使用Dim时,所声明的数组变量的作用域为模块级(作用范围为数组声明所在模块)。
Private:
用于在窗体模块、标准模块的通用声明段中声明一个模块级的私有数组变量,其作用域为模块级。
在窗体模块或标准模块的通用声明段使用Private和使用Dim其作用效果相同。
Public:
用于在标准模块中声明公用数组变量,所声明的数组变量的作用域为整个应用程序。
在VB中,允许在窗体模块中使用Public声明公用简单变量,但是不允许在窗体模块中使用Public声明公用数组变量。
Static:
用于在过程中声明静态数组变量,所声明的静态数组变量的作用域为该过程。
2.数组元素和下标
数组声明后,仅仅表示在内存分配了一段连续的存储空间。
在对数组进行操作时,一般是针对某个元素进行操作。
数组元素是带有下标的变量,是数组的一个成员,其一般形式为:
数组名(下标1[,下标2,……])
如:
A
(2)B(2+2,1)C(1*2,3,1)D(i)
下标表示顺序号,每个数组元素有一个唯一的顺序号。
下标可以是常数、数值变量、算术表达式甚至可以是一个数组元素。
下标中如含有变量,使用前该变量应提前赋值。
多个下标之间应该由逗号分隔。
下标值应该为整数,否则计算机将对下标自动取整。
比如a(3.2)将被视为a(3),a(-3.7)将被视为a(-4)。
3.数组的维数和维界
标志一个数组元素所需的下标个数称为数组的维数。
所以有一维数组、二维数组以及两个以上下标的多维数组。
在VB中,理论上数组的维数最多可以达到60维。
下标的取值范围称为数组在这一维的界。
在VB中,维界不得超过Long数据类型的范围(-2,147,483,648~2,147,483,647)。
我们把下标所取的最大值称为上界,最小值称为下界(默认为0)。
数组的下标在上下界内是连续的。
对某一维而言,其下标不能超出维界的范围,否则会出现“下标越界”错误。
在数组声明语句中的维数说明中,如果明确指出维界,则声明的是固定大小数组;否则声明的是动态数组。
4.数组的数据类型和大小
数组的数据类型由数组声明语句中的“As类型”决定,可以是整形、长整形、单精度、双精度、货币型、字节型、字符串型、布尔型、日期型、对象型,如果声明时省略“As类型”则数组的数据类型默认为Variant类型。
数组中元素的个数称为数组的大小,数组的大小与它的数据类型无关。
数组的大小为每一维大小的乘积,而某一维的大小为:
下界-上界+1。
5.数组的引用
数组的引用通常是指对数组元素的引用。
在引用数组元素时,数组名、数据类型和维数必须和定义时一致。
另外还要注意区分数组的声明和数组元素,例如下面的程序片段:
Dimx(8)AsInteger
DimTempAsInteger
...
Temp=x(8)
尽管有两个x(8),但是Dim语句中的x(8)不是数组元素,而是说明由它声明的数组x的下标最大值为8;而赋值语句”Temp=x(8)”中的x(8)是一个数组元素。
6.数组和简单变量的比较
(1)输入的简单变量越多,程序就越长,程序本身占用的内存空间就越大。
(2)在一个程序中使用的简单变量个数有限,对大批量数据,简单变量就不能表示了。
(3)简单变量的存储位置呈松散状态,数组却占据着一片连续的存储区域。
(4)在程序结构上,简单变量不适合使用循环的办法来解决。
总之,简单变量适合于处理一个或几个变量的情况,每个简单变量只能存储一个数据,各简单变量之间没有固定的联系。
而数组反映的是大批数据间的顺序和联系,体现的是数据间更复杂的结构,因此数组适用于处理大批量数据之间的比较、排序和检索。
7.数组的分类
(1)根据数组的数据类型分为:
整形、长整形、单精度、双精度、货币型、字节型、字符串型、布尔型、日期型、对象型(也可叫控件数组)和可变数组variant。
(2)根据数组的作用域可分为:
公用数组、模块数组和局部数组。
(3)根据数组的生命期和存放方式可分为:
静态数组和自动数组。
(4)根据数组的元素个数是否变化分为:
固定数组和动态数组。
4.3固定大小数组
固定大小数组在声明时其大小就已经确定,在程序运行期间其元素个数不能改变,这种形式的数组在编译阶段就已经确定了存储空间。
4.3.1数组的声明
1.声明格式
Dim|Private|Public|static数组名(维界定义)[As类型]
2.功能
声明一个数组,并初始化所有数组元素。
3.说明
(1)数组的维界定义必须为常数或常量符号,不能是表达式或变量。
例如:
ConstkAsinteger=10
Dimx(10)AsSingle'正确
Dima(k)Aslong'正确
而n=10
Dimx(n)AsSingle'错误
(2)维界定义的形式是:
[下界1to]上界1[,[下界2to]上界2]…。
一般情况下,当[下界To]缺省时,默认值为0,下界≤上界,维的大小为:
上界-下界+1。
维界说明如果不是整数,将自动进行四舍五入处理。
例如:
Dimsum(10)AsInteger'声明sum为一维数组,共有11个元素,下标从0到10
Dimres(1to20)AsSingle'声明res为一维数组,共有20个元素,下标从1到20
Dimx(9,19)AsInteger'声明x为二维数组,共有10*20=200个元素
Dimy(-5to4,9)AsInteger'声明y为二维数组,共有10*10=100个元素
Dimz(9,1to10,9)AsInteger'声明z为三维数组,共有10*10*10=1000个元素
(3)As数据类型:
用来说明数组元素的类型,如果缺省,默认为是变体型(Variant)。
例如:
Dima(12)AsSingle'声明a数组为单精度型
Dimx(1To50)AsInteger'声明x数组为整型
Dimy(-9To10)'声明y为变体型数组
(4)声明数组时可以通过OptionBasen语句来指定缺省下界,n的值只能为0或1。
例如:
OptionBase1'指明缺省下界为1
Dimcup(4,5)AsInteger'声明cup为二维数组,共有(4-1+1)*(5-1+1)=20个元素
Dimda(7,1to10)AsInteger'声明da为二维数组,共有(7-3+1)*(10-1+1)=50个元素
注意:
OptionBase语句只能在模块级使用,即在窗体模块或标准模块的通用声明段使用,而不能在过程中使用;当在某一模块中使用了OptionBase语句改变了缺省的下界值,这一缺省值只能影响到包含该OptionBase语句的模块,而其他模块中所定义的数组的下界缺省值不会受到影响。
如在窗体Form1的通用声明段中加入语句OptionBase1,则只有在Form1中定义数组时,默认下界值为1。
(5)数组声明语句声明一个数组,并对所有数组元素进行初始化,把数值数组中的全部数组元素都初始化为0,把变体字符串数组中的数组元素初始化为空字符串,把定长字符串数组的元素初始化为给定长度的空格,把逻辑型数组元素初始化为False,变体型初始化为Empty。
(6)在声明数组时,也可以使用类型说明符代替“As类型”。
例如:
Dima$(10)'字符串类型数组
Dimb%(2,3)'整形数组
Dimc!
(3,4,5)'单精度浮点类型数组
(7)在声明数组时,一条声明语句可以同时声明多个相同或不同数据类型的数组。
例如:
Dima1(10)AsSingle,a2(10,10)AsLong,a3(10,10,10)AsInteger
Dimb1%(10),b2%(20),b3!
(2,2),b4#(3,4,5)
4.声明数组的方法
1)建立公用数组
在模块的通用声明段用Public语句声明数组。
例如:
PublicCounters(14)AsDouble'定义Counters为15个元素的公用数组
2)建立模块级数组
在模块的通用声明段用Private或Dim语句声明数组。
例如:
PrivateSums(1To20)AsDouble'定义Sums为20个元素的模块级数组
Dima(4)asInteger'声明模块级数组
PrivateSubCommand1_Click()
…
EndSub
3)建立局部数组
在过程中用Dim或Static语句声明数组。
例如:
PrivateSubForm_Click()
DimSubs(20)AsDouble'定义Subs为20个元素的局部数组
EndSub
PrivateSubForm_Click()
Statics(3)AsInteger
Endsub
4.3.2固定大小数组使用举例
【例4.1】一维数组举例,求一个给定数组中的最大元素和最小元素,并给出相应元素的下标,同时求出各元素的和以及平均值。
1.1. 控件及属性表
表4-1控件及属性表
控件
名称(Name)
属性
标签
Label1
Caption=”最大元素”
标签
Label2
Caption=”最小元素”
标签
Label3
Caption=”各元素的和”
标签
Label4
Caption=”数组元素的平均值”
标签
Label5
Caption=”对应下标”
标签
Label6
Caption=”对应下标”
文本框
Text1
Locked=True
文本框
Text2
Locked=True
文本框
Text3
Locked=True
文本框
Text4
Locked=True
文本框
Text5
Locked=True
文本框
Text6
Locked=True
按钮
Command1
Caption=”计算”
2.布局
图4-1一维数组举例界面布局
3.代码
'变量声明
Dimb(1To10)AsInteger
Dimbmax%,bmin%,bsum%,baverage!
'计算按钮代码
PrivateSubCommand1_Click()
Dimimax%,imin%
Fori=1To10
Ifbmin>b(i)Then
bmin=b(i)
imin=i
EndIf
Ifbmax
bmax=b(i)
imax=i
EndIf
bsum=bsum+b(i)
Nexti
baverage=bsum/10
Text1.Text=bmax
Text2.Text=bmin
Text3.Text=bsum
Text4.Text=baverage
Text5.Text=imax
Text6.Text=imin
EndSub
'窗体载入代码
PrivateSubForm_Load()
Text1.Text="":
Text2.Text=""
Text3.Text="":
Text4.Text=""
Text5.Text="":
Text6.Text=""
b
(1)=10:
b
(2)=40:
b(3)=-10:
b(4)=100:
b(5)=1200
b(6)=-93:
b(7)=-239:
b(8)=76:
b(9)=-921:
b(10)=44
bmax=bmin=b
(1)
bsum=baverage=0
EndSub
4.运行结果
图4-2一维数组举例运行结果
【例4.2】二维数组举例,一个二维表格就是一个二维数组。
数学上形如矩阵{aij}表示的数据均可用二维数组来处理。
请编程完成两个相同阶数的矩阵A和B相加,将结果存入矩阵C,即C=A+B。
由于阶数相同,因此只要分别求出
即可。
1.1. 控件及属性表
表4-2控件及属性表
控件
名称(Name)
属性
标签
Label1
Caption=”矩阵A”
标签
Label2
Caption=”矩阵B”
标签
Label3
Caption=”矩阵C”
图片框
Picture1
图片框
Picture2
图片框
Picture3
按钮
Command1
Caption=”矩阵求和”
2.布局
图4-3矩阵求和界面布局
3.代码
'矩阵求和按钮代码
PrivateSubCommand1_Click()
Picture1.Cls
Picture2.Cls
Picture3.Cls
Dima(4,5)AsInteger
Dimb(4,5)AsInteger
Dimc(4,5)AsInteger
Fori=0To4
Forj=0To5
a(i,j)=Int(Rnd*91)+10
b(i,j)=Int(Rnd*91)+10
c(i,j)=a(i,j)+b(i,j)
Nextj
Nexti
Fori=0To4
Forj=0To5
Picture1.PrintFormat(a(i,j),"!
@@@@");
Picture2.PrintFormat(b(i,j),"!
@@@@");
Picture3.PrintFormat(c(i,j),"!
@@@@");
Nextj
Picture1.Print
Picture2.Print
Picture3.Print
Nexti
EndSub
4.运行结果
图4-4矩阵求和运行结果
4.4动态数组
与固定大小数组对应的是动态数组,即数组元素个数不定并且可以根据需要动态改变数组元素个数的数组。
在使用数组解决实际问题时,有时候我们可能不知道数组到底多大才合适,太大的话会占用大量的存储空间,而太小的话可能不能满足需要;或者由于程序运行的需要,要求数组的大小能够动态的变化,这时就要使用动态数组。
在VB中,动态数组很灵活,可以在任何时候改变大小,有助于有效管理内存。
例如,当要处理的数据量很大时,可短时间使用一个大数组(分配比较大的存储空间),然后在数据量变小时,将原来的大数组变为一个较小的数组,从而释放部分存储空间;甚至可以在不使用这个数组时,将数组所占用的存储空间全部释放。
4.4.1动态数组的创建
1.创建方法
要创建动态数组,需要分两步进行。
(1)与前面的静态数组的声明类似,只是不说明维数和界限,并不分配内存。
(2)实际使用时用ReDim语句分配实际的内存空间,格式为:
Redim[preserve]数组名(维界定义1[,维界定义2…])[As类型]
例如,可先在模块级声明中建立动态数组DynArray:
DimDynArray()AsInteger
然后,在过程中给数组分配空间:
SubTestArray()
…
ReDimDynarray(9,1to20)
…
EndSub
2.说明
(1)ReDim语句中的维界定义中的上下界可以是常量,也可以是有了确定值的变量。
(2)ReDim语句只能出现在过程体内,为数组临时分配存储空间,当所在过程结束时,分配的存储空间就会释放。
在过程中可以多次使用ReDim语句来改变数组的大小。
(3)使用Redim语句时,如果不使用Preserve选项,则原来数组中的值丢失,即数组中的内容全部被重新初始化。
(4)使用Redim语句时,如果使用Preserve选项,则在对数组重新说明时,将会保留数组中原来的数据。
但是不能改变维数,并且只能改变最后一维的大小,前面维的大小不能改变。
例如:
Dimexa()AsInteger
PrivateSubForm_Click()
ReDimexa(2,2)'正确,二维数组
ReDimPreserveexa(2,4)'正确,保留数组原来的数据,只可改变最后一维大小
ReDimPreserveexa(4,2)'下标越界错误,使用Preserve选项只可改变最后一维大小
ReDimPreserveexa(2,2,4)'下标越界错误,使用Preserve选项不能改变维数
…
EndSub
(5)使用ReDim语句时,可以省略“As类型”,即维持数组原来的数据类型。
但如果使用“As类型”,其中的“类型”应该和此数组最初的数据类型一致,即使用ReDim语句不可以改变数组的数据类型。
例如:
Dimexa()AsInteger'整形
PrivateSubForm_Click()
ReDimexa(2,2)'正确,省略”As类型”,表示整形
ReDimexa(2,4)AsInteger'正确,整形,与初始定义一致
ReDimexa(2,2,2)AsSingle'错误,不能改变数组元素的数据类型
...
EndSub
(6)在ReDim语句中可以定义多个动态数组,但是这些数组必须都已事先用不带维数和界限的数组声明语句进行了声明。
例如:
Dima11%(),a12$(),a13!
()'先声明
PrivateSubForm_Click()
ReDima11(2,3),a12(4,5),a13(5,6,7)
…
EndSub
4.4.2动态数组使用举例
【例4.3】请编程,输出杨辉三角形,其一般形式如下:
1
11
121
1331
14641
15101051
……
为了输出杨辉三角形,首先找到形成上述矩阵的规律:
对角线和每行的第1列均为1,其余各项是它的上一行中前一个元素和上一行的同一列元素之和;从而可以得出形成矩阵数据的一般规律:
a(i,j)=a(i-1,j-1)+a(i-1,j)。
1.1. 控件及属性表
表4-3控件及属性表
控件
名称(Name)
属性
文本框
Label1
Caption=”杨辉三角形”
图片框
Picture1
按钮
Command1
Caption=”显示”
2.布局
图4-5杨辉三角形界面布局
3.代码
OptionBase1
Dima%()
'显示按钮代码
PrivateSubCommand1_Click()
Dimm%
m=Val(InputBox("请输入要显示杨辉三角形的级数m(小于等于14的正整数)","获取显示级数",6))
If(m<1Orm>14)Then
MsgBox"请输入大于等于3小于等于14的整数",64,”杨辉三角形”
ExitSub
EndIf
ReDima(m,m)
Picture1.Cls
Fori=1Tom
a(i,1)=1:
a(i,i)=1
Nexti
Fori=3Tom
Forj=2Toi-1
a(i,j)=a(i-1,j-1)+a(i-1,j)
Nextj
Nexti
Dimn%,k%
n=42
Fori=1Tom
Picture1.PrintTab(n);
k=n
Forj=1Toi
Picture1.PrintTab(k);
Picture1.PrintFormat(a(i,j),"@@@@@@");
k=k+6
Nextj
Picture1.Print
n=n-3
Nexti
EndSub
4.运行结果
图4-6杨辉三角形运行结果
4.5数组的基本操作
数组是程序设计中最常用的结构类型,将数组元素的下标和循环语句结合使用,能解决大量的实际问题。
数组在声明时用数组名表示该数组的整体,但在具体操作时是针对每个数组元素进行的。
4.5.1数组函数及语句
1.LBound函数和UBound函数
LBound函数返回数组某维的下界(最小下标)。
用法:
LBound(数组名,[维值])
UBound函数返回数组某维的上界(最大下标)。
用法:
UBound(数组名,[维值])
(1)对于一维数组,在使用这两个函数时,可以省略维值。
例如:
Dimr(10)AsInteger
PrintLBound(r),Ubound(r)'运行的结果会输出0和10两个数
(2)对于多维数组,在使用这两个函数时,要指定维值从而说明是要获取哪一维的下界或上界。
例如:
OptionBase1
Dima(0To9,5)
PrivateSubForm_Click()
PrintUBound(a,2)'打印第二维的上界,5