第五章 VB中的数组
引例:利用随机函数产生20个50~100范围内的随机数,显示最大值和最小值。运行界面如图 5.2 静态数组 引例:利用随机函数产生20个50~100范围内的随机数,显示最大值和最小值。运行界面如图 [程序代码] Private Sub Command1_Click() Dim maxa As Integer, mina As Integer, x As Integer, i As Integer Form1.Cls ‘每单击一次清除原来内容 maxa = 50 ‘假设较小的数为最大 mina = 100 ‘假设较大的数为最小 Randomize For i = 1 To 20 x = Int(Rnd * 51 + 50) Print x; IF i Mod 10 = 0 Then Print IF x > maxa Then maxa = x F x < mina Then mina = x Next i Print Print "最大值为"; maxa Print "最小值为"; mina End Sub x是一个简单变量,存放的是最后一个随机数
5.2.1 一维数组的声明和引用 1. 静态数组及声明 形式: Dim 数组名(下标1[,下标2…]) [As 类型] 数组不是一种数据类型,而是一组相同类型的变量的集合,数组必须先声明后使用。 两类数组: 静态(定长)数组、动态(可变长)数组 1. 静态数组及声明 形式: Dim 数组名(下标1[,下标2…]) [As 类型] 声明了数组的名、维数、大小、类型 维数:几个下标为几维数组,最多60维。 下标:[下界 To ] 上界 省略下界为0 ,必须为常数。 每一维大小:上界-下界+1 数组大小: 每一维大小的乘积 例:Dim mark(1 to 100) As Integer
Dim lArray( 0 To 3, 0 To 4) As Long 共有 4×5个元素 等价于: Dim lArray(3, 4) As Long 注意:(1)下界缺省为0,也可在重新定义数组的下界。例如: Option Base 1 (2)错误的声明,下标是变量 n =Inputbox("输入n " ):Dim x(n) As Single
上界/下届必须为常数,不可以为表达式和变量 如果声明数组时省略类型,则为variant变体型。 说明 Dim数组名([下界 to ]上界)[As类型](也可使用类型符号) 例如:dim a%(3 to 10) 上界>=下届 上界/下届必须为常数,不可以为表达式和变量 如果声明数组时省略类型,则为variant变体型。 可以在一条dim语句中同时定义多个数组,用逗号分隔 dim c(15) as integer, b(5) as single
5.2.1 一维数组的声明和引用 2.一维数组元素的引用 引用一维数组元素的格式:数组名(下标) 引用数组元素时,下标可以为整型常量、变量或表达式 例如:i=1 a(1)=1:a(i)=x+y:a(i+1)=t print a (1);a(i) 在数组声明中的下标说明了数组的整体,即每维的大小; 而在程序其他地方出现的下标表示数组中的一个元素。两者写法形式相同,但意义不同。 例如: Dim x(10) As Integer ' 声明了x数组有11个元素 x(10)=100 ' 对x(10)这个数组元素赋值
5.2.2使用一维数组 1.一维数组的赋值 (1)对数组中的元素逐个赋值 例如:Dim arr(5) As Integer arr(0)=5 : arr(1)=4 : arr(2)=-2 : arr(3)=1 : arr(4)=-8 : arr(5)=6 一般来说,如果各个数组元素的值彼此之间毫无规律可寻,则可以采用逐个赋值的方法,显然这种方法在进行大量数据的处理时决非上乘之选。 (2)使用循环语句对数组元素赋值 例如: For i=0 to 5 arr(i)=Int(Rnd*90)+10 Next i 如果各个数组元素的值彼此之间是有规律可寻的,则可以采用循环语句来实现其赋值操作。
(2)使用循环语句对数组元素赋值 例如: 例如: For i=1 to 5 For i=1 to 50 a(i)=val(inputbox(“请输入一个数字”)) Next i 例如: For i=1 to 50 a(i)=5 Next I 例如: For i=1 to 50 a(i)=100+i Next I
2.一维数组的输出 对于一维数组的输出,基本上都是使用一个单循环语句来达到目的: For i=0 to 5 Print arr(i) Next i 例5-1随机产生50个0~100之间的整数,输出并求出总和与平均值。程序运行界面如图所示。 程序代码: Private Sub Form_Click() Dim a%(1 To 50), i%, sum%, ave% sum = 0 For i = 1 To 50 a(i) = Int(Rnd * 101) sum = sum + a(i) Print Tab(5 * ((i - 1) Mod 10)); a(i); If i Mod 10 = 0 Then Print ave = sum / 50 Print Print "总和为:"; sum; "平均值为:"; ave End Sub Private Sub Form_Click() Dim a%(1 To 50), i%, sum%, ave% sum = 0 For i = 1 To 50 a(i) = Int(Rnd * 101) Print Tab(5 * ((i - 1) Mod 10)); a(i); If i Mod 10 = 0 Then Print Next I for i=1 to 50 sum=sum+a(i) next i ave = sum / 50 Print Print "总和为:"; sum; "平均值为:"; ave End Sub
现在有一个数组a(1 to 10),要将数组a复制给数组b 3.静态一维数组的复制 现在有一个数组a(1 to 10),要将数组a复制给数组b Dim a(1 to 10) as integer,b(1 to 10) as integer For i=1 to 10 a(i)=val(inputbox(“请输入一个数”)) Next i For i=1 to 10 ‘开始复制数组 b(i)=a(i)
5.3.1动态数组的声明 动态数组指在声明数组时未给出数组的大小(省略括号中的下标),当要使用它时,随时用ReDim语句重新指出数组大小 声明动态数组通常分为两步: 第一步,使用Dim语句声明一个没有下标的数组,即括号内为空的数组,但是括号不能省略; 第二步,在过程中使用ReDim语句指定该数组的大小,其作用是为数组分配实际存储空间。 Redim语句的格式: ReDim数组名(下标1[,下标2…])[As类型] 其中下标可以是常量,也可以是有了确定值的变量,类型可以省略,若不省略,必须与Dim中的声明语句保持一致。 例如: 例 Sub Form_Load( ) Dim x( ) As Single n =Inputbox(“输入n”) ReDim x(n) End Sub
说明 在过程中可多次使用ReDim来改变数组的大小和维数。 例如: Dim a() as integer Dim、Private、Public变量声明语句是说明性语句,可出现在过程内或通用声明段;ReDim语句是执行语句,只能出现在过程内。 在过程中可多次使用ReDim来改变数组的大小和维数。 例如: Dim a() as integer Redim a(10):改变数组大小 Redim a(3,4):改变数组大小和维度 Redim a(4,5) 可使用redim来改变数组的格式和维度,但不能改变数组的数据类型 使用ReDim语句会使原来数组中的值丢失,可以在ReDim语句后加Preserve参数来保留数组中的数据。使用Preserve只能改变最后一维的大小,前面几维大小不能改变。 ReDim中的下标可以是常量,也可以是有了确定值的变量。 静态数组在程序编译时分配存储单元,动态数组在运行时分配存储单元。
要保留原来数组中的数据,使用Preserve。但只能改变最后一维的大小,不能改变维度。 格式:Redim Preserve 数组名(下标) 5.3.1动态数组的声明 要保留原来数组中的数据,使用Preserve。但只能改变最后一维的大小,不能改变维度。 格式:Redim Preserve 数组名(下标) 例如: Dim a() as integer, Dim b() as integer Redim a(10) ’动态改变数组大小 Redim Preserve a(4) ‘改变数组大小,并保存原来数组中的数据 Redim b (3,5) Redim Preserve b (3,6) ‘只能改变最后一维的大小 Redim Preserve b(3) ’出错
5.3.2与动态数组操作相关的函数 a=array(3,4,5) For i=Lbound (a) To Ubound(a) 1.Array函数(p98) 使用格式:Array(参数列表) 说明: (1)用Array函数给动态数组赋值后,该数组被确定为一维数组,其下标下界由Option Base n语句决定,下标上界由参数个数决定。 (2)用Array函数也可给Variant类型的变量赋值,此时该变量也表示一个Variant类型的动态数组。 例如:Dim a() As Variant ,b As Variant a=Array(1,”abc”,3) b=Array(5,6) a=Array(9,8,7,6) ‘重新改变数组a的元素个数 ReDim Preserve a(2),b(1 To 5): 改变数组a、b的大小,并保留原来的数据。 2.Lbound()函数和Ubound()函数 Lbound()函数和Ubound()函数帮助用户确定数组每一维下标的变化范围,Lbound()函数返回数组的下界,Ubound()函数返回数组上界。 使用格式:Lbound(数组名,n)和Ubound(数组名,n) 说明:n表示第几维,默认为1(第一维),即省略参数n时,默认数组为一维数组。 例如:输出动态一维数组a中的各元素 For i=Lbound (a) To Ubound(a) Print a(i) Next i a=array(3,4,5) For i=Lbound (a) To Ubound(a) Print a(i) Next i a=array(12,43,56,86,87)
例5-4通过Array函数获得6整数存放于数组a中,在文本框输入一个数,将其插入到数组中,使得数组中的各元素保持小到大的次序,并显示,然后删除数组中负数元素并显示最后结果。程序运行结果如图所示。 应用程序初始化程序代码: Dim a() Private Sub Form_Load() a = Array(-3, -6, 2, 4, 8, 12) Print "原数组中的元素为:" For i = 0 To 5 Print a(i); Next i Print End Sub
插入及删除元素的程序代码: Private Sub Command1_Click() Dim i%, j%, x% x = Val(Text1.Text) For i = 0 To UBound(a) If x <= a(i) Then Exit For Next i ReDim Preserve a(UBound(a) + 1) For j = UBound(a) To i Step -1 a(j) = a(j - 1) Next j a(i) = x Print "插入元素后的数组为:" Print a(i); Print End Sub Private Sub Command2_Click() i = 0 Do While (i <= UBound(a)) If a(i) < 0 Then If i < UBound(a) Then For j = i To UBound(a) - 1 a(j) = a(j + 1) Next j End If ReDim Preserve a(UBound(a) - 1) n = n - 1 Else i = i + 1 End If Loop Print "删除负数后数组为:" For i = 0 To UBound(a) Print a(i); Next i End Sub
5.4 数组的基本操作 1. 数组元素的赋初值 (1)用循环 For i = 1 To 10 iA(i)=0 Next i (2) Array函数 Dim ib As Variant ib = Array("abc", "def", "67") For i = 0 To UBound(ib) Picture1.Print ib(i); " "; Next i 注意: 利用Array对数组各元素赋值,声明的数组是可调数组或连圆括号都可省,并且其类型只能是Variant。 数组的下阶为零,上界由Array函数括号内的参数个数可决定,也可通过函数Ubound获得。
b = a 2.数组的赋值(p101 注意) 在VB6.0中,提供了数组直接对数组的赋值。例如: Dim a() As Variant, b() As Variant, i% a = Array(1, 2, 3, 4, 5) b = a 3. 数组的输出 输出方阵sC中的下三角元素 For i = 0 To 4 For j = 0 To i sc(i, j) = i * 5 + j Print sc(i, j); " "; Next j Print ' 换行 Next I Redim b(UBound(a)) For i = 0 To UBound(a) b(i) = a(i) Next i 注意:赋值号左边的数组只能声明为可调数组或简单变量。
4. 求数组中最大元素及所在下标 Dim Max As Integer,iMax As Integer Max=iA(1):iMax=1 For i = 2 To 10 If iA(i)>Max Then Max=iA(i) iMax=i End If Next I 5. 将数组中各元素交换 For i =1 To 10\2 t=iA(i) iA(i)=iA(10-i+1) iA(10-i+1)=t
数组中常见错误和注意事项 1.静态数组声明下标出现变量 n = InputBox("输入数组的上界") Dim a(1 To n) As Integer 2.数组下标越界 引用的下标比数组声明时的下标范围大或小。 Dim a(1 To 30) As Long, i% a(1) = 1: a(2) = 1 For i = 2 To 30 a(i) = a(i - 2) + a(i - 1) a(0)不存在 Next i 3.数组维数错 数组声明时的维数与引用数组元素时的维数不一致。 Dim a(3, 5) As Long a(i)=10 4.Aarry函数与Split函数使用问题 只能对Variant 的变量或动态数组赋值。 5.获得数组的上界、下界 Ubound 、Lbound函数
常用算法(二) 1.数组排序(选择法) 对已知存放在数组中的n个数,用选择法按递增顺序排序。 For i = 1 To n - 1 iMin= i For j = i+1 To n If a(j) <a(iMin) Then iMin = j Next j t= a(i): a(i) = a(iMin) : a(iMin) = t Next I
2.排序(冒泡法) 冒泡法排序在每一轮排序时只要将第一个与其他几个比较,只要次序不对,就交换,出了内循环,最小数已冒出。排序进行的过程见下表。 原始数据 8 6 9 3 2 7 a(0) a(1) a(2) a(3) a(4) a(5) 第一趟排序 2 8 9 6 3 7 第二趟排序 2 3 9 8 6 7 第三趟排序 2 3 6 9 8 7 第四趟排序 2 3 6 7 9 8 第五趟排序 2 3 6 7 8 9
例:使用Array函数建立并输出一个数组,然后将该数组的元素按从小到大的原则进行排序,并输出排序结果。程序运行结果如图所示。 程序代码为: Private Sub Command1_Click() Dim b As Variant, n As Integer Cls b = Array(17, 10, 45, 27, 60, _ 18, 79, 41, 59, 21) Print " 数组输出:" n = UBound(b) For i = 0 To n Print b(i); Next i Print For i = 0 To n - 1 '开始排序 For j = n To i + 1 Step -1 If b(j - 1) > b(j) Then t = b(j - 1): b(j - 1) = b(j): b(j) = t End If Next j Print " 冒泡法排序后输出:" For i = 0 To n Print b(i); Next i Print End Sub 冒泡法排序
3. 查找 Private Sub Command1_Click() Dim i As Integer, tofind As Integer, found As Boolean tofind = Val(InputBox("查找", "请输入要查找的数")) found = False For i = 0 To UBound(a) If a(i) = tofind Then found = True Exit For End If Next i If found = True Then Form1.Print "您要找的数是"; tofind; "。在数组中找到,在第"; i + 1; "个元素" Else Form1.Print "您要找的数是"; tofind; "。抱歉,在数组中未找到" End Sub
Private Sub Command1_Click() Dim num%(0 To 9), i%, j%, a As String * 1 4. 统计 例5-5输入字符串分别统计该字符串中每个数字字符(“0” ~“9”)出现的次数。用num(0)来统计字符“0”的个数,用num(1)来统计字符“1”的个数,…,用num(9)来统计字符“9”的个数,并显示最后的统计结果。程序运行结果如图所示。 程序代码: Private Sub Command1_Click() Dim num%(0 To 9), i%, j%, a As String * 1 Picture1.Cls lg = Len(Text1.Text) For i = 1 To lg c = Mid(Text1, i, 1) If c >= "0" And c <= "9" Then j = Asc(c) - 48 num(j) = num(j) + 1 End If Next i For i = 0 To 9 If num(i) > 0 Then Picture1.Print """"; Chr$(i + 48); """"; "="; num(i); End Sub
4.数组元素的插入与删除 (1) 插入 (例5-4) 在有序数组a(1 to n)(原有n-1个元素)插入一个值Key元素,算法: 查找要插入的位置k(1<=k<=n-1) 腾出位置,把最后一个元素开始到第k个元素往后移动一个位置 第k个元素的位置腾出,就可将数据Key插入 (2) 删除 要找到欲删除的元素的位置k;然后从k+1到n个位置开始向前移动;最后将数组元素减1。
5.4控件数组 5.4.1控件数组的概念 控件数组是一组相同类型的控件,共用同一个控件名,共享同样的事件过程,完成相似的操作,每个控件都有一个唯一的下标,即Index属性,第一个元素的下标为0。控件数组适用于若干个控件执行的操作相似的场合。 5.4.2控件数组的建立 建立控件数组有两种基本方法: 1.在设计阶段静态创建 基本步骤: (1)在窗体上创建控件数组中的第一个控件,并设置好控件名等相关属性。 (2)选择该控件,执行 “复制”命令。 (3)根据需要执行若干次 “粘贴”命令。 (4)进行事件过程的编程。 2.在运行阶段动态添加 (1)在窗体上创建控件数组中的第一个控件,设置好控件名等相关属性后,设置其Index属性值为0,表示这是一个控件数组。 (2)在代码中使用Load语句和Unload语句进行控件元素的添加和删除 使用格式:Load控件数组名(下标) Unload控件数组名(下标)。 (3)设置新添加控件的相关属性,可通过Left属性和Top属性确定其位置,并将Visible属性设置为True。 5.4.3控件数组的引用 控件数组元素的引用格式:控件数组名(Index)
例5-6:建立含有3个命令按钮的控件数组,当单击某个命令按钮时,分别执行不同的操作。程序运行结果如图所示: 解:(1)在窗体上建立一个命令按钮,其Name属性设置为Comtest,复制两个命令按钮 (2)把3个命令按钮的Caption属性依次设置为“命令按钮1”,“命令按钮2”和“退出” (3)双击任一命令按钮,打开代码编辑窗口,键入如下事件过程: Private Sub comtest_Click(Index As Integer) FontSize=12 If Index=0 Then Print “单击第一个命令按钮” ElseIf Index=1 Then Print “单击第二个命令按钮” Else End End If End Sub
5.2.3二维数组的声明和引用 1.静态二维数组的声明 声明格式:Dim 数组名([下届 to] 上界,[下届 to] 上界)[As类型] 说明: 二维数组的元素个数=(上界1-下界1+1) ×(上界2-下界2+1)。 例如:dim d(-1 to 5,6) as long 和一维数组类似,声明二维数组时,下届 /上界只能是常数 2.二维数组的赋值和引用 通过InputBox函数输入,此方法适合输入少量数据。 例如: Dim s(5,6)As integer For i= 0 To 5 For j=0 To 6 s(i,j)=InputBox("输入第" & i & "行第" & j &"列的值") form1.print s(i,j) Next j Next i
例5-3:在文本框中输入矩阵的行列数n,根据文本框内输入矩阵的行列数n,用1~n×n的自然数生成1个n×n矩阵(数组),并显示在图形框中, 并分别能显示上、下三角矩阵。程序运行界面如图所示。 Option Base 1 Dim a%() Dim n% Private Sub Command1_Click() Dim i%, j% Picture1.Cls n = Val(Text1.Text) ReDim a(n, n) For i = 1 To n For j = 1 To n a(i, j) = (i - 1) * n + j Picture1.Print Tab(4 * j); a(i, j); Next j Picture1.Print Next i ReDim Preserve a(n, n) Command2.Enabled = True Command3.Enabled = True End Sub Private Sub Form_Load() Command2.Enabled = False Command3.Enabled = False End Sub 以上为应用程序初始化及产生矩阵的程序代码,变换为上三角及下三角矩阵的程序代码见后页。
变换为上三角及下三角矩阵的程序代码: Private Sub Command2_Click() Picture1.Cls For i = 1 To n For j = i To n a(i, j) = (i - 1) * n + j Picture1.Print Tab(4 * j); a(i, j); Next j Picture1.Print Next i End Sub I=1,j=1 to 5 A(1,1) A(1,2) A(1,3) A(1,4) A(1,5) I=2 ,j=2 to 5 A(2,2) A(2,3) A(2,4) A(2,5) I=3 ,j=3 to 5 A(3,3) A(3,4) A(3,5) I=4 ,j=4 to 5 A(4,4) A(4,5) I=5 ,j=5 to 5 A(5,5)
Private Sub Command3_Click() Picture1.Cls For i = 1 To n For j = 1 To i a(i, j) = (i - 1) * n + j Picture1.Print Tab(4 * j); a(i, j); Next j Picture1.Print Next i End Sub I=1,j=1 to 1 A(1,1) I=2 ,j=1 to 2 A(2,1) A(2,2) I=3 ,j=1 to 3 A(3,1) A(3,2) A(3,3) I=4 ,j=1 to 4 A(4,1) A(4,2) A(4,3) A(4,4) I=5 ,j=1 to 5 A(5,1) A(5,2) A(5,3) A(5,4) A(5,5)
例5-2用1~25的自然数生成1个5×5按自然排列的二维矩阵,并输出到Picture1上;然后将该矩阵循环上移一行,第一行元素换到最后一行,结果在Picture2上输出。程序运行界面如图所示。 程序代码: Private Sub Command1_Click() Dim a%(1 To 5, 1 To 5), t(1 To 5) As Integer Picture1.Print "生成的原始矩阵为:" & vbCrLf For i = 1 To 5 For j = 1 To 5 a(i, j) = 5 * (i - 1) + j Picture1.Print Tab(5 * (j - 1)); a(i, j); Next j Picture1.Print Next i Picture2.Print "变换后的矩阵为:" & vbCrLf For j = 1 To 5 '保存第一行数据于数组t() t(j) = a(1, j) For j = 1 To 5 a(5, j) = t(j) Next j For i = 1 To 5 Picture2.Print Tab(5 * (j - 1)); a(i, j); Picture2.Print Next i End Sub For i = 1 To 4 For j = 1 To 5 a(i, j) = a(i + 1, j) Next j Next i
5.2.4多维数组的声明和引用 我们把三维以上的数组统称为多维数组,在应用程序中,多维数组的使用与二维数组非常相似。 1.静态多维数组的声明 我们把三维以上的数组统称为多维数组,在应用程序中,多维数组的使用与二维数组非常相似。 1.静态多维数组的声明 声明格式: Dim数组名(下标1,下标2,……,下标n)[As类型] 2. 静态多维数组的引用 引用多维数组元素的格式: 数组名(下标1,下标2,……,下标n) 说明: (1)下标个数决定数组的维数,最多60维(即n≤60)。 (2)每一维的元素个数=上界-下界+1;数组的元素个数=每一维的元素个数的乘积。