1、第 6 章,数组,利用数组可以有效地存储和处理成批数据本章主要内容,第6章 数 组,退出,处理成批的数据时,必须使用数组来处理。例如,表示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称为下标变量的下标(默认情况下,下标从0开始)由三行四列组成的二维数组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
2、,0) y(2,1) y(2,2) y(2,3)只要有规则地改变下标值,就可以很方便地使下标变量(如t(k)成为所需要的具体下标变量,6.1 数组的概念,6.2.1 数组声明语句使用数组之前,一般需要定义数组,以便让系统分配相应的存储单元。格式为:Dim 数组名(下界1 to上界1,下界2 to上界2)As 数据类型 功能:指定数组的维数、各维的上下界和数据类型 举例: Dim Sum(10) As Long 下标号从010,共11个元素 Dim Ary(1 to 20) As Integer 下标号从120,共20个元素 Dim d(1 to 5,1 to 10) As Double 定义二
3、维数组还可以使用Public、Static、Private等语句来声明数组,6.2 数组的声明和应用,设定下界的方法 Option Base 1 设定下界为1 Dim Data(10) As Single 下标号从1106.2.2 Array函数使用Array函数可以为数组元素赋值示例Dim D As Variant 定义数组名(变体类型)D = Array(1, 2, 3, 4)执行结果:1D(0),2D(1), 3D(2), 4D(3),例6.1 输入某小组5个同学的成绩,计算总分和平均分(取小数后一位)本例利用InputBox函数来输入成绩,输入完毕后经过计算,再采用Print直接在窗体
4、上输出结果,6.2.3 数组的应用,Private Sub Form_Load()Dim d(5) As IntegerDim i As Integer, total As Single, average As SingleShowFor i = 1 To 5 输入成绩d(i) = Val(InputBox(“请输入第“ & Str(i) & _“个学生的成绩“, “输入成绩“)Next itotal = 0For i = 1 To 5 计算总分和平均分total = total + d(i)Next iaverage = total / 5Print “总分:“ & totalPrint “
5、平均分:“ & Format(average, “#.0“) End Sub,例6.1,(1)创建应用程序的用户界面和设置对象属性,例6.2 输入10名学生的成绩,求出最高分和最低分,例6.2,功能要求:通过Array函数输入10个分数;单击“查找”按钮(Command2)后,开始查找最高分和最低分,找到后显示在标签Label1上Option Base 1Dim score As VariantPrivate Sub Form_Load()Label1.Caption = “单击“查找”按钮开始查找最高分和最低分“score = Array(89, 96, 81, 67, 79, 90, 63
6、, 85, 95, 83)End Sub,(2) 编写程序代码,Private Sub Command1_Click()Dim max As Integer, min As Integermax = score(1) 设定初值min = score(1)For i = 2 To 10 与后面的数据逐一比较If max score(i) Then 找最低分min = score(i)End IfNext iChr(13)起换行作用Label1.Caption = “最高分:“ + Str(max) + _Chr(13) + “最低分:“ + Str(min)End Sub,例6.3 分别计算5个
7、学生和3门课的平均分,某学习小组有5名学生,成绩如表6.1所示分析:用一个二维数组a(5, 3)来描述。程序中设置两重循环,用以实现每行和每列上的累加。本例采用赋值语句来输入学生成绩,并采用Print直接在窗体上输出结果Option Base 1Private Sub Form_Load()Dim a(5, 3) As IntegerDim r As Integer, c As Integer, s As Integerk = Array(“数学“, “英语“, “计算机“) 输入课程名a(1, 1) = 69: a(1, 2) = 89: a(1, 3) = 74 输入学生成绩a(2, 1)
8、 = 94: a(2, 2) = 80: a(2, 3) = 90a(3, 1) = 57: a(3, 2) = 62: a(3, 3) = 73a(4, 1) = 98: a(4, 2) = 94: a(4, 3) = 90a(5, 1) = 73: a(5, 2) = 76: a(5, 3) = 63,ShowPrint “学生“, “平均分“Print String(20, “-“) 输出20个减号“-”For r = 1 To 5s = 0 累加前清0For c = 1 To 3累加同一行数据s = s + a(r, c)Next cPrint r, Format(s / 3, “#.
9、0“)Next rPrint,Print “课程“, “平均分“Print String(20, “-“)For c = 1 To 3s = 0 For r = 1 To 5累加同一列数据s = s + a(r, c) Next rPrint k(c), Format(s / 5, “#.0“)Next c End Sub,程序运行结果,例6.3,1. 执行下列程序段后,输出的结果是_。Dim a(1 To 3, 1 To 3)For j = 1 To 3For k = 1 To 3a(j, k) = jPrint a(j, k);Next kPrintNext jA. 3 2 1 B. 0
10、1 2 C. 1 2 3 D. 1 1 12 3 2 1 0 1 2 1 2 2 2 21 2 3 2 1 0 3 2 1 3 3 3,下列程序的运行结果?,想一想,思考题,D,1. 执行下列程序段后,输出的结果是_。Dim a(1 To 4, 1 To 4)For j = 1 To 4For k = 1 To 4a(j, k) = Abs(j - k)Print a(j, k);Next kPrintNext jA. 3 2 1 0 B. 0 1 2 3 C. 0 1 1 1 D. 3 3 3 32 1 0 3 1 0 1 2 1 0 1 1 2 2 2 21 0 3 2 2 1 0 1 1
11、 1 0 1 1 1 1 10 1 2 3 3 2 1 0 1 1 1 0 0 0 0 0,下列程序的运行结果?,想一想,思考题,B,两种形式的数组:静态数组和动态数组静态数组(前面介绍的)是指数组元素的个数固定不变;动态数组的元素个数,在程序运行时可以改变动态数组可以在运行过程中改变数组的大小,提高存储区的使用效率6.3.1 建立动态数组用ReDim语句重新定义带下标的动态数组6.3.2 数组刷新语句 Erase语句用来清除静态数组的内容,或者释放动态数组占用的内存空间,6.3 动态数组,Dim t() As Integer 声明一个动态数组ReDim t(100) 用ReDim语句重新定义
12、ReDim t(200) 用ReDim语句重新定义,静态数组和动态数组,Dim t(200) As Integer 声明一个静态数组For k=1 To 200t(k) = Next k,使用 静态数组个数固定不变,使用 动态数组个数可以改变,Private Sub Form_Load()Dim a() As Integer 声明一个整型动态数组ShowReDim a(800) 用ReDim语句重新定义k = 0For x = 200 To 600 Step 3If x Mod 8 = 0 Then k = k + 1a(k) = xEnd IfNext xReDim Preserve a(k
13、) Preserve 能保留数组中原有的数据For i = 1 To kPrint a(i)Next i End Sub,例6.4 ReDim语句应用示例,例6.4,与前面的循环语句For.Next类似,都是用来执行指定重复次数的循环。但For Each.Next语句专门作用于数组或对象集合中的每一成员。语法格式: For Each 成员 In 数组名 循环体 Exit For Next 成员“成员”是一个Variant变量,它实际上代表数组中每一个元素本语句可以对数组元素进行读取、查询或显示,它所重复执行的次数由数组中元素的个数确定在不知道数组中元素的数目时非常有用,6.4 For Each
14、.Next循环语句,6.5 控件数组,两类数组:一般数组和控件数组6.5.1 控件数组的概念 控件数组是一组具有相同名称、类型和事件过程的控件例如,Label1(0),Label1(1),Label1(2), 但Label1, Label2, Label3, 不是控件数组控件数组具有以下特点: (1)相同的控件名称(即Name属性); (2)控件数组中的控件具有相同的一般属性;(3)所有控件共用相同的事件过程。以下标索引值(Index)来标识各个控件,第一个下标索引号默认为0,6.5.2 控件数组的建立,建立控件数组有三种方法: (1)给控件起相同的名称 (2)将现有的控件复制并粘贴到窗体等上
15、面 (3)将控件的Index属性设置为非Null数值6.5.3 控件数组的使用例6.6 建立一个文本框控件数组Text1和一个文本框Text2,在控件数组Text1中输入一组数后,把累加值存放在Text2。,通过“复制”方法控件数组Text1。第一次 单击工具栏上的“粘贴”按钮(或按Ctrl+V),此时系统弹出一个如下的对话框,例6.6,控件数组Text1的4个元素为:Text1(0)Text1(3)Private Sub Command1_Click()s = 0For i = 0 To 3s = s + Val(Text1(i).Text)Next iText2.Text = sEnd S
16、ub,注意:控件数组元素的表示方法与列表框表项有所不同列表框List1的表项内容为:List1.List(0)、 List1.List(1)、。下标规定为顺序号0,1,2,。一个列表框控件,其List属性是一个数组。控件数组Text1的元素内容为:Text1(0).Text、Text1(1).Text、。下标可由用户指定,不一定为顺序号。多个控件组成一个数组,相同名称。使用这些控件的Text属性。,例6.7 按图6.6设计窗体,其中一组(共3个)单选按钮构成控件数组,要求当单击某个单选按钮时,能够改变文本框中文字的大小,例6.7,设计步骤:(1)设计控件数组Option1,其中包含3个单选按钮
17、对象设置控件数组各元素(从上而下)的Caption属性分别为12,20和28 (2)建立一个文本框Text1,其Text属性设置为“控件数组的使用”。再建立一个标签,其Caption属性为“字号控制” (3)编写程序代码,Private Sub Form_Load()Option1(0).Value = True 选定第一个单选按钮Text1.FontSize = 12 设定文本框中的字号End SubPrivate Sub Option1_Click(Index As Integer)Select Case Index 系统自动返回Index值Case 0Text1.FontSize = 1
18、2Case 1Text1.FontSize = 20Case 2Text1.FontSize = 28End SelectEnd Sub,控件数组的事件过程,数组是程序设计中广泛使用的一种数据结构,它可以方便灵活地组织数据。数组应用的一个重要内容:排序与查找排序:将一组数按递增或递减的次序排列查找:从数组中查找所需的数据,6.6 程序举例,排序查找,顺序查找 折半查找,选择法排序 冒泡法排序,随机产生十个10100的整数,用“选择排序法”按值从小到大顺序排序,最后输出结果。 解题方法: (1)利用Int(91*Rnd+10)产生值为10到100的随机整数 使用Randomize得到不同的随机数
19、序列 (2)按值从小到大进行排序。排序方法: 将10个数放入数组a中,对下列下标变量进行排序处理: a(1), a(2), a(3), , a(8) , a(9) , 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)存放的就是最
20、大值,例6.8 选择排序法,排列要求 小 大 示例: a(1) a(2) a(3) a(4)90 64 61 591. a(1)与a(2) a(4)比较,选出最小值,结果59 64 61 902. a(2)与a(3) a(4)比较,选出次小值,结果59 61 64 903. a(3)与a(4)比较,选出较小值,结果59 61 64 90i=1 j=2, 3, 4i=2 j=3, 4i=3 j=4,For i=1 to 3For j=i+1 to 4Next j Next i,程 序 结 构,循环体 比较a(i)与a(j) 若a(i)大于a(j) 则a(i)与a(j)交换值,假设要对4个数排序,
21、两重循环 对4个数排序 外循环 i 次数为3 内循环 j 次数为i+14,完成上述比较及排序处理过程,可以采用两重循环结构,外循环的循环变量i从1到9,共循环九次;内循环的循环变量j从i+1到10。 本例采用默认的用户界面,所需数据由随机函数产生,处理后结果信息通过Print方法直接输出在窗体上。 Private Sub Form_Load()ShowRandomizeDim a(1 To 10) As IntegerPrint “原始数据:“For i = 1 To 10 产生10个随机数a(i) = Int(91 * Rnd + 10)Print a(i);Next i,(3) 程序结构,
22、Print: PrintFor i = 1 To 9For j = i + 1 To 10If a(i) a(j) Thent = a(i): a(i) = a(j): a(j) = t 交换位置End IfNext jNext iPrint “排序结果:“For i = 1 To 10Print a(i);Next iEnd Sub,例6.8,改写中间程序段“For i=1 To 9”“Next i”(共7个程序行)For i = 1 To 9k = i k用来记录每次选择的最小值的下标For j = i + 1 To 10If a(k) a(j) Thenk = jEnd IfNext j
23、t = a(k): a(k) = a(i): a(i) = t 交换位置Next i变量k记录每一次选出的最小值的下标,在本次比较结束后,使a(i)与a(k)一次换位即可,例6.8a,例6.9 查找考场教室号某课程统考凭准考证入场,考场教室安排如表6.2。编制程序,查找准考证号码所对应的教室号码(1)分析:为便于查找,通过二维数组rm建立这两种号码对照表。数组rm由Form_Load事件过程来建立,它的每一行存放了一个教室资料(包含准考证号码范围和教室号码)。当判断到某个给定准考证号码落在某一行的准考证号码范围内时,则该行中的教室号码为所求,先用给定号码与第1行的Rm(1,1)及Rm(1,2)
24、比较若在此范围内,则Rm(1,3)为所求,若不是第1行,则与第2行的Rm(2,1)及Rm(2,2)比较若在此范围内,则Rm(2,3)为所求,依此类推 顺序比较,(3)编写程序代码 功能要求:用户在文本框Text1中输入准考证号码,单击“查找”按钮(Command1)后,则查找出对应的教室,并将教室号码输出在文本框Text2中Dim rm(6, 3) As IntegerPrivate Sub Form_Load() 输入数组数据,一行存放1个教室信息 rm(1, 1) = 2101: rm(1, 2) = 2147: rm(1, 3) = 102rm(2, 1) = 1741: rm(2, 2
25、) = 1802: rm(2, 3) = 103rm(3, 1) = 1201: rm(3, 2) = 1287: rm(3, 3) = 114rm(4, 1) = 3333: rm(4, 2) = 3387: rm(4, 3) = 209rm(5, 1) = 1803: rm(5, 2) = 1829: rm(5, 3) = 305rm(6, 1) = 2511: rm(6, 2) = 2576: rm(6, 3) = 306End Sub,例6.9,(2)创建用户界面和设置对象属性,Private Sub Command1_Click()Dim no As Integer, flag As
26、 Integerflag = 0 查找标记,0表示未找到no = Val(Text1.Text)For i = 1 To 6If no = rm(i, 1) And no = rm(i, 2) ThenText2.Text = rm(i, 3) 显示教室号码flag = 1 1表示找到Exit ForEnd IfNext iIf flag = 0 ThenText2.Text = “无此准考证号码“End IfText1.SetFocus 设置焦点 End Sub,某学习小组10名学生的成绩情况如表6.3所示,现要求采用折半查找法,通过学号查询学生成绩(1)分析:折半查找法也称对半查找法,是一
27、种效率较高的查找方法。对于大型数组,它的查找速度比顺序查找法(例6.8采用的是顺序查找法)快得多假设要查找的数据个数为n=1000顺序查找的平均次数为500,即1000/2折半查找的最大次数为x=10, 即 2x = 1000在采用折半查找法之前,要求将数组按查找关键字(如本例的学号)排好序(从大到小或小到大),例6.10 采用折半查找法查询学生成绩, 先从数组中间开始比较, 判别中间的那个元素是不是要找的数据:是,则查找成功否,若被查找的数据是在该数组的上半部,则从上半部的中间继续查找,否则从下半部的中间继续查找 照此进行下去,不断缩小查找范围 至最后,因找到或找不到而停止查找 对于n个数据
28、,若用变量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
29、 67 80 78,m=Int(Top + Bott)/2) 要找的学号No h(m)= m为所求 mTop = m + 1,Top=1,Bott=10,(2) 创建应用程序的用户界面和设置对象属性(3)编写程序代码,例6.10,Dim h(10) As Integer, d(10, 2) As Integer 模块级变量Private Sub Form_Load() 学号存放在数组h()中h(1) = 1201 : h(2) = 1202: h(3) = 1203h(4) = 1205 : h(5) = 1206: h(6) = 1207h(7) = 1209 : h(8) = 1210:
30、h(9) = 1211: h(10) = 1215成绩存放在数组d(,)中d(1, 1) = 92 : d(1, 2) = 86d(2, 1) = 78 : d(2, 2) = 71d(3, 1) = 83 : d(3, 2) = 74d(4, 1) = 67 : d(4, 2) = 75d(5, 1) = 71 : d(5, 2) = 55d(6, 1) = 62 : d(6, 2) = 80d(7, 1) = 98 : d(7, 2) = 83d(8, 1) = 99 : d(8, 2) = 80d(9, 1) = 57 : d(9, 2) = 67d(10, 1) = 80 : d(10
31、, 2) = 78End Sub,Private Sub Command1_Click()Dim no As Integer, flag As IntegerDim m As Integer, top As Integer, bott As Integerflag = -1 置未找到标志top = 1: bott = 10 设定范围no = Val(Text1.Text) 取学号If no h(bott) Thenflag = -2 若超出学号范围, 置特殊标志-2End If,Do While flag = -1 And top h(m) 大于中间数据top = m + 1 下半部End SelectLoop,If flag 0 Then 判是否找不到Text2.Text = “Text3.Text = “Text4.Text = “Text5.Text = “MsgBox “无此学生!“End IfText1.SetFocusEnd Sub,