第六章【数组】课后复习材料_第1页
第六章【数组】课后复习材料_第2页
第六章【数组】课后复习材料_第3页
第六章【数组】课后复习材料_第4页
第六章【数组】课后复习材料_第5页
已阅读5页,还剩51页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、第六章 数 组【学习目的和要求】1 掌握静态数组的定义和程序设计方法2 掌握动态数组的定义和程序设计方法3 熟悉控件数组的创建和使用4 掌握数组常用算法的程序设计【学习要点】一何时需要使用数组?在程序设计过程中,如果需要对一组同类型的很多数据进行处理时,就必须使用数组进行程序设计。比如求某班级80个学生某门课成绩的平均分,再统计所有高于平均分成绩的学生人数。如果不用数组,通过简单变量,要么定义80个变量来保存学生的成绩,光赋值语句就得写80行,要么采用循环程序设计,定义一个变量,通过80次循环来接收每个学生的成绩,并计算平均分。程序段如下:Dim cj As Integer, sum As I

2、nteger, ave As Single Dim i As Integer For i = 1 To 80 cj = InputBox(请输入第 & i & 个学生的成绩) sum = sum + cj 求总分 Next i ave = sum / 80 求平均分问题是:当求出平均分后,还需要统计成绩高于平均分的学生人数,而变量cj只能存放一个值,在本循环结束后,cj中存放的是最后一个学生的成绩,它无法同时保存80个学生的成绩,只能再编写程序重新输入80个学生的成绩,依次与平均分进行比较,程序段如下:For i = 1 To 80 cj = InputBox(请输入第 & i & 个学生的成

3、绩) If cj ave Then n = n + 1 统计成绩高于平均分的人数 Next i Print 成绩高于平均分的人数有 & n & 个这样处理会带来2个问题:1 数据的输入量变为原来的2倍2 数据量很大,在第二次输入过程中很可能出现与第一次不一致的情况,造成数据统计的错误。在类似的问题上,如果采用数组处理就可以有效解决上述问题。数组在形式上可以看成为一组同类型的数据集合,每个数组元素拥有相同的名称,但根据其在数组中的位置分配一个唯一标识的序号,如本例中,可以定义一个数组cj(80)来表示成绩,数组名为cj,cj(1)表示第1个学生的成绩,cj(2) 表示第2个学生的成绩,这样只要一

4、次输入,就可以有效解决上面的问题。二数组的形式1一维数组在上例中,只要用一个下标就可以标识一个数组元素,这样的数组称为一维数组。比如定义一个一维数组a(10),表示数组名为a,数组中有11个元素(注意:VB中数组的下标默认为从0开始),分别是a(0)、a(1)、a(2)、a(10)。2二维数组从形式上看,可以把一维数组看成是一个数列,适合于类型相同的一组数据的处理,但有的时候用一维数组处理就不能满足要求了。比如处理一个班50个人4门课的成绩,将其按总分从高到低的顺序进行排序。很显然,这是一张二维表,每个人的4门课成绩构成表中的一行,要表示其中每个人的成绩,都需要指定行和列两个下标才能唯一的确定

5、,这时就需要定义一个二维数组。如定义一个数组cj(50,4),用cj(1,1)表示第一个人的第一门课成绩,cj(2,3)表示第二个人的第三门课成绩。象这样,需要两个下标才能确定一个数组元素在数组中的位置,这样的数组称为二维数组。从形式上看,二维数组就是一张二维表格。比如定义一个二维数组a(1 To 3,1 To 4),共有12个元素,分成3行4列,其中每个元素的分布如下表5-1所示:表5-1a(1,1)a(1,2)a(1,3)a(1,4)a(2,1)a(2,2)a(2,3)a(2,4)a(3,1)a(3,2)a(3,3)a(3,4)3多维数组如果数组中的每个元素需要2个或2个以上的下标才可以标

6、识,这样的数组统称为多维数组。比如三维数组a(3,4,2)中的每个元素都需要3个下标才能够唯一的确定。以后我们进行程序设计时,定义的数组一般不会超过三维,所以应重点掌握一维和二维数组的使用。三数组的定义程序中用到的变量,可以不定义就使用,如果没有定义,系统会自动定义其类型为变体型。但数组不可以直接使用,所有的数组只有先定义才可以使用。VB提供了两类数组可以定义。1 固定大小的数组定义如果在程序设计时可以确定其大小和维数,这样的数组称为固定大小数组。比如:Dim a(20) As Integer,表示定义一个固定大小的数组a,有21个元素,下标从0到20。固定大小的数组一经定义,以后在程序中就不

7、能再改变其大小和维数。例6-1 以下定义数组的语句错误的是_。A Dim a(-3 to 5) As IntegerB Dim a(1 to 6.7) As SingleC Dim a(n) As IntegerD Dim a(-2 to 3,2*3) As Integer分析:选项A中定义一个整型的一维数组,分别为a(-3)、a(-2)、a(5) ,共9个元素;在VB中如果数组下标不是整数,系统会自动四舍五入取整,所以选项B等价于Dim a(1 To 7) As Integer;选项D表示定义一个整型的二维数组,其中第一维的下标从-2到3,第二维的下标从0到6,一共有6*7=42个元素;选项

8、C是错误的,因为VB不允许用变量来定义数组,如果不能确定数组大小,定义时数组名后的()中也不能是变量,必须将其定义成动态数组:Dim a ( ) As Integer,数组名后的()中不写任何内容。考虑以下定义数组的语句是否正确?1)Const n As Integer = 6 Dim a(n) As Integer2)Dim a(n) As Integer Const n As Integer = 63)Dim a(5 To -3) As Integer分析:定义1是正确的,这时n是符号常量,相当于常量6,所以Dim a(n) As Integer等价于Dim a(6) As Integer

9、;定义2是错误的,因为在执行Dim a(n) As Integer之前并没有定义符号常量n,VB不允许用变量定义数组;定义3是错误的,因为定义数组时不允许其下界高于上界。2 动态数组定义如果在程序设计时不能确定数组的大小和维数,就必须定义动态数组。动态数组的大小和维数可以在程序运行时根据需要改变。动态数组的定义和固定大小数组不同,它一般分两个步骤进行:1) 用数组名加()来定义动态数组比如需要定义一个整型的动态数组b,只能按以下格式定义:Dim b() As Integer表示b是一个数组,但数组的大小和维数都不确定,以后在程序运行时可根据需要定义。注意:只能用数组名后加()来定义,不能写成b

10、(n)或b(m,n)或b(,)等形式。2) 用Redim重新定义动态数组大小动态数组只有用Redim重新定义后才可以使用。比如上面定义的数组b,如果在程序运行时需要定义其为10个元素的一维数组,则可以执行语句Redim b(1 to 10),若需要定义其为3行4列的二维数组,则可以执行语句Redim b(1 to 3,1 to 4)。一旦用Redim重定义动态数组后,该数组就可以象固定大小数组一样地使用。3 Option Base 1数组默认的下标下界是0,如果希望定义数组的下标从1开始,可以在模块的通用声明段中用Option Base 1说明。注意:1)Option Base后面只可以是0或

11、1,不能是其他数字。比如不能通过Option Base 2让数组的下标从2开始。2)Option Base语句只可以出现在模块的通用声明段,不可以出现在过程中。四数组的使用1数组元素的引用数组定义后,可以通过下标来引用数组的每个元素。和数组的定义不同,引用数组元素时下标可以是变量、常量或表达式。例6-2 以下引用数组元素的语句中正确的是_。ADim a(2, 3) As Integer a(1) = 10BDim a(3 To 6) As Single a(1) = 1Ca(n + 3) = a(n - 1) + a(n)DDim a(5) As Single a = 1分析:选项A中定义一个

12、3行4列的二维数组(注意:每一维的下标下界默认为0),每个数组元素必须用两个下标表示,比如,第一个元素应该为a(0,0),第2行第2列的元素应该为a(1,1)。不允许通过a(1)企图引用二维数组中的某个元素,所以选项A是错误的;选项B中定义一个单精度型一维数组,规定下标的范围从3到6,不存在下标为1的元素,所以引用a(1)会出现“下标越界”的错误;选项D中定义一个一维数组,数组名为a,拥有6个元素,分别是a(0)到a(5),对数组赋值只能分别对每个元素赋值,而不能通过给a赋值来达到给所有数组元素赋值的目的,程序中并不存在名称为a的变量,所以选项D是错误的;由于引用数组元素时允许下标是变量和表达

13、式,所以选项C的含义是计算a(n - 1) + a(n)的值,并将其赋给数组元素a(n + 3),比如,当n为2时,该语句的功能是计算a(1)+a(2) 的值,并将其赋给数组元素a(5),很显然,选项C是正确的。归纳一下:1) 引用数组元素时要注意,下标不能越界,即数组元素的下标不允许比定义数组时的上界大,也不允许比下界小。2) 一维数组元素用1个下标引用,二维数组元素必须用2个下标引用,依次类推。3) 引用数组元素时,下标可以是变量和表达式。4) 对数组元素操作时,不可以直接引用数组名,只可以引用单个数组元素。2数组的相关函数数组的相关函数只需要掌握以下三个:1) LBound:获得数组某一

14、维下标的下界格式:LBound(数组名)或LBound(数组名,维数)比如Lbound(a)表示返回数组a第一维下标的下界;Lbound(a,2) 表示返回数组a第二维下标的下界。2) UBound:获得数组某一维下标的上界格式:UBound(数组名)或UBound(数组名,维数)例6-3 执行以下程序段, 输出结果是_。Dim a(-3 To 5) As Single Dim b(3, 4) As Integer Print UBound(a), UBound(b, 1) Print LBound(a), LBound(b, 2)分析:根据UBound和LBound函数的功能可以知道,第一行

15、的输出结果是5 3,第二行的输出结果是-3 0。3)Array函数利用Array函数可以将一个变体型变量创建成一维数组,同时实现数组元素的赋值。例6-4 执行以下程序段, 第一行输出结果是_,第二行输出结果是_。Private Sub Form_Click() Dim a Dim i As Integer a = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) For i = 0 To 3 Print a(5 - i); Next Print a = Array(abc, 123, def)Print a(1)End Sub分析:根据Array函数的功能,赋值语句a = Ar

16、ray(1, 2, 3, 4, 5, 6, 7, 8, 9)将变体型变量a创建成一个整型的一维数组,有9个元素,下标从0到8(注意:默认下标的下界为0),其中a(0)的值为1,a(1)的值为2,a(8)的值为9。For循环的功能是分别输出a(5)、a(4)、a(3)、a(2)的值,所以第一行输出结果为6 5 4 3;执行赋值语句a = Array(abc, 123, def)后,a被创建成一个字符串型的一维数组,有3个元素,下标从0到2,a(1)的值为123,所以第二行输出结果为123。例6-5 执行以下程序段,输出结果是_。Private Sub Form_Click() Dim a(9)

17、As Variant Dim i As Integer a = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) Print a(2)End Sub分析:由于Array函数只能给变体型简单变量或变体型动态数组赋值,虽然程序中定义的a(9)是变体型数组,却是固定大小的数组,所以上述程序运行时会出错。考虑一下:如果将上述程序改成以下程序段,输出结果是多少?Dim a() As Variant Dim i As Integer a = Array(1, 2, 3, 4, 5, 6, 7, 8, 9) Print a(2)注意:Array函数只能生成一维数组,不能生成多维数组; Arr

18、ay函数只能给变体型变量和变体型动态数组赋值,赋值时有多少个数值,生成的一维数组就有多少个元素,数组的类型由数值的类型决定。3数组相关语句对于数组的相关语句,只需要大家掌握Erase语句的功能。例6-6 执行以下程序段,输出结果是_。Option Base 1Private Sub Command1_Click() Dim a, b(5) As Integer a = Array(1, 2, 3, 4, 5) b(2) = a(a(1) + 2) Print a(2), b(2) Erase a, b Print b(2) Print a(2)End Sub分析:程序中定义变量a为变体型变量,

19、b为一维数组,有5个元素,下标从1到5。执行语句a = Array(1, 2, 3, 4, 5)后将a创建成一维数组,有5个元素,值分别为1、2、3、4、5;因为a(1)值为1,所以语句b(2) = a(a(1) + 2)等价于将a(3) 的值赋给b(2),第一行的输出结果为2 3 。注意:Erase语句对动态数组和固定大小数组有不同的功能。若a是动态数组,执行语句Erase a的功能是释放动态数组a的空间,此时a没有任何元素,在内存中也没有空间分配,除非用Redim重新定义,否则该数组不可访问;若a是固定大小数组,执行语句Erase a的功能是将原来数组的值全部清空,但数组空间仍存在。由于a

20、是Array 函数创建的动态数组,b是固定大小数组,程序中执行Erase a, b后,数组a的空间将被撤消,数组b的每个元素值将恢复初始值0,所以运行上述程序后,第二行的结果为0,但执行到Print a(2)语句时程序会出现“下标越界”错,因为此时已经不存在数组元素a(2)。五数组的输入输出操作数组由于其构成和存储的特殊性,非常适合用循环程序来实现其各种操作。1一维数组的输入输出例6-7 定义一个包含20个元素的整型数组,让用户输入每一个值,并在窗体上打印输出。 分析:假设数组名为a,数组元素下标从1变化到20,即a(1)到a(20),每一个数组元素都执行统一的输入和输出操作,同样的操作要执行

21、20次,很显然用循环处理更方便。设一个循环控制变量,假设为i,每个数组元素可用a(i)来表示,i的值从1变化到20,在循环体中对每一个a(i)执行相关操作。程序如下:Private Sub Form_Click() Dim i As Integer, a(1 To 20) As Integer For i= 1 To 20 Rem 从键盘输入a(i)的值,i的值从1变化到20,即输入a(1)一直到a(20)的值a(i) = InputBox(请输入a( & i & )的值) Next i Rem 输出a(1)到a(20)的值 For i = 1 To 20 步长缺省,默认为1 Print a(

22、i); Next i Next语句完成给循环变量i增加步长的操作,即i=i+1End Sub不难发现,输入和输出都是20次循环,还可将以上程序简化为: Dim i As Integer, a(1 To 20) As Integer For i= 1 To 20 a(i) = InputBox(请输入a( & i & )的值) Print a(i); Next i 这样利用一次循环就可以同时实现输入和输出操作。当然,以上程序段用Do-loop语句也可实现。程序段如下: Dim i As Integer, a(1 To 20) As Integer i = 1 Do While i Sqr(n)

23、Then n是素数 将计数器加1,动态数组大小增加一个,并给新增加元素赋值 k = k + 1 ReDim Preserve a(k) a(k) = n End If Next n 输出数组元素 For i = 1 To UBound(a) Print a(i); If i Mod 5 = 0 Then Print Next i归纳一下:当在程序设计中不能直接确定数组大小时,就可以采用上述的方法来实现,即将动态数组的重定义与计数器配合起来使用,这是通常的做法。七控件数组1控件数组元素的访问如果程序界面上有很多同类型的控件,并且他们需要执行相同或相似的操作,就可以考虑使用控件数组。控件数组中,每

24、个元素都是指定类型的控件,其所有的属性、方法和事件都和简单控件一样,但这时访问控件的标识符以及响应事件的过程框架会有区别,具体表现为:1)简单控件和控件数组元素的访问名称比如,在窗体上有3个文本框控件,如果是简单控件,其名称可能是Text1、Text2和Text3,但如果是控件数组,则它们的名称必须相同(相当于数组名),每个控件数组元素必须通过数组名(下标)的方式来访问。假设将3个文本框的名称都设置为Text1,则3个文本框将分别是Text1(0)、Text1(1)和Text1(2),其中元素的下标可以在属性窗口中设置其Index属性。注意:普通控件也有Index属性,但值为空,不能设置任何数

25、值;控件数组元素的Index属性代表其下标,值为大于等于0的数值。2)属性和方法的使用虽然控件数组的每个元素和简单控件具有相同的属性和方法,要注意引用属性和方法时,所有控件数组元素必须带下标。比如普通的文本框控件Text1,引用其Text属性可以用Text1. Text,执行设置焦点的方法可以用语句Text1.Setfocus实现;而对于文本框控件数组元素Text1(0),则必须用Text1(0) . Text和Text1(0) . Setfocus实现。3)事件过程的框架对于一个控件数组来讲,数组中的每个元素都响应同一个事件过程,但其事件过程框架会比简单控件对应的事件过程多一个参数Index

26、。比如一个名称为Text2的文本框的Change事件过程框架为:Private Sub Text2_Change() End Sub对于上面的文本框控件数组Text1,它有3个元素,分别是Text1(0)、Text1(1)和Text1(2),它们响应的Change事件过程框架为:Private Sub Text1_Change(Index As Integer) End Sub因为3个控件元素都响应同样的事件过程,所以为了知道在事件发生时,究竟是哪个控件响应了该事件,控件数组的事件过程中都会比简单控件事件过程多一个参数,Index返回响应事件的数组元素的下标。比如Index值为0时,表示Tex

27、t1(0)元素引发了该事件,Index值为2时,表示Text1(2)元素引发了该事件。很多时候,在控件数组的事件过程的处理都是和多分支结构的程序配合完成。例6-14 在窗体上有一个文本框和三个单选按钮,单选按钮构成控件数组op1,下标分别为0、1、2,要求实现程序运行时,根据单选按钮的选中情况改变文本框的字体。界面如下图5-1所示:图5-1按上述要求完善以下程序:Private Sub Op1_Click (Index As Integer) Select Case (1) Case 0 Text1.FontName = 宋体 Case 1 Text1.FontName = 黑体 Case (

28、2) Text1.FontName = 隶书End SelectEnd Sub分析:3个单选按钮构成一个控件数组,当单击“宋体”单选按钮op1(0),将文本框字体设置为“宋体”,当单击“黑体”单选按钮op1(1),将文本框字体设置为“黑体”,依次类推。每个单选按钮都响应同一个事件过程,在Index参数中记录了响应事件的控件下标。很显然,Select Case语句中需要根据Index识别是哪个控件响应了该事件,所以(1)应该填入Index,填空(2)中应该填入2或Else。考虑一下:上述事件还可以改为以下程序段实现,效果是一样的。Private Sub Op1_Click(Index As In

29、teger) Text1.FontName = Op1(Index).CaptionEnd Sub八数组相关算法程序设计1数组的排序假设已将n个数存放在数组中,要求将其按从小到大的顺序排序。排序是程序设计中很重要的算法,排序的算法有很多,这里介绍两种常见的算法:选择法和冒泡法。1)选择法排序 选择法的排序思想是:a、 将第一个数依次与后面的n-1个数进行比较,如果有一个数比它小,就执行交换操作,经过这一轮比较,产生最小数放在第一个数中。b、 将第二个数再依次与后面的n-2个数进行比较,如果有一个数比它小,就执行交换操作,经过这一轮比较,产生第二小的数放在第二个数中。c、 重复执行以上操作,最后

30、是第n-1个数和第n个数进行比较,如果后者小于前者,执行交换,否则保持原值。从以上的排序过程可以看出:n个元素排序要进行n-1轮的比较,每一轮中要进行若干次比较,所以排序的算法是一个双重循环。若用循环变量i表示比较的轮数,则i的值从1变化到n-1,当i=1时, a(1)分别与a(2)到a(n)的每一个元素进行比较,一旦有元素比a(1)小就执行交换;当i=2时, a(2) 分别与a(3)到a(n)的每一个元素进行比较,一旦有元素比a(2)小就执行交换;所以在第i轮的比较中, a(i)分别与a(i+1)到a(n)的每一个元素进行比较,一旦有元素比a(i)小就执行交换。若用j表示内循环的控制变量,则

31、j的值是从i+1变化到n。因为涉及到交换,所以还需定义变量Temp作交换时的临时变量。例6-15 随机产生10个三位正整数,用选择法将其按增序排序,并输出原始顺序和排序后的顺序。(分析见上面) 程序如下:Option Base 1Private Sub Form_Click() Dim a(10) As Integer, i As Integer, j As Integer Dim temp As Integer Randomize Print 原始顺序: For i = 1 To 10 a(i) = Int(Rnd * 900) + 100 利用随机函数产生数组元素的值 Print a(i)

32、; Next i Print For i = 1 To 9 10个元素,外围循环需要9次 For j = i + 1 To 10 每次a(i)都和其后面的每个元素作比较 If a(i) a(j) Then 如果a(i) a(j)就执行交换 temp = a(i) a(i) = a(j) a(j) = temp End If Next j Next i Print 排序后的顺序: For i = 1 To 10 Print a(i); Next i End Sub优化一下: 从上面排序的执行可以看出,在第i轮的比较中,只要有一个数比它小就执行交换,实际上这里有很多交换是无效的,因为每一轮比较中,

33、a(i)只需与当前的最小元素执行一次交换既可,无需发现比它小的数就执行交换。因此可将选择法优化一下,过程如下:a、 对有n个数的序列,从中选出最小的数,与第1个数交换。b、 除第1个数外,其余n-1个数再按a的方法选出最小的数,与第2个数交换。c、 重复以上操作,直到最后只剩下一个数时结束。假设数组a中有5个元素,下标从1到5,分别被赋值为 12、23、15、34、9。排序的执行过程如下所示:(下划线部分表示执行交换的两个数组元素) 原始数据 12、23 、15、34、9 a(1) a(2) a(3) a(4) a(5) 第1遍交换后 9 、23 、15、34、12 a(2) a(3) a(4

34、) a(5) 第2遍交换后 9 、12 、15、34、23 a(3) a(4) a(5) 第3遍交换后 9 、12 、15 、34、23 a(4) a(5) 第4遍交换后 9 、12 、15 、23 、34 可以看出,优化的选择法执行外层和内层的循环次数完全一样,只不过在每轮比较中,优化的选择法不会频繁执行交换操作,在数据量比较大时可提高运行效率。优化的选择法在每轮比较中,是找出该轮的最小值后再进行交换。若用循环变量i表示比较的轮数,在第i轮的比较中,只需记录a(i)到a(n)中的最小元素所在的下标k,如果k不等于i,则将a(k)与a(i)交换,否则说明a(i)中就是最小值,不需交换,所以每轮

35、比较中最多执行一次交换。所以上述排序部分的程序段可优化如下: For i = 1 To 9 k = i 将本轮第一个元素下标赋给k For j = i + 1 To 10 只要发现有元素的值比a(k)小,就用k记录最小元素所在的下标If a(k) a(j) Then k = j Next j 如果a(i)不是本轮最小元素,将a(i)与本轮最小元素a(k)交换 If k i Then temp = a(i) a(i) = a(k) a(k) = temp End If Next I2)数组的冒泡法排序冒泡排序法主要是比较相邻两个元素的值,如果前面的数比后面的数大,就执行一次交换,即在每一轮的比较

36、中都产生了本轮的最大值。下面以一个例子来看一下冒泡排序法的执行过程。为方便叙述,假设有一个数组a(4),下标从1开始,现将其按冒泡法进行排序。排序的执行过程如下所示:(下划线部分表示执行交换的两个数组元素,每次都是相邻两个元素之间进行比较) 原始数据 34 、23 、15 、9 a(1) a(2) a(3) a(4) 第1轮 23 、34 、15 、9 23 、15 、34 、9 23 、15 、9 、34 a(1) a(2) a(3) 第2轮 23 、15 、9 15 、23 、9 、 15 、9 、23 、 a(1) a(2) 第3轮 15 、9 9 、15 排序后数据 9 、15 、23 、34 由上述的排序过程可看出,n个数按冒泡法排序也需n-1轮比较,每一轮中也要进行若干次比较,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论