利用数组可以有效地存储和处理成批数据本章主要内容数组的概念数组的声明和应用动态数组
For Each...Next循环语句控件数组程序举例第 6章 数 组
6.1.1 数组与数组元素简单变量用一个变量名标识,不同的变量使用不同的变量名表示。处理成批的数据时,必须使用数组来处理表示 100个学生的成绩,采用简单变量来表示:
s1,s2,s3,… s99,s100
采用数组来表示,t(0),t(1),t(2),… t(98),t(99)
t(k) (k=0,1,2,…99) 为数组元素 (或称 下标变量 ),它表示第 k个学生的成绩,k称为下标变量的 下标数组的一个主要特点是通过下标 (相当于索引 )来引用数组元素
6.1 数组的概念例如计算这 100个学生成绩的平均分,可用:
S= 0
For k=0 To 99
S = S + t(k) ‘ 累加分数
Next k
Aver=S/100 ‘ 求平均分数组是一组按一定顺序排列的数据的集合例如,学生成绩T= [t(0),t(1),… t(99) ] 是一个数组
a11 a12 a13
A= a21 a22 a23
a31 a31 a33
也是一个数组数组名 (不能与简单变量同名 );数组类型又称有序的变量 ——下标变量默认情况下,下标从 0开始例如,由一行共 5个元素组成的数组 x,它的 5个下标变
x(0) x(1) x(2) x(3) x(4)
由三行四列元素组成的数组 y,它的 12个下标变量可表
y(0,0) y(0,1) y(0,2) y(0,3)
y(1,0) y(1,1) y(1,2) y(1,3)
y(2,0) y(2,1) y(2,2) y(2,3)
下标变量 与 简单变量 具有基本相同的性质和作用数组元素下标用来标明该下标变量在数组中的位置下标可以是常数值,也可以是变量 (包括下标变量 )或数值表达式例如:
若 x(2)=10,k=2,则 y(x(2))就是 y(10),y(x(2)+k)就是 y(12)
只要有规则地改变下标值,就可以很方便地使下标变量
(如 a(i))成为所需要的具体下标变量数组的维数
6.1.2 下标和数组的维数
6.2.1 数组声明语句使用数组之前,一般需要定义数组,以便让系统分配相应的存储单元。格式为:
Dim 数组名 ([下界 1 to]上界 1[,[下界 2 to]上界
2?])[As 数据类型 ]
功能:指定数组的维数、各维的上下界和数据类型举例:
Dim Sum(10) As Long?下标号从 0~ 10,共 11个元素
Dim Ary(1 to 20) As Integer?下标号从 1~ 20,共 20个元素
Dim d(1 to 5,1 to 10) As Double?定义二维数组还可以使用 Public,Static,Private等语句来声明数组
6.2 数组的声明和应用设定下界的方法
Option Base 1?设定下界为 1
Dim Data(10) As Single?下标号从 1~ 10
6.2.2 Array函数使用 Array函数可以为数组元素赋值示例
Dim D As Variant?定义数组名 (变体类型 )
D = Array(1,2,3,4)
执行结果,1→D(0),2→D(1),3→D(2),4→D(3)
例 6.1 输入某小组 5个同学的成绩,计算总分和平均分 (取小数后一位 )
本例利用 InputBox函数来输入成绩,输入完毕后经过计算,再采用 Print直接在窗体上输出结果
6.2.3 数组的应用
Private Sub Form_Load()
Dim d(5) As Integer
Dim i As Integer,total As Single,average As Single
Show
For i = 1 To 5 '输入成绩
d(i) = Val(InputBox("请输入第 " & Str(i) & _
"个学生的成绩 ","输入成绩 "))
Next i
total = 0
For i = 1 To 5 '计算总分和平均分
total = total + d(i)
Next i
average = total / 5
Print "总分," & total
Print "平均分," & Format(average,"##.0")
End Sub
程序中,先通过 Dim语句为数组 d定义维数及下标范围,也即为数组安排一块连续的内存存储区,
但这并不意味着内存里该数组已建立了应有的内容本例中输入数组中的数据是由 InputBox函数来实现的,共循环了五次,输入的五个数依次赋值给下标变量 d(1)~ d(5)
建立了数组中的数据后,就可以按要求进行处理
(1)创建应用程序的用户界面和设置对象属性例 6.2 输入 10名学生的成绩,求出最高分和最低分功能要求,通过 Array函数输入 10个分数;单击“查找”按钮 (Command2)后,开始查找最高分和最低分,找到后显示在标签 Label1上
Option Base 1
Dim score As Variant
Private Sub Form_Load()
Label1.Caption = "单击“查找”按钮开始查找最高分和最低分 "
score = Array(89,96,81,67,79,90,63,85,95,83)
End Sub
(2) 编写程序代码
Private Sub Command1_Click()
Dim max As Integer,min As Integer
max = score(1) '设定初值
min = score(1)
For i = 2 To 10
If max < score(i) Then '找最高分
max = score(i)
End If
If min > score(i) Then '找最低分
min = score(i)
End If
Next i
'Chr(13)起换行作用
Label1.Caption = "最高分," + Str(max) + _
Chr(13) + "最低分," + Str(min)
End Sub
例 6.3 分别计算 5个学生和 3门课的平均分某学习小组有 5名学生,成绩如表 6.1所示分析,用一个 二维数组 a(5,3)来描述。程序中设置两重循环,用以 实现每行和每列上的累加 。本例采用赋值语句来输入学生成绩,并采用 Print直接在窗体上输出结果
r=1 c=1,2,3
r=2 c=1,2,3
r=3 c=1,2,3
r=4 c=1,2,3
r=5 c=1,2,3
求 5个学生的平均分下标使用情况
Option Base 1
Private Sub Form_Load()
Dim a(5,3) As Integer
Dim r As Integer,c As Integer,s As Integer
k = Array("数学 ","英语 ","计算机 ") '输入课程名
a(1,1) = 69,a(1,2) = 89,a(1,3) = 74 '输入学生成绩
a(2,1) = 94,a(2,2) = 80,a(2,3) = 90
a(3,1) = 57,a(3,2) = 62,a(3,3) = 73
a(4,1) = 98,a(4,2) = 94,a(4,3) = 90
a(5,1) = 73,a(5,2) = 76,a(5,3) = 63
例 6.3
Show
Print "学生 ","平均分“
'输出 20个减号,-”
Print String(20,"-")
For r = 1 To 5
s = 0 '累加前清 0
For c = 1 To 3
'累加同一行数据
s = s + a(r,c)
Next c
Print r,Format(s / 3,"##.0")
Next r
Print "课程 ","平均分 "
Print String(20,"-")
For c = 1 To 3
s = 0
For r = 1 To 5
'累加同一列数据
s = s + a(r,c)
Next r
Print k(c),Format(s / 5,"##.0")
Next c
End Sub
程序运行结果解题方法:
(1)利用 Int(91*Rnd+10)产生值为 10到 100
使用 Randomize得到不同的随机数序列
(2)
将 10个数放入数组 a
a(1),a(2),a(3),…,a(10)
① 从这 10个下标变量中,选出最小值,通过交换把该值存入 a(1)中
② 除 a(1)之外 (a(1)已存放最小值 ),从其余 9个下标变量中选出最小值 (即
10个数中的次小值 ),通过交换把该值存入 a(2)中
③ 选出 a(3)~ a(10)中的最小值,通过交换,把该值存入 a(3)
④ 重复上述处理,至 a(8),可使 a(1)~ a(8)按小到大排列
⑤ 第 9次处理,选出 a(9)及 a(10)中的最小值,通过交换把该值存入 a(9)中,
此时 a(10)存放的就是最大值例 6.4 随机产生十个 10~ 100的整数,用,选择排序法,按值从小到大顺序排序,最后输出结果排列要求 小 大示例,a(1) a(2) a(3) a(4)
90 64 65 59
1,a(1)与 a(2) ~ a(4)比较,选出最小值,结果
59 90 65 64
2,a(2)与 a(3) ~ a(4)比较,选出次小值,结果
59 64 90 65
3,a(3)与 a(4)比较,选出较小值,结果
59 64 65 90
i=1 j=2,3,4
i=2 j=3,4
i=3 j=4
For i=1 to 3
For j=i+1 to 4
……
Next j
Next i
程序结构完成上述比较及排序处理过程,可以采用两重循环结构,
外循环的循环变量 i从 1到 9,共循环九次;内循环的循环变量 j
从 i+1到 10
本例采用默认的用户界面,所需数据由随机函数产生,处理后结果信息通过 Print
Private Sub Form_Load()
Show
Randomize
Dim a(1 To 10) As Integer
Print "原始数据,"
For i = 1 To 10 '产生 10个随机数
a(i) = Int(91 * Rnd + 10)
Print a(i);
Next i
(3) 程序结构
Print,Print
For i = 1 To 9
For j = i + 1 To 10
If a(i) > a(j) Then
t = a(i),a(i) = a(j),a(j) = t '交换位置
End If
Next j
Next i
Print "排序结果,"
For i = 1 To 10
Print a(i);
Next i
End Sub
改写中间程序段,For i=1 To 9”~,Next i”(共 7个程序行 )
For i = 1 To 9
k = i?k用来记录每次选择的最小值的下标
For j = i + 1 To 10
If a(k) > a(j) Then
k = j
End If
Next j
t = a(k),a(k) = a(i),a(i) = t '交换位置
Next i
变量 k记录每一次选出的最小值的下标,在本次比较结束后,使 a(i)与 a(k)一次换位即可两种形式的数组,静态数组 和 动态数组静态数组是指数组元素的个数固定不变;动态数组的元素个数,在程序运行时可以改变动态数组可以在运行过程中改变数组的大小,提高存储区的使用效率
6.3.1 建立动态数组建立动态数组的步骤:
第一步:声明一个没有下标 (或称空维数 )的数组为动态数组第二步:在过程中用 ReDim语句重新定义带下标的动态数组
ReDim语句 格式,
ReDim [Preserve] 数组名 ([下界 1 T0] 上界 1[,[下界2 T0] 上界 2…]) [As 数据类型 ]
功能,重新定义动态数组,按定义的上下界重新分配存储单元
6.3 动态数组声明 F为动态数组的示例:
Private Sub Command1_Click()
Dim F() As Integer?声明一个整型动态数组
……
Size=20
ReDim F(Size)
……
End Sub
每次执行 ReDim时,系统会清除指定数组的内容若采用,ReDim Preserve F(Size)
则能保留数组中原有的数据
Private Sub Form_Load()
Dim a() As Integer
Show
ReDim a(800)
k = 0
For x = 200 To 600 Step 3
If x Mod 8 = 0 Then
k = k + 1
a(k) = x
End If
Next x
ReDim Preserve a(k)
For i = 1 To k
Print a(i)
Next i
End Sub
例 6.5 ReDim语句应用示例数组刷新语句可以作用于动态数组和静态数组格式:
Erase 数组名 [,数组名 ]…
功能,该语句用来清除静态数组的内容,或者释放动态数例如,
Dim Array1(20) As Integer
Dim Array2() As Single
ReDim Array2(9,10)
Erase Array1,Array2
对静态数组,Erase语句将数组重新初始化 ; 对动态数组,
Erase语句将释放动态数组所使用的内存
6.3.2 数组刷新语句 (Erase)
与前面的循环语句 For...Next类似,都是用来执行指定重复次数的循环。但 For Each...Next语句专门作用于数组或对象集合中的每一成员。语法格式:
For Each 成员 In 数组名循环体
[Exit For]
Next 成员
“成员”是一个 Variant变量,它实际上代表数组中每一个元素本语句可以对数组元素进行读取、查询或显示,它所重复执行的次数由数组中元素的个数确定在不知道数组中元素的数目时非常有用
6.4 For Each...Next循环语句
Private Sub Form_Load()
Dim a(1 To 10) As Long,sum As Long,t As Long
Dim n As Integer
Show
t = 1
For n = 1 To 10
t = t * n
a(n) = t
Next n
sum = 0
For Each x In a
sum = sum + x
Next x
Print "1! + 2! + 3! + …… 10! ="; sum
End Sub
1! + 2! + 3! + … + 10! = 4037913
例 6.6 求 1! + 2! + … + 10! 的值两类数组,一般数组 和 控件数组
6.5.1 控件数组的概念控件数组是一组具有相同名称、类型和事件过程的控件例如,Label1(0),Label1(1),Label1(2),……
但 Label1,Label2,Label3,…… 不是控件数组
(1)相同的控件名称 (即 Name属性 )
(2)控件数组中的控件具有相同的一般属性;
(3)所有控件共用相同的事件过程。
以下标索引值 (Index)来标识各个控件,第一个下标索引号为 0
6.5 控件数组
6.5.2 控件数组的建立建立控件数组有三种方法:
(1)
(2)
(3)将控件的 Index属性设置为非 Null数值
6.5.3 控件数组的使用例 6.7 按图 6.4设计窗体,其中一组 (共 5个 )单选按钮构成控件数组,要求当单击某个单选按钮时,能够改变文本框中文字的大小控件数组设计步骤:
(1)设计控件数组 Option1,其中包含 5个单选按钮对象具体操作方法:
① 画出第一个单选按钮控件,名称采用默认的 Option1。此
② 单击工具栏上的“复制”按钮 (或按 Ctrl+C)。
③ 单击工具栏上的“粘贴”按钮 (或按 Ctrl+V),此时系统弹出一个如图 6.5所示的对话框单击“是”,就建立一个控件数组元素,其 Index属性为 1,
而已画出的第一个控件的 Index属性值为 0。
通过鼠标拖放可以调整新控件的位置
④ 继续单击“粘贴”按钮 (或按 Ctrl+V)和调整控件位置,
可得到控件数组中的其他三个控件,其 Index属性值分别为 2,
3和 4(即从上而下为 0,1,2,3,4)
⑤ 设置控件数组各元素 (从上而下 )的 Caption属性分别为
10,14,18,24和 28
(2)建立一个文本框 Text1,其 Text属性设置为
“控件数组的使用”。 再建立一个标签,其 Caption
属性为“字号控制”
(3)编写程序代码
Private Sub Form_Load()
Option1(0).Value = True '选定第一个单选按钮
Text1.FontSize = 10 '设定文本框中的字号
End Sub
Private Sub Option1_Click(Index As Integer)
Select Case Index '系统自动返回 Index值
Case 0
Text1.FontSize = 10
Case 1
Text1.FontSize = 14
Case 2
Text1.FontSize = 18
Case 3
Text1.FontSize = 24
Case 4
Text1.FontSize = 28
End Select
End Sub
6.6 程序举例例 6.8 查找考场教室号某课程统考凭准考证入场,考场教室安排如表 6.2。编制程序,查找准考证号码所对应的教室号码
(1)分析,为便于查找,通过二维数组 rm建立这两种号码对照表。
数组 rm由 Form_Load事件过程来建立,它的每一行存放了一个教室资料 (包含准考证号码范围和教室号码 )。当判断到某个给定准考证号码落在某一行的准考证号码范围内时,则该行中的教室号码为所求
(2)创建应用程序的用户界面和设置对象属性
(3)编写程序代码功能要求,用户在文本框 Text1中输入准考证号码,单击
“查找”按钮 (Command1)后,则查找出对应的教室,并将教室号码输出在文本框 Text2中
Dim rm(6,3) As Integer
Private Sub Form_Load()?输入数组数据
rm(1,1) = 2101,rm(1,2) = 2147,rm(1,3) = 102
rm(2,1) = 1741,rm(2,2) = 1802,rm(2,3) = 103
rm(3,1) = 1201,rm(3,2) = 1287,rm(3,3) = 114
rm(4,1) = 3333,rm(4,2) = 3387,rm(4,3) = 209
rm(5,1) = 1803,rm(5,2) = 1829,rm(5,3) = 305
rm(6,1) = 2511,rm(6,2) = 2576,rm(6,3) = 306
End Sub
Private Sub Command1_Click()
Dim no As Integer,flag As Integer
flag = 0 '查找标记,0表示未找到
no = Val(Text1.Text)
For i = 1 To 6
If no >= rm(i,1) And no <= rm(i,2) Then
Text2.Text = rm(i,3) '显示教室号码
flag = 1 '1表示找到
Exit For
End If
Next i
If flag = 0 Then
Text2.Text = "无此准考证号码 "
End If
Text1.SetFocus?设置焦点
End Sub
某学习小组 10名学生的成绩情况如表 6.3所示,现要求采用折半查找法,通过学号查询学生成绩
(1)分析,折半查找法也称对半查找法,是一种效率较高的查找方法。对于大型数组,它的查找速度比顺序查找法 (例 6.8
采用的是顺序查找法 )快得多在采用折半查找法之前,要求将数组按查找关键字 (如本例的学号 )排好序 (从大到小或小到大 )
例 6.9 采用折半查找法查询学生成绩
· 先从数组中间开始比较,判别中间的那个元素是不是要找的数据:
是,则查找成功否,若被查找的数据是在该数组的上半部,则从上半部的中间继续查找,否则从下半部的中间继续查找
· 照此进行下去,不断缩小查找范围
· 至最后,因找到或找不到而停止查找对于 n个数据,若用变量 Top,Bott分别表示每次“折半”
的首位置和末位置,则中间位置 M为
M=Int((Top+Bott)/2)
这样就将 [Top,Bott]分成两段,即 [Top,M-1]和 [M+1,Bott],
若要找的数据小于由 M指示的数据,则该数据在[ Top,M-1]
范围内,反之,则在[ M+1,Bott]范围内折半查找法的过程折半查找法的过程学号 h()
1201
1202
1203
1205
1206
1207
1209
1210
1211
1215
先排好序数学 d( x,1) 语文 d( x,2)
92 86
78 71
83 74
67 75
71 55
62 80
98 83
99 80
57 67
80 78
m=Int((Top + Bott)/2)
要找的学号 No h(m)
= m为所求 m
< Bott = m -1
> Top = m + 1
Top=1
Bott=10
(2) 创建应用程序的用户界面和设置对象属性
(3)编写程序代码
Dim h(10) As Integer,d(10,2) As Integer
Private Sub Form_Load()
'学号存放在数组 h()中
h(1) = 1201,h(2) = 1202,h(3) = 1203
h(4) = 1205,h(5) = 1206,h(6) = 1207
h(7) = 1209,h(8) = 1210,h(9) = 1211,h(10) = 1215
'成绩存放在数组 d(,)中
d(1,1) = 92,d(1,2) = 86
d(2,1) = 78,d(2,2) = 71
d(3,1) = 83,d(3,2) = 74
d(4,1) = 67,d(4,2) = 75
d(5,1) = 71,d(5,2) = 55
d(6,1) = 62,d(6,2) = 80
d(7,1) = 98,d(7,2) = 83
d(8,1) = 99,d(8,2) = 80
d(9,1) = 57,d(9,2) = 67
d(10,1) = 80,d(10,2) = 78
End Sub
Private Sub Command1_Click()
Dim no As Integer,flag As Integer
Dim m As Integer,top As Integer,bott As Integer
flag = -1 '置未找到标志
top = 1,bott = 10 '设定范围
no = Val(Text1.Text) '取学号
If no < h(top) Or no > h(bott) Then
flag = -2 '若超出学号范围,置特殊标志 -2
End If
Do While flag = -1 And top <= bott
m = (top + bott) / 2 '取中点
Select Case True
Case no = h(m) '找到
flag = m '置找到标志
Text2.Text = h(m)
Text3.Text = d(m,1)
Text4.Text = d(m,2)
Text5.Text = (d(m,1) + d(m,2)) / 2
Case no < h(m) '小于中间数据
bott = m - 1 '上半部
Case no > h(m) '大于中间数据
top = m + 1 '下半部
End Select
Loop
If flag < 0 Then '判是否找不到
Text2.Text = ""
Text3.Text = ""
Text4.Text = ""
Text5.Text = ""
MsgBox "无此学生 !"
End If
Text1.SetFocus
End Sub
(1)解题方法数据排序的常用方法:,选择排序法”及“起泡排序法”
“起泡法”排序就是每次将两个相邻的数进行比较,然后将大数调换 (或称“下沉” )到下面。
例如,若有 4个数,则通过三次外循环来完成排序过程:
7
5
3
4
初始 第 1次 第 2次 第 3次寻 找 最 大 数(第一次外循环)
5
7
3
4
5
3
7
4
5
3
4
7
大数“沉底”,小数“浮起”; 如有 n 个数,则要进行 n-1趟比较; 需要两重循环例 6.10 起泡排序法演示程序
(1) 创建应用程序的用户界面和设置对象属性
(2)创建应用程序的用户界面和设置对象属性窗体上含有一个文本框控件数组和一个命令按钮文本框控件数组( Text1(1)~ Text1(8))用来显示演示的 8
个数
(3)编写程序代码功能要求:
程序运行后自动产生 8个两位随机整数单击“排序”按钮 (Command1)时,即启动排序过程通过 MsgBox函数来暂停程序运行
Const n = 8 '声明符号常量
Option Base 1
Private Sub Form_Load()
Randomize
For i = 1 To n '产生 n 个随机数
Text1(i).ForeColor = RGB(0,0,0) '用黑色显示
Text1(i).Text = Int(90 * Rnd + 10)
Next i
End Sub
Private Sub Command1_Click()
For j = 1 To n - 1 '外循环
MsgBox "准备进行第 " + Str(j) + "次比较,按回车键继续 "
For i = 1 To n - j '内循环
If Val(Text1(i).Text) > Val(Text1(i + 1).Text) Then
t = Text1(i).Text
Text1(i),Text = Text1(i + 1).Text
Text1(i + 1).Text = t
End If
Next i
'沉底数用红色表示
Text1(n - j + 1).ForeColor = RGB(255,0,0)
Next j
MsgBox "排序完毕,
End Sub
输入一个含有数字字符和非数字字符的字符串,如
t345+abc12spc276www8t56?
将其中的数字串 (1至多个连续数字字符 )存放到列表框中,
例如将 345放在第一行,12放在第二行,276放在第三行,8
放在第四行,56放在第五行。统计共有多少个数字串
(1)创建应用程序的用户界面和设置对象属性附录 从字符串中抽取数字字符串 (例 6.11)
(2)编写程序代码功能要求,用户在文本框 (Text1)中输入要处理的字符串内容,单击“处理”按钮 (Command1)后,则按要求取出各个数字串并显示在列表框 List1中,统计出数字串的个数并显示在标签 Label3
Private Sub Command1_Click()
k = 0,n = -1,s = Text1.Text '取字符串
For i = 1 To Len(s) '按顺序逐个字符判断
t = Mid(s,i,1) '取 i位置的一个字符
If t < "0" Or t > "9" Then '判是否数字
k = 0 '非数字,置 k=0
Else
If k = 0 Then
n = n + 1 '指向列表框的下一行
List1.List(n) = t '存入列表框
k = 1 '表示刚存过数字
Else '把数字加入到列表框当前行的末尾
List1.List(n) = List1.List(n) + t
End If
End If
Next i
Label3.Caption = Str(n + 1) + "个数字串 "
End Sub
本程序采用按顺序逐个字符判断方式,大致处理过程如下,
(1)取出字符串中的第一个字符,若该字符不是数字,则
k=0;若是数字,则 k=1,并将该数字存入列表框的第一行中
(2)取出下一个字符,判断是不是数字,若不是数字,则
k=0;若是数字,则再判断 k是否为 0,若 k非 0(说明上一个字符也是数字 ),则将该数字加入到列表框的当前行末尾,若 k
为 0(说明这是新数字串的开头 ),则把该数字存入列表框的下一个新行中,并使 k=1
(3)重复 (2)的处理过程,直到把字符串中所有字符都判断完为止