母亲父亲刘和刚演唱:VB数组

来源:百度文库 编辑:中财网 时间:2024/04/26 22:41:26

VB数组
━━━━━━━━━━━━━━━━━━━━━━━━━━

知识要点
1.数组的概念

数组:存放具有相同性质的一组数据,也就是数组中的数据必须是同一个类型和性质。
数组元素:数组中的某一个数据项。数组元素的使用同简单变量的使用。

2.静态数组的声明

静态数组:在声明时已确定了数组元素个数。
声明形式:Dim数组名([下界To]上界[,[下界To]上界[,…]])As 类型
此语句声明了数组名、数组维数、数组大小、数组类型。

[注意]

下界、上界必须为常数,不能为表达式或变量:省略下界,默认为0,也可用Option Base语句重新设置下界的值。

3.动态数组的声明

声明形式:    Dim数组名 ()
       ReDim [Preserve]数组名([下界To]上界[,[下界To]上界[,…]])

[注意]

此时的上界、下界可以是赋了值的变量或表达式。若有Preserve关键字,表示当改变原有数组最末尾的大小时,使用此关键字可以保持数组中原来的数据。

4.控件数组

相同类型的控件组成的数组。
控件数组的建立:在设计时的窗体上,通过对某控件的复制和粘贴操作:在程序运行时通过Load方法实现。
控件数组元素:由控件的Index属性值表示数组的F标。

5.数组的操作

应掌握的基本操作有:数组初始化、数组输入、数组输出、求数组中的最大(最小)元素及下标、求和、平均值、排序和查找等。

5.3 常见错误和难点分析

1.Dim数组声明

有时用户为了程序的通用性,声明数组的上界用变量来表示,如下程序段:
       n=InputBox("输入数组的上界")
       Dim a(1 To n)As Integer
程序运行时将在Dim语句处显示"要求常数表达式"的出错信息。即Dim语句中声明的数组上,下界必须是常数,不能是变量。

解决程序通用的问题,一是将数组声明的很大,这样浪费一些存储空间;二是利用动态数组,将上例改变如下:

       Dima()As Integer
       n=InputBox ("输入数组的上界")
       ReDim a(1 To n)As Integer

2.数组下标越界

引用了不存在的数组元素,即下标比数组声明时的下标范围大或小。例如,要形成有如下30项的斐波那契数列:
1,1,2,3,5,8,13,21,34,…,317811,514229,832040
正确的程序段如下:
       Dim a(1 To 30) As Long, i%
若将For i=3To 30改为For i=1 To 30,程序运行时会显示"下标越界"的出错信息,因为开始循环时i=l,执行到循环体语句a(i)=a(i-2)+a(i-1),数组下标i-2、i-1均小于下界1。
同样若将上例:a(i)+a(i-2)+a(i-1)语句改为:a(i+2)=a(i)+a(i+1)
程序运行时也会显示"下标越界"的出错信息,这时是数组下标大于上界30。

3.数组维数错

数组声明时的维数与引用数组元素时的维数不一致。例如,下程序段为形成和显示3×5的矩阵:

       Dim a(3,5) As Long
              For i=1 To 3
                     For j=1 To 5
                            a(i)=i*j
                            Print a(i);"";
                     Next j
              Print
       Next i

程序运行到a(i)=i*j语句时出现"维数错误"的信息,因为在Dim声明时是二维数组,引用时的一个下标。

4.Aarry函数使用问题

Aarry函数可方便地对数组整体赋值,但此时只能声明Variant的变量或仅由括号括起的动态数组。赋值后的数组大小由赋值的个数决定。
例如,要将1,2,3,4,5,6,7这些值赋值给数组a,表2.5.1列出了三种错误及相应正确的赋值方法。
表2.5.1 Aarry函数表示方法

错误的Aarry函数赋值 改正的Aarry函数赋值

Dim a(1 To 8)a=Array(1,2,3,4,5,6,7,8) Dim a( )a=Array(1,2,3,4,5,6,7)
Dim a As Integera=Array(1,2,3,4,5,6,7)       Dim aa=Array(1,2,3,4,5,6,7)
Dim aa()=Array(1,2,3,4,5,6,7)      Dim aa=Array(1,2,3,4,5,6,7)

5.如何获得数组的上界、下界

Aarry函数可方便地对数组整体赋值,但在程序中如何获得数组的-上界、下界,以保证访问的数组元素在合法的范围内,可使用UBound和LBound函数来决定数组访问。

在上例中,若要打印a数组的各个值,可通过下面程序段实现:

For i=Lbound(A) To Ubound(A)
              Print a(i)
       Next l

6.给数组赋值

VB6.0提供了可对数组整体赋值的新功能,方便了数组对数组的赋值操作。但真正使用不那么方便,有不少限制。数组赋值形式如下:

数组名2=数组名1

我们就此形式作讨论:这里的数组名2,实际上在前面的数组声明时,只能声明为Varian的变量,赋值后的数组2的大小、维数、类型同数组名1;否则,若声明成动态或静态的数组,例如:

Dim数组名2()或Dim数组名2 (下标)

程序在运行到上述赋值语句时显示"不能给数组赋值"的出错信息。

所以,为了程序的安全、可靠,建议读者还是忍痛割爱,少用VB6.0的这一新功能,使用传统的循环结构来给数组赋值。基于此原因,我们也就在教程中不作展开。

第六章 过    程

6.1 知识要点

1.过程的概念

VB的程序是由一个个过程构成的,除了VB系统提供了大量使用的内部函数过程和事件过程外,VB系统还允许用户根据各自需要自定义过程。使用过程的好处:使程序简练、高效、便于程序的调试和维护。本节涉及的过程主要指的是用户自定义的子过程和函数过程。

2.两类过程定义与调用

(1)子过程

定义形式:Sub<子过程名>[(形参表)]

        …

       End Sub

特点:子过程名无值,无类型。

调用形式:Call<子过程名>[(实参表)]

       或:<子过程名>[(实参表)]

特点:是一句独立的语句。

(2)函数过程

形式:Function<函数过程名>([形参表])

       …

       <函数过程名>=<表达式>

       …

       End Sub

特点:函数过程名有值、有类型,在过程体内至少赋值一次。

调用形式:<函数过程名> ([实参表])

特点:不能独立存在,必须参加表达式的运算。

3.参数传递

(1)传值方式是将实参的具体值传递给形参。

传值方式是形参前加ByVal关键字,表示值传递。这种传递方式是一种单向的数据传递,即调用时只能由实参将值传递给形参;调用结束不能由形参将操作结果返回给实参。实参可以是常数或表达式。

(2)传地址

传地址方式(ByRet)是将实参在内存的地址传递给形参,也就是实参、形参共用内存内的"地址"。

这种传递方式是一种双向的数据传递,即调用时实参将值传递给形参:调用结束由形参将操作结果返回给实参。当实参要得到返回的结果时,实参只能是变量,不能是常数或表达式。

在过程中具体用传值还是传地址,主要考虑的因素是:若要从过程调用中通过形参返回结果,则要用传地址方式;否则应使用传值方式,减少过程间的相互关联,便于程序的调试。数组、记录类型变量、对象变量只能用地址传递方式。

在VB中,默认是传地址方式。

4.变量的作用域

全局变量:Public关键字开头的变量为全局变量,在整个工程中都有效。

窗体、模块级变量:在通用声明段用Dim或Private关键字声明的变量,在该窗体或模块内有效。

局部变量:在过程中声明的变量,在该过程调用时分配内存空间并初始化,过程调用结束,回收分配的空间。

使用规则见表2.6.1所示。

表2.6.1 变量的作用域

使用范围       局部变量       窗体/模块级变量   全局变量

                     窗体       标准模块

声时方式       Dim, tatic       Dim,Private          

声明位置       在过程中       窗体/模块的通用声明段      窗体/模块的通用声明段

能被本模块的其他过程存取       不能       能    能

能被其他模块存取       不能       不能       能,但在变量名前加窗体名       能

静态变量:局部变量声明前加Static关键字,在程序运行的过程中始终保值。

5.过程的递归调用

在调用一个子过程或函数过程中又调用自己,称为递归调用,这样的子过程或函数过程称为递归子过程或递归函数,简化称为递归过程。

构成递归过程的条件:递归结束条件及结束时的值:能用递归形式表示,并且递归向终止条件发展。

6.常用算法

对数值计算方面要求掌握:求最大值(最小值)及下标位置、求和、平均值、最大公约数、最小公倍数、素数、数制转换、高次方程求根(迭代法、二分法)、定积分(矩形法、梯形法、辛卜生法、蒙特卡洛法)。

非数值计算:常用字符串处理函数、排序(选择法、冒泡法、插入法、合并排序)、查找(顺序、二分法)。

6.3 常见错误和难点分析

1.程序设计算法问题

该章程序编写难度较大,主要是算法的构思有困难,这也是程序设计中最难学习的阶段。经验告诉每一位程序设计的初学者,没有捷径可走,多看、多练、知难而进。上机前一定要先编写好程序,仔细分析、检查,才能提高上机调试的效率。每当一个程序通过艰苦的努力调试通过时,那苦尽甘来的喜悦令你一言难尽。

2.确定自定义的过程是子过程还是函数过程

实际上过程是一个具有某种功能的独立程序单位,供多次调用。子过程与函数过程的区别是前者子过程名无值:后者函数过程名有值。若过程有一个返回值,则习惯使用函数过程;若过程无返回值,则使用子过程:若过程返回多个值,一般使用子过程,通过实参与形参的结合带回结果,当然也可通过函数过程名带回一个,其余结果通过实参与形参的结合带回。

3。过程中形参的个数和传递方式的确定

对初学者,在定义过程时不能确定形参的个数和传递方式。

过程中参数的作用是实现过程与调用者的数据通信。一方面,调用者为子过程或函数过程提供初值,这是通过实参传递给形参实现的:另一方面,子过程或函数过程将结果传递给调用者,这是通过地址传递方式实现的。因此,决定形参的个数就是由上述两方面决定的。对初学者,往往喜欢把过程体中用到的所有变量命作为形参,这样就增加了调用者的负担和出错概率:也有的初学者全部省略了形参,则无法实现数据的传递,既不能从调用者得到初值,也无法将计算结果传递给调用者。

VB中形参与实参的结合有传值和传地址两种方式。区别如下:

(1)在定义形式上前者在形参前加即Val关键字。

(2)在作用上值传递只能从外界向过程传入初值,但不能将结果传出:而地址传递既可传入又可传出。

(3)如果实参是数组、自定义类型、对象变量等,形参只能是地址传递。

4.实参与形参类型对应问题

在地址传递方式时,调用过程实参与形参类型要一致。例如:

函数过程定义如下:

       Public Function f!(x!)
              f=x+x
       End Function
主调程序如下:
       Privme Sub Commandl_Click()
              Dim y%
              y=3
              Print f(y)
       End Sub

上例形参x是单精度型、实参y是整型,程序运行时会显示"ByRef参数类型不符"的编译出错信息。

在值传递时,若是数值型,则实参按形参的类型将值传递给形参。例如:

函数过程定义如下:

       Public Function f!(ByVal x%)
              f=x+x
       End Function
主调程序如下:
       Priva~SubCommandI_Click()
              Dim y!
              Y=3.4
              Print f(y)
       End Sub

程序运行后显示的结果是6。

5.变量的作用域问题

局部变量,在对该过程调用,分配该变量的存储空间,当过程调用结束,回收分配的存储空间,也就是调用一次,初始化一次,变量不保值:窗体级变量,当窗体装入,分配该变量的存储空间,直到该窗体从内存卸掉,才回收该变量分配的存储空间。

例如,要通过文本框输入若于个值,每输入一个按Eenter键,直到输入的值为9999,箱入结束,求输入的数的平均值。

       Private Sub Textl_Key Press(Key Ascii As Integer)
              Dim sum!,n%
              If KeyAscii=13 Then
                     If Val(Text1)=9999 Then
                            sum=sum/n
                            Print sum
                     Else
                            Sum=sum+Text1
                                   n=n+1
                            Text1=""
                     End If
              End If
       End Sub

该过程没有语法错,运行程序可输入若干个数,但当输入9999时,程序显示"溢出"的错误。原因sum和n是局部变量,每按一个键,局部变量初始化为o,所以会有上述错误产生。

改进方法:将要保值的局部变量声明为Static静态变量或声明为窗体级变量。也可将要保值的变量在通用声明段进行声明为窗体级变量。

6.递归调用出现"栈溢出"

如下求阶乘的递归函数过程:

PublicFunctionfac(nAsInteger)Asinteger
       If n=1 Then
                     fac=1
              Else
                     fac=n*fac(n-1)
              End If
       End Function
       Private Sub Commandl_Click()     '调用递归函数,显示出fac(5)=120
                     Print "fac(5)":fac(5)
       End Sub

当主调程序调用时,n的值为5时,显示120结果:当n的值为-5时,显示"溢出堆栈空间"的出错信息。

实际上每递归调用一次,系统将当前状态信息(形参、局部变量、调用结束时的返回地址)压栈,直到到达递归结束条件。上例当n=5时,每递归调用一次,参数n-l,直到n=l递归调用结束,然后不断从栈中弹出当前参数,直到栈空。而当n'-5时,参数n-1为-6、压栈,再递归调用、n-1永远到不了n=l的终止条件,直到栈满,产生栈益出的出错信息。

所以设计递归过程时,一定要考虑过程中有终止的条件和终止时的值或某种操作,而且每递归调用一次,其中的参数要向终止方向收敛,否则就会产生栈溢出。

第七章 常用控件(一)

7.1 知识要点

1.单选按钮和复选框

单选按钮和复选框的常用属性是Value,它的主要作用是用宋检查单选按钮或复选框是否被选定。

单选按钮和复选框能够响应Click事件,但通常不需要编写事件过程。

2.框架

框架的主要作用是将其他控件组合在一起,对一个窗体中的各种功能进行分类,以便于用户识别。当用框架将同一个字体上的单选按钮分组后,每一组单选按钮都是独立的,也就是说,在一组单选按钮中进行操作不会影响其他组单选按钮的选择。

框架的重要属性是Caption。

一般不需要编写事件过程。

3.列表框

列表框的主要属性有:Text、List、Listlndex、ListCount和So~ed。当MultiSelect属性为 1或2时允许多项选择,此时往往需要Selected属性判定哪些项目被选定。

列表框的常用方法是:Addltem、Removeltem和Clear。

在通常情况下,列表框不需要编写事件过程,其中的项目也不需要更改。

4.组合框

组合框是组合了文本框和列表框的特性而形成的一种控件。组合框的类型由其Style属性决定。下拉式组合框(Style为0)和简单组合框(Style为1)允许用户在文本框中输入不属于列表内的选项。

5.滚动条

滚动条特有的常用属性有:Max、Min、Value、SmallChange和LargeChange。

滚动条的重要事件是:Change和Scroll。

6.时钟控件

时钟控件特有的常用属性是Interval,它的值以0. 001秒为单位。

时钟控件的Enabled属性与其他控件是不同的,当时钟控件的Enabled属性为True时, Timer事件以Interval属性值的毫秒间隔发生。如果将时钟控件的Enabled属性设为False或 Interval属性设为0时计时器停止运行,则Timer事件不会发生。

Timer是时钟控件的唯一事件。

可以利用时钟连续播放图片达到动画效果。

7.3 常见错误和难点分析

1.遗漏对象名称

在VB程序设计时,初学者常犯的一个错误是遗漏对象名称,特别是在使用列表框时。例如,如果要引用列表框(List1)中当前选定的项目,Listl.list(Listlndex)是错误的。即使当前焦点在Listl上,VB也不是认为Listlndex是List l的属性,而是一个变量。所以正确的引用方式是:Listl. 1ist(Listl.Listlndex)。

2.列表框的Columns属性

列表框的Columns属性决定列表框是水平还是垂直滚动、以及如何显示列中的项目。如果水平滚动,则Columns属性决定显示多少列,如表2.7.2所示。图2.7.1是一个水平滚动两列显示的列表框。
在程序运行期间,该属性是只读的,也就是说,不能在运行时,将多列列表框变为单列列表框或将单列列表框变为多列列表框。
表2.7.2 列表框的Columns属性
列数       属    性
0(默认值)1到n       项目安排在一列中,且列表框竖直滚动项目安排在多个列中,先填第一列,再填第二列……列表框水平滚动并显示指定数目的列

3.域级验证

域级验证是指输入到某独立域的数据的验证,在域级验证的过程中一般不考虑窗体-般其他域的内容。进行域级验证的合适时间是:
(1)当往某域中输入某个键时,此时涉及键盘事件(KeyDown、KeyUp和KeyPress)。有关这方面的内容请参阅教程第4.7节。
(2)当用户企图离开某域时,此时涉及CansesValidate属性和Validate事件。
(3)当某域的内容发生变化时,此时涉及Change事件。

CausesValidation属性和Validate事件通常是协同工作的。

CausesValidate属性决定Validate事件是否发生。如果控件的CausesValidate属性为False,该控件的Validate事件永远不会发生。如果控件的CausesValidate属性为Tree,当焦点企图移到(还没有离开,也可以说离开之前)另一个CausesValidate属性为True的控件时,原控件的Validate事件发生:当焦点企图移到另一个CausesValidate属性为False的控件时,原控件的Validate事件暂时不发生,什么时候发生?直到焦点移到一个CausesValidate属性为True的控件上时才发生。

例如,假定有如图2.7.2所示的程序。当焦点企图从Textl移到Text2时,Textl的Validate事件发生:同样当焦点企图从Text2移到Textl时,Text2的Validate事件发生。当焦点企图从Textl移到Text3时,TextI的Validate事件暂时没有发生,因为Text3的CausesValidate为False,然后如果焦点企图继续移动到Text2时,Textl的Validate事件才发生。

图2.7.2 CausesValidate属性和Validate事件

CausesValidate属性和Validate事件的这一特性常常应用在如图2.7.3所示的程序中。当在文本框中输入了无效数据时而又不知道如何输入有效数据时,用户往往选择Help命令寻求帮助或选择Cancel命令结束数据输入,此时不希望执行验证程序。因为如果执行验证程序且发现了无效数据,则无法选择Help或Cancel了,用户就这样被套住了。现在只要将文本框的CausesValidate属性设为True,命令按钮的CausesValidate属性为False,验证程序放在 Validate过程中,问题就解决了。在默认情况下,所有控件的CausesValidation属性都为Tree。

图2.7.3 命令按钮的CausesValidate属性和Validate事件

并不是所有的控件都有Validate事件。只有那些能用于输入数据的控件(如文本框、复选框、滚动条等)才有这个事件。Validate事件过程如下:
       Privme Sub object_Validate(Cancel As Boolean)
              …
       EndSub
其中,当参数Cancel被设为Tree后,焦点将不会离开对象。
如果要将实验七第1题改用Validate事件和CausesValidation属性实现数据验证,则应有如下的程序。
       Sub txtMath_Validate(Cancel As Boolean)
              If Val(txtMath.Text)<0 Or Val(txtMath.Text)>100 Then
                     Cancel=True
              End If
       End Sub