第七章 数组 一维数组:一个变量每次只能存储一个值。一个包含40个元素的数组变量可以存放40个值,采用循环结构实现计算过程非常方便。 第七章 数组 一维数组:一个变量每次只能存储一个值。一个包含40个元素的数组变量可以存放40个值,采用循环结构实现计算过程非常方便。 动态数组:数组包含的元素个数可以是固定不变的,也可以是动态改变的。在程序中可以根据情况改变数组大小。 二维数组:数组可以有多个维。例如:存储40个学生5门科目的成绩,可以定义一个整数类型的二维数组,好比一个二维表格。第一维包括40个元素,第二维包括5个元素,这个数组的元素共计200(40×5)个。 控件数组:多个相同类型的控件元素也可以组织成为控件数组,使用控件数组编程可以减少代码量。
一维数组的声明 数组变量的作用域: 没有下界,则默认为0 上界不能超出Long的范围 公用数组:模块声明段用Public {Dim|Private|Public} 数组名 ( [下界 To] 上界 ] ) As 数据类型 数组变量的作用域: 公用数组:模块声明段用Public 模块级数组:模块声明段用Private 局部数组:过程中用Dim 没有下界,则默认为0 上界不能超出Long的范围 Dim stuScore(1 To 40) As Integer ‘整数数组,元素从stuName(1)到stuName(40) Dim stuName(1To 40) As String ‘字符串数组 Dim salary(100) As Double ‘元素从salary(0)到salary(100)
给数组元素赋值 数组元素用数组名(下标值)的方式来指定,下标可以直接是一个数字,也可以是整数变量或表达式。 比如: stuName(1) = "张三" '第1个元素的值为张三 stuScore(8) = 85 '第8个元素的值为85 salaries(i) = salaries(i) +500 '第i个元素的值为原值加500 给数组所有元素赋值,通常使用循环结构。如: For i = 0 To 99 ' 循环100次 salary(i) = 2000 Next
访问数组元素 访问数组中的全部元素有两种方法: Dim i as integer, x as variant Dim Temp(10) as integer ‘第一种方法 For i=0 To 10 Temp(i)=num Next ‘第二种方法 For Each x In Temp Debug.Print one ** x变量必须是Variant类型 ** 不能用于用户自定义类型
数组示例1 【例】输入40个学生的成绩,输出平均成绩以及高出 平均成绩的人数。 编程思路:为了操作的方便,利用【下一个】按钮将当前成绩放入数组中,并累计总成绩,然后清空成绩输入框等待下一个成绩的输入。当数组计数达到40后,统计平均成绩和超出人数,将结果输出到平均成绩文本框txtAvg和超出人数文本框txtOver中。
数组示例1 Const MAXNUMBER = 40 ' 定义常数表示学生人数为40 Dim score(MAXNUMBER) As Integer '成绩数组,从第0个开始 Dim num As Integer, sum As Integer Private Sub Command1_Click() ' 按下按钮 Dim i As Integer, count As Integer, avg As Integer score(num) = CInt(txtScore.Text) ' 给数组元素赋值 sum = sum + score(num) ' 累计总成绩 num = num + 1 If num = MAXNUMBER Then '计算平均成绩和超过人数 MsgBox "输入完毕" avg = sum / MAXNUMBER count = 0 For i = 1 To MAXNUMBER If score(i) > avg Then count = count + 1 Next txtAvg.Text = avg txtOver.Text = count End If txtScore.Text = "" txtScore.SetFocus End Sub
数组的上下界 VB声明数组变量,可以自由定义数组的上下界。并且 程序中可以使用LBound与UBound函数来获知一个数 组的大小。 如: Dim stuScore(1 To 40) As Integer Debug.Print LBound(stuScore) ' 输出结果为1 Debug.Print UBound(stuScore) ' 输出结果为40
数组大小可以随意变化吗 如果数组元素个数是不可知的,通常声明一个尽可能大的数组以保证够用,但这样可能带来内存资源的浪费和内存操作速度的降低。 VB提供的动态数组能够在运行时根据实际情况来改变数组的大小。 声明时指定数组为动态数组 声明动态数组,即空的一维数组。如: Dim Temp() As Integer 使用过程中用ReDim分配实际的元素个数,维数和元素个数可任意更改。如: Redim Temp(10) As Integer
使用ReDim改变数组大小 使用ReDim语句可以改变原来已经声明过的动态数组的大小,可以改变数组的上下界(使用数字、整数常量、整数变量或表达式),但不能改变数组的数据类型。 Dim stuName() As String ' 先声明一个动态数组 …… ReDim stuName(1 To 30) As String '改变数组大小 ReDim stuName(1 To 30,1 To 2) As String ReDim实质上就是一条给数组重新分配空间的语句,在一个过程中可以多次使用。
使用Preserve保留动态数组原有数据 使用ReDim语句后,系统为数组重新分配了空间,并使用初始值0填充,而原来位置上保存的值就全部丢失了。 为了解决这一问题,使用具有Preserve关键字的ReDim语句就可以在改变数组大小的同时又保留数组中原来的数据。 ReDim Preserve Temp(UBound(Temp)+1) 该语句的目的是为数组Temp增加一个元素(上界加1,但原始数据仍保留) **用Preserve只能改变数组最后一维的上界 **ReDim不能改变数组的数据类型
数组示例2 【例】输入任意个学生的成绩,将成绩按从高到低的顺序排列输出。 编程思路: 利用输入框输入分数,当输入为-1表示输入完毕,开始执行冒泡排序并显示结果。为了更好地观察排序算法,原始数据和每轮排序的结果都将输出在窗体中。 因为不知道有多少个学生,所以成绩使用了动态数组,利用ReDim Preserve语句重新定义动态数组大小,并保留以前的元素值
数组示例2 以下是输入成绩和排序前的成绩输出: Dim num As Integer, scores() As Integer, total As Integer ' 输入若干分数 total = 0 Do While (1) num = CInt(InputBox("输入学生成绩:")) If num = -1 Then Exit Do ‘ 输入-1结束循环 total = total + 1 ' 累加人数 ReDim Preserve scores(total) ' 改变数组大小,并保留原值 scores(total) = num ' 输入的分数存放到数组中 Loop ' 输出原始数据 Print " 原始数据:"; For k = 1 To total Print scores(k); Next Print
数组示例2 执行冒泡排序(从大至小),并输出每轮排序的结果: For i = total To 1 Step -1 Change = False ' 每轮排序开始前设置交换标志 For j = 1 To i - 1 If (scores(j) < scores(j + 1)) Then Change = True temp = scores(j) scores(j) = scores(j + 1) scores(j + 1) = temp End If Next Print “第” & total - i + 1 & “轮结果:”; ‘ 输出本轮排序结果 For k = 1 To total Print scores(k); Print If Change = False Then Exit For ' 本轮没有发生交换,排序结束
数组示例2 如果是从小至大排序,只需要在排序算法中修改If语句: For i = total To 1 Step -1 Change = False ' 每轮排序开始前设置交换标志 For j = 1 To i - 1 If scores(j) > scores(j + 1) Then Change = True temp = scores(j) scores(j) = scores(j + 1) scores(j + 1) = temp End If Next
二维数组 二维数组的声明基本上与一维数组相似,但需要两个维数的上下界,它们之间使用逗号分隔。 比如40个学生的5门科目的成绩采用数组记录,应该这样声明该数组: Dim score(1 To 40, 1 To 5) As Integer ' 下界从1开始 或 Dim score(40, 5) As Integer ' 下界从0开始 访问某个元素需要指定两个索引下标: Print score(10,2) ‘输出第10个学生的第2门课程成绩 访问全部数据,需要利用双层嵌套循环了: For i = 1 to 40 For j = 1 to 5 Print score(i, j); ' 在同一行显示5门课程成绩 Next Print ' 换行
控件也可以有数组吗? 比如一个计算器程序如下图,每个数字是一个按钮,每 按下一个数字按钮后,该数字应添加在文本框中。 两种方法: 每个数字是单独的一个命令按钮控件,并分别编写每个按钮的Click事件过程。一共有10个按钮、10个事件过程。 VB对于多个同种类型的控件提供控件数组的概念,即将它们设置为具有相同的名称(name),而Index属性各自不同的一组控件数组,它们对事件具有一致的响应机制(10个按钮,1个事件过程)。
怎样创建控件数组 控件数组的特征: Index属性不空。控件数组中的 创建方法(以下两种): 每个元素具有相同的名称(name),不同的Index属性值。 创建方法(以下两种): 增加一个控件,并让该控件的Index属性≥0,就会建立一个只有一个元素的控件数组 复制某个控件,并且进行粘贴,会提示是否创建一个控件数组,回答是。
访问控件数组的元素 控件数组和普通数组的使用语法相同,不同的是每个元素是一个对象,而不是一个数字或字符串。 但要注意:数组中的各个控件是相互独立的,可以具有不同的属性 ‘将数组中的第1个按钮的文本设为“兰” Command1(1).Caption = "兰" ‘所有按钮的背景颜色都设置为红色 For i=0 to Command1.UBound Command1(i).BackColor = vbRed Next
控件数组的元素共性 一个控件数组的所有控件共享一个事件过程,其中事件过程的第一个参数是触发事件的控件元素的Index属性值(自动出现)。如: Private Sub Text1_Change(Index As Integer) Private Sub Command_Click(Index As Integer) 可以在运行时动态地添加新元素到控件数组中,或者删除一个元素: Load Text1(2) Unload Text1(2)
控件数组的事件过程 后动态改变窗体上的背景颜色。 【例】编写界面提供不同的颜色按钮,选中不同的按钮 Private Sub Command1_Click(Index As Integer) Form1.BackColor = QBColor(Index) ' 改变窗体背景颜色 End Sub
控件数组计算平均成绩(见第4章) Private Sub txtScore_Change(index As Integer) 设计控件数组,包含三个TextBox控件元素txtScore(0)、 txtScore(1)和txtScore(2),只需要编写一个事件过程: Private Sub txtScore_Change(index As Integer) Dim i As Integer sum = 0 For i =0 To 2 If IsNumeric( txtScore(i) ) Then sum = sum + Val( txtScore(i) ) Endif Next txtAvg = sum / 3 End Sub