《Delphi程序设计基础.ppt》由会员分享,可在线阅读,更多相关《Delphi程序设计基础.ppt(79页珍藏版)》请在三一办公上搜索。
1、第3章 Object Pascal语言基础,3.1 标识符与保留字3.2 数据类型3.3 常量与变量3.4 运算符和表达式3.5 常用内部函数3.6 程序语句,3.1 标识符与保留字、指令字,3.1.1 标识符Object Pascal语言使用的是ASCII码字符集,包括字母AZ、az、数字09和其他的一些标准字符。下面的单个字符可作为特殊符号:#$另外,有些字符对也作为单个的特殊符号,具体有:(*(.*).)./:=其中,左中括号“”等价于“(.”,右中括号“”等价于“.)”,左大括号“”等价于“(*”,右大括号“”等价于“*)”。在Object Pascal语言中,标识符(Identifi
2、ers)用来标志常量、变量、类型、属性、对象、过程、函数、程序、单元、库和组件库等。标识符可以由任意长的一个不带空格的字符串组成,但是只有前面的255个字符有效。标识符的第一个字符必须是字母或下划线,其余字符可以是字母、数字或下划线。一般标识符可以由一个或多个具有适当意义的英文单词组成。Pascal语言对于字母的大小写不敏感。当然,字符串中的大小写字母是需要分清的。,3.1.2 保留字和指令字,保留字,3.1.2 保留字和指令字,指令字,3.2 数据类型,描述客观事物的数、字符以及所有能输入到计算机中并被计算机程序加工处理的符号的集合称为数据。数据的一个重要特征就是其所属的数据类型,数据的类型
3、不仅确定了该类数据的表示形式和取值范围,而且还确定了数据所能够参加的各种运算。标准数据类型属于Object Pascal内部约定的数据类型,无需定义就可以直接使用。,3.2 数据类型,高级数据类型体现了特殊的数据结构,在使用之前必须由用户自己定义。,3.2 数据类型,整型、字符型、布尔型、枚举型和子界型5种被称为顺序类型,其取值是一个有序的集合,每一个可能的取值都与顺序(整数值)有关,即其取值与某一整数相对应。(有序数据类型常用函数)本章主要介绍Object Pascal的标准数据类型。3.2.1 数值型数据3.2.2 字符数据3.2.3 布尔型数据,3.2.1 数值型数据,1.整型整型是存储
4、整数数据的类型,Object Pascal包括9种形式的整型数据。,3.2.1 数值型数据,2.实型实型是存储实数数据的类型,Object Pascal包括5种形式的实型数据。,3.2.2 字符数据,1.字符型字符型是存储单个字符数据的类型,Object Pascal包括3种形式的字符型数据。2.字符串型字符串型是存储字符串数据的类型,Object Pascal包括4种形式的字符串型数据。(PChar,PAnsiChar,PWideChar),3.2.3 布尔型数据,布尔型数据用于进行逻辑运算,Object Pascal包括4种形式的布尔型数据。后3种类型是为了兼容其他语言而设置的,编程时应尽
5、量使用Boolean类型。布尔运算 BoolToStr(True),3.3 常量与变量,常量和变量是学习各种编程语言进行程序设计的基础概念,分别代表了在程序运行过程中两种不同状态的量。常量是指在程序运行过程中其值始终不变的量;与之相反,变量则是程序运行过程中其值可以改变的量。3.3.1 常量在Pascal中用const关键字来声明常量,不需要在对常量赋值时声明常量的类型,编译器能根据常量的值自动判断常量的类型并分配内存。(可靠修改、容易修改、可读性强)3.3.2 变量当在Object Pascal中声明一个变量时,变量名在类型的前面,中间用冒号隔开,变量初始化通常要跟变量声明分开。Delphi
6、能在var块中对全局变量赋初值。(声明方法、命名格式、作用范围),3.4 运算符和表达式,运算符是在代码中对各种数据类型进行运算的符号。表达式由运算对象和运算符两部分组成。3.4.1 运算符Object Pascal语言中的运算符(Operators)有:、not、*、/、div、mod、and、shl、shr、as、+、-、or、xor、=、=、in和is等。按照操作数数目的多少来分,运算符分为下面两类:单目运算符(Unary Operator)和双目运算符(Binary Operator)。上面的、not和为单目运算符,其余的为双目运算符。其中和也可以作为单目运算符来使用。单目运算符一般放
7、在操作对象的前面,只有可以放在操作对象的后面。双目运算符都放在两个操作数之间。有些运算符是根据给定的操作数的数据类型做相应处理的。例如,运算符not对于整型的操作数说,做的是按位取反;对于逻辑类型的操作数来说,它完成的则是逻辑取反。除了运算符、is和in外,其余操作符都可以对Variant类型的数据进行操作。,3.4.1 运算符,在复杂的表达式中,各种运算符的优先级分别如下:第一级(最高):、not第二级:*、/、div、mod、and、shl、shr、as第三级:+、-、or、xor第四级(最低):=、=、in、is尽管各种运算符的优先级比较明确,但是在具体编程的时候,并不需要记住所有运算符
8、的优先级顺序。常见的一些优先级顺序比较好记,如乘、除运算符的优先级比加、减运算符的优先级高。在优先级顺序不太明显的地方,可以多加一些小括号以明确表达式的结合次序。,3.4.2 表达式,一个表达式由运算对象和运算符两部分组成。运算符可以分为算术运算符、逻辑运算符、串运算符、字符指针运算符、集合运算符、关系运算符以及运算符。运算符的优先顺序见表。,3.5 常用内部函数,为了尽可能地减少开发应用程序的难度和工作量,Delphi提供了一个内容十分丰富的程序库Run-Time Library(RTL),其中包括了大量的基本函数、过程、常量和变量定义。RTL包含的函数、过程、常量等都是在System单元中
9、定义的,而System单元会自动地被其他程序单元引用,所以用户编写的应用程序可以随时调用RTL中可用的函数,而不用在程序的uses语句中引用该单元。3.5.1 数学运算函数(round函数,和random(range:integer)函数3.5.2 字符处理函数 pos,length,sizeof,copy,appendstr,concat3.5.3 时间和日期函数 Encodedate,Decodedate,FormatDateTime3.5.4 数据类型转换函数 InttoStr,StrtoInt,FloatToStr,DatetoStr3.5.5 格式输出函数 format(数1:%,数
10、2:%d,1,88)格式控制符的形式:%下标:-场宽.精度类型说明符 例1:Format(%*.*f,8,2,123.456);例2:TVarRec args3=8,2,123.456;Format(%*.*f,args,2);,3.6 程序语句,语句是执行具体操作的指令。语句由Object Pascal的保留字、属性、函数、运算符以及能够生成Delphi编辑器可识别指令的符号组成。建立程序语句时必须遵从的构造规则称为语法。编写正确程序语句的前提,就是学习语言元素的语法,并在程序中使用这些元素正确地处理数据。语句的书写规则 赋值语句 过程语句 注释语句 声明语句 GOTO语句,3.7 基本程序
11、设计,3.7.1 顺序结构顺序结构是程序设计中最简单、最常用的基本结构。在该结构中,各操作块(简称块,对应于程序中的“程序段”)按照出现的先后顺序依次执行。它是任何程序的主体基本结构,即使在选择结构或循环结构中,也常以顺序结构作为其子结构。在顺序结构中,通常使用基本控件完成输入及输出操作,使用赋值语句等简单的操作语句组成顺序结构即可实现顺序结构程序的编写。,3.7.2 选择结构,选择结构是计算机科学用来描述自然界和社会生活中分支现象的重要手段。其特点是:根据所给定的条件成立(真)与否(假),而决定从各实际可能的不同分支中执行某一分支的相应操作,并且任何情况下总有:“无论分支多寡,必择其一;纵然
12、分支众多,仅选其一”。在Delphi中,实现选择结构的是IF语句和Case语句。这两种语句又称为条件语句,条件语句的功能就是根据表达式的值有选择地执行一组语句。IF语句 Case语句,IF 语句,If 语句又称为条件语句,是最常用的单条件选择结构。If语句的语法格式为:If Then Else;可以是关系表达式或布尔表达式。如果的值为真,则执行,否则执行。因为IfThenElse语句是一个完整的语句,因此在Else保留字之前没有分号,如果加入分号将产生编译错误。可以是简单语句,也可以是复合语句。If 语句的流程图如图所示。其中的a1或a2可以是空语句。当然,如果a1、a2操作同时为空语句的话,
13、就失去了选择的意义。为了养成良好的程序设计风格和习惯,如果必须设立空分支时,应该把它设在选择条件为假的相应分支(即a2)中。If 语句分为简单条件语句和复合条件语句两种。1.简单条件语句:简单条件语句的语句中不包含其他的条件语句。2.复合条件语句:如在 If 语句格式中的语句1或语句2本身又是一个 If 语句,则称为If 语句的嵌套。嵌套的If语句又被称为复合条件语句。If else if else语句,Case 语句,使用IF 语句可以方便地实现双分支选择结构,但是,对于多分支选择的情况,若仍然使用IF 语句,就必须用多层嵌套,非常繁琐。为此,Delphi提供了Case 语句专门来实现多分支
14、选择结构。Case 语句可以根据“选择器表达式”的值,来决定执行相应的语句。Case 语句的语法格式为:Case of:;.:;Else;End;的值必须是顺序类型(如整型、字符型、布尔型、子界型等)。中的值应该是可能具有的值,各常量之间用逗号分隔。所有常量表中的值必须互不相同。可以是简单语句,也可以是复合语句。Case 语句首先计算的值,然后判断该值是否等于某个常量,若相等则执行该常量后面的语句,执行完该语句后,转去执行End后面的语句。若与所有情况常量表中所列的常量都不相等,则执行Else后面的语句列。,Case 语句,Case语句的流程如图所示。,3.7.3 循环结构,在程序设计中,从某
15、处开始有规律地反复执行某一程序块的现象称为“循环”,完成这一功能的程序结构称为“循环结构”,而其中重复执行的程序块称为“循环体”。使用循环可以避免不必要的重复操作,简化程序,节约内存,从而提高效率。Object Pascal提供的循环结构语句有3种,它们分别是:While语句、Repeat语句以及For语句。无论何种类型的循环结构,其特点都是:循环体执行与否及其执行次数多少都必须视其循环类型与条件而定,且必须确保循环体的重复执行能在适当的时候得以终止。While语句Repeat语句 For语句For in Do 语句循环的嵌套 Break过程Continue过程,While语句,While语句
16、属于前测型循环结构。首先判断条件,根据条件决定是否执行循环,执行循环的最少次数为0。其流程图如图所示。While语句的语法格式为:While Do;是一个具有Boolean值的条件表达式,为循环的条件。可以是简单语句、复合语句和其他结构语句。While循环的执行过程:首先计算的值,如果为真(True),则执行Do后面的循环体,执行完后,再开始一个新的循环;如果为假(False),则终止循环,执行后面的语句。可以在中的任何位置放置Break语句来强制终止While循环随时跳出While循环。Break语句通常用在If语句中。可以在循环体中的任何位置放置Continue语句,在整个循环体没有执行完
17、就重新判断,以决定是否开始新的循环。Continue语句通常用于If语句之后。,Repeat语句,Repeat语句属于后测型循环结构。首先执行循环体,然后判断条件,根据条件决定是否继续执行循环,因此执行循环的最少次数为1。其流程图如图所示。Repeat语句的语法格式为:Repeat Until;是一个具有Boolean值的条件表达式,为循环的条件。可以是一条语句,也可以是多条语句。多条语句无需用BeginEnd括起来,而由保留字Repeat与Until将其括起。Repeat循环的执行过程:首先执行,然后计算的值,如果为假(False),则开始一个新的循环;如果为真(True),则终止循环,执行
18、后面的语句。可以在循环体中的任何位置放置Break语句来强制终止Repeat循环随时跳出Repeat循环。Break语句通常用于If语句之后。可以在循环体中的任何位置放置Continue语句,在整个循环体没有执行完就重新判断,以决定是否开始新的循环。Continue语句通常用于If语句之后。,For语句,在不知道需要执行多少次循环时,应该用While或Repeat循环。但是,若知道要执行多少次循环时,则最好使用For循环结构。与前两种循环不同,For循环使用一个循环变量,每重复一次循环之后,循环变量的值就会自动增加或者减少。For循环的流程图如图所示。For语句的语法格式为:For=To|Do
19、wnTo Do;为必要参数,用作循环计数器,只能是顺序类型。和表示的初值和终值,可以是表达式,但应与的类型相同。若为表达式,则在进入循环之前已被计算确定,在循环体中改变初值或终值表达式中变量的值,并不影响循环的次数。To表示计数器递增,DownTo表示计数器递减。可以是简单语句、复合语句和其他结构语句。For循环的执行过程:首先判断循环变量的值是否“超过”终值(对于递增循环为大于,对于递减循环为小于),若已超过则跳出循环执行后面的语句;若未超过则执行Do后面的,然后循环变量自动“增量”(递增或递减)并开始一个新的循环。可以在中的任何位置放置Break语句来强制终止For循环随时跳出For循环。
20、Break语句通常用于If语句之后。可以在循环体中的任何位置放置Continue语句,在整个循环体没有执行完就重新开始新的循环。Continue语句通常用于If语句之后。在循环体内,不允许以任何语句修改循环变量,退出for循环后,循环变量的值就自动变得不确定的,不能再使用,For in do语句,为win32开发提供的新语法结构,它可以使用在数组、字符串和集合3种类型中,以及Collection类中。例子:page77,循环的嵌套 在前面循环语句的循环体中仅包含了简单语句,这种类型的循环结构称为单重循环。如果在循环体中又包含了另一个循环结构,则称为多重循环。这种情况又称为循环的嵌套。前面介绍的
21、三种类型的循环可以互相嵌套。在循环体中嵌套的循环称为内循环(相对的),外部的循环称为外循环。多重循环嵌套的层数几乎可以是任意的,根据循环结构嵌套的层数可以分为二重循环、三重循环等。Break过程 在while、for或repeat循环中调用Break,使得程序的执行流程立即跳到循环的结尾,在循环中当某种条件满足时需要立即跳出循环,这时调用Break。Pascal中的Break类似于C语言中的break和Visual Basic中的Exit语句。Continue过程 如果想跳过循环中部分代码重新开始下一次循环,就调用Continue过程。,3.8 过程与函数,过程与函数是程序设计语言中的重要概念
22、,也是实现结构化程序设计思想的重要手段。结构化程序设计思想的要点之一就是对一个复杂的问题采用“分而治之”的策略模块化。把一个较大的程序划分为若干个模块,每个模块只完成一个或若干个功能,每个功能可以用一个程序段来实现,这个程序段称为“子程序”。Delphi的子程序分为过程(Procedure)和函数(Function)两种形式。过程与函数是实现一定功能的语句块,可以在程序的其他地方被调用,也可以进行递归调用。过程与函数的区别在于:过程没有返回值,而函数有返回值。过程函数参数子程序的嵌套与递归变量的作用域,过程,过程的定义包括过程原型、过程体的定义。过程定义的语法格式如下:Procedure();
23、directives;begin;end;其中为一个有效的标识符。需要指明参数的个数及其数据类型。directives是一些关于函数的指令字,可以一次设置多个,使用分号隔开。局部声明部分用来声明该过程中所使用的类型、常量、变量,这些类型、常量、变量的作用范围只限于该过程内部,与过程体外的同名对象无关。在局部声明部分还可以包含另一个过程或函数声明(称为内嵌的过程或函数)。在begin与end之间是在函数调用时实现特定功能的一系列语句。,函数,函数的定义与过程非常类似,只是使用的保留字不同,而且多了一个返回值类型。函数的定义的语法格式如下:function():;directives;begin;
24、end;可以将函数要返回的数值赋值给Result。如果函数体中存在着一些由于判断而产生的分支语句时,要在每一个分支中设置返回值。通常要根据函数的返回值来确定下一步的操作。也能在函数体内把一个值赋给函数名来返回一个值,这是Pascal的标准语法,是从Borland Pascal的老版本继承下来的。如果选择这种方法,一定要注意它和程序代码中把函数放在赋值运算符的左边是不同的!如果在函数体内把它放在赋值运算符的左边表示你要返回函数值,如果程序中把它放在左边表示要对它进行递归调用。,内联函数,内联函数就是在程序编译时,编译器将程序中出现的内联函数的调用表达式用函数体来代替,从而使这个函数的汇编代码嵌入
25、到调用过程中以大幅度地提高效率。使用inline保留字就可以将一个函数指定为内联函数。例:function myFun(a,b:integer):Integer;inline begin end;注意要点:1.在内联函数内部不允许使用循环语句和开关语句,否则视为普通函数;2.内联函数不能是递归函数;3.内联函数的代码应尽量少,一般不大于5行。,参数,一般将函数定义时参数列表中的参数称为形参,将函数调用时参数列表中的参数称为实参。在函数原型中,多个参数之间用分号隔开,同一类型的参数可以放在一起,以逗号隔开。在函数调用的时候,在函数原型中,多个参数之间用逗号隔开。一般来说,形参列表和实参列表完全匹
26、配是指参数的个数一样,而且顺序排列的数据类型也完全一致。对于普通的函数,如果编译器发现实参的数据类型与形参的数据类型不匹配,会将实参的数据类型进行一次或多次的“提升”,比如:将Integer类型转换为Double类型。可以为过程和函数的参数指定默认数值。具体方法是在参数定义后面紧接着一个等号“=”,然后是一个常量。指定默认数值的参数要放在参数列表的后部,将没有指定默认数值的参数放在参数列表的前面部分。在函数调用的时候,可以为设置了默认值的参数指定一个新值,在函数体中,各语句使用的是指定的新值;如果没有指定新值,则使用默认值。同样,如果存在多个设置了默认值的参数,只有前面的参数指定了新值,后面的
27、参数才可以指定新值。,参数,在调用过程或函数的时候,如果参数列表中具有多个参数,那么参数传递给过程或函数的顺序会对结果产生一定的影响。对于不同的语言,参数传递的顺序是不同的:Pascal语言是按照从左向右的顺序进行传递的,而C语言是按照从右向左的顺序来传递的。为了确定传递的顺序,可以在过程或函数定义的时候,在directives部分利用指令字指定传递的顺序。表中列举了directives部分可使用的关于函数调用约定的指令字。,参数类型,数值参数变量和结构被完整地复制到堆中,调用的函数接收到的是参数的一个副本。变量参数(var)变量参数在传递时传递的不是参数的副本,而是实参的引用。此时实参不能是
28、表达式。常量参数 Const不能对常量参数修改,也不允许把常量参数再作为实参传递给一个过程或函数。外部参数 out同变量参数一样,传递的也是引用,但初始值被忽略。无类型参数数组参数静态数组参数;开放数组参数,可变开放数组参数,子程序的嵌套与递归,在一个子程序(过程或函数)中包含另外一个子程序(过程或函数)的调用,称为子程序的嵌套。子程序的递归调用是指一个过程直接或间接调用自己本身,子程序直接调用自身称为直接递归,子程序间接调用自己称为间接递归。在递归调用中,一个过程执行的某一步要用到它自身的上一步(或上几步)的结果。递归调用在处理阶乘运算、级数运算、幂指数运算等方面特别有效。递归在算法描述中有
29、着重要的地位,很多看似非常复杂的问题,但使用递归后可以很轻松地解决。在间接递归调用中,子程序必须超前引用,即在子程序的首部后面加上保留字forward。利用递归算法能简单有效地解决一些特殊问题,但是由于递归调用过程比较繁琐,所以执行效率很低,在选择递归时要慎重。,第4章 高级数据类型,第3章介绍了Object Pascal语言的5种标准数据类型:整型、实型、字符型、字符串型以及布尔型,这些数据类型无需声明(定义)即可在程序中直接使用。为了满足实际问题的需要,Object Pascal语言还允许用户使用自定义的数据类型。本章介绍的枚举、子界与集合类型就是用户自定义的数据类型,属于Object P
30、ascal语言的高级数据类型。4.1 类型定义语句4.2 枚举类型4.3 子界类型4.4 集合类型4.5 数组4.6 记录类型4.7 指针类型,4.1 类型定义语句,Object Pascal语言的高级数据类型在使用之前必须首先使用类型定义语句进行定义。类型定义语句的语法格式为:type=;=;=;其中保留字type表示类型定义段的开始。是用户为自定义类型取的名称,是用户定义的数据类型名,既可以是Object Pascal语言的标准数据类型,也可以是Object Pascal语言的高级数据类型。,4.2 枚举类型,在处理诸如物体的颜色、人的职业、教师的职称等非数值数据时,可以用数值或字符串来表
31、示,比如用1表示红色,2表示黄色;或用“red”表示红色,“yellow”表示黄色。但这样的表示都存在一些缺点:使用数值表示很不直观,特别当表示的种类较多时容易引起混乱和错误,使用字符串则需要占用较多的内存。仔细分析这些数据,可知这些数据的个数总是有限的,而且可以一一列举。为此,Object Pascal提供的用户自定义数据类型枚举类型,可以很方便地处理这类数据。定义枚举类型的语法格式如下:Type=(,);是用户定义的枚举类型名称。表示该类型数据中的元素,圆括号中列出了该类型数据的所有取值,这些取值又称为枚举常量。每个枚举常量必须是标识符,不能是其他任何数据类型。枚举常量不允许在同一枚举类型
32、定义中重复出现,也不允许同时在不同的枚举类型定义中出现。不能直接用枚举类型中的元素参与运算,4.3 子界类型,在Object Pascal中,具有确定的数据类型(称为基类型),且其取值范围确定的数据可以定义为“子界类型”。其中的基类型,必须为顺序类型。子界类型是Object Pascal允许用户定义的一个结构数据类型。如果用户预先知道一个变量的范围,就可以通过定义子界类型和子界类型变量来实现由系统自动检查变量是否超出了允许的范围。定义子界类型的语法格式如下:Type=.;是用户定义的子界类型名称。表示子界类型的下界,表示子界类型的上界。子界的上、下界必须属于相同的顺序类型,即它们应同时为整型、
33、布尔型、字符型或同一个枚举类型。子界的上、下界所属的数据类型即子界的基类型。若子界的基类型为标准数据类型(整型、布尔型、字符型),则子界的上、下界可以直接使用该类型常量,若子界的基类型为枚举类型,则必须先定义基类型(枚举类型),再定义子界类型。子界的上界必须不小于下界。具有基类型数据的所有运算特性,但结果必须在定义的上下界之内,常量类型相同的不同子界类型可以混合运算,可以赋值。,4.4 集合类型,集合是指具有相同性质且可以相互区分的对象的全体。构成集合的各个对象,称为集合的元素。如小于100的正整数全体、某单位中年龄大于30的男人全体、大写的英文字母全体等均构成集合。在理解集合的概念时,要注意
34、以下几点:集合中的元素是互异的,即相同的元素视为是同一个元素。集合中的元素是无序的,即1,2,3,4与2,3,1,4是同一个集合。集合中的元素个数可以是有限的,也可以是无限的。元素与集合的关系是“属于”或“不属于”,二者必取其一且仅取其一。为了表示集合,在Pascal中引入了集合类型。集合类型属于构造类型,是由其他的数据类型按照一定的规则构造而成。集合的元素是某种简单数据类型的值,这种数据类型称为集合的“基类型”。在Delphi中,基类型只能是顺序类型,不能是实型或其他构造类型。注意Delphi限制了集合数目,所以整型数据不能作为集合类型的基类型。集合类型常用来维护一系列互不相同的处理对象或用
35、来表示不同的状态,如在Delphi中,许多对象的属性被定义为集合类型。在使用集合类型之前,必须进行类型定义与变量声明。,4.4 集合类型,定义集合类型的语法格式如下:type=set of;是用户定义的集合类型名称。表示集合中各元素的类型,可以是字符型、布尔型、枚举型和子界型等顺序类型,不能是整型、实型和其他的构造类型。若为枚举或子界类型,则必须先定义该基类型,再定义集合类型。例如,以下定义是正确的:type numbers=set of 1.100;/直接给出子界 Uchar=set of A.Z;/直接给出子界 Colors=(Red,Blue,Green,Yellow,White,Bla
36、ck);/定义一个枚举类型 color=set of Colors;/基类型为枚举类型 Lchars=a.z;/定义一个子界类型 Lchar=set of Lchars;/基类型为子界类型 在Delphi中,集合的元素个数最多不能超过256个,因此,基类型的序数值必须在0255之间。由于整型数据的取值范围是-3276832767,所以基类型不能是整型。但可以是整型的子界类型,且该子界类型只能在0255范围内。,4.5 数组,数组是一些具有相同类型的元素按一定顺序组成的序列。数组中的每一个数据元素都可以通过数组名和唯一的索引号来存取,它们被顺序地安排在内存中的一段连续的存储区中。在Object
37、Pascal中数组可分为静态数组和动态数组两种类型。4.5.1 静态数组4.5.2 动态数组,4.5.1 静态数组,静态数组在程序初始化时必须分配内存单元,明确其固定的大小和元素的数据类型。1.一维静态数组数组通常可分为一维、二维和多维数组,这里首先从最简单的一维数组来说明静态数组的声明及其使用方法。在Object Pascal中,定义一个一维数组类型,其声明的语法格式为:Type array of;例如,定义这么一个数组类型:Type MyArrayarray1.100 of Real;表示定义一个下标类型是整数,共有100个元素,元素下标从1到100,每个元素类型是Real,类型标识符是M
38、yArray的数组类型。数组类型标识符可以是任何合法的标识符,Object Pascal允许下标的类型为整数类型、字符类型、布尔类型、子界类型、枚举类型等,而元素的类型可以是任意的数据类型,并且在同一数组中,所有元素的数据类型必须相同。对于用户定义的数据类型作为下标类型,在使用之前必须声明。,4.5.1 静态数组,2.二维静态数组上面讲的是一维数组,所谓一维数组,从形式上讲,就是只有一个下标的数组,如x1.2,y3.100。而二维数组是指一个一维数组中的元素类型本身又是一个一维数组,其一般定义的语法格式为:Type=Array of Array of;也可以把上述语法格式简写成下面的格式:Ty
39、pe=Array,of;这两种声明形式对编译器来说是完全一样的,第一种格式可以理解为把一行看成一个元素,而每行又是一个一维数组的递归定义。第二种格式较为容易理解,因此最好采用第二种声明格式。,4.5.1 静态数组,3.多维静态数组定义多维静态数组的一般语法格式为:Typearray,of;一般情况,用户常用的数组不超过三维数组,用到三维以上的数组是很少的,Object Pascal允许用户定义任意维数的数组。4.使用静态数组的注意事项在程序设计中,要想使用静态数组,必须首先声明,然后利用声明的类型定义程序所需的变量,这样就可真正申请一段内存地址,以便利用数组来实现数据的存取和其他操作。因此,使
40、用数组应该注意数组类型变量的初始化问题。经过初始化以后的数组变量,编译器会给数组分配一段确定的内存区,但内存区中的数据是随机的、不确定的。只有给数组中每个元素赋以确定的值,数组元素才能参与具体运算。,4.5.2 动态数组,前面介绍的静态数组通过下标类型、维数(下标个数)明确了数组有固定的大小。而动态数组在使用时无需事先说明数组的大小,只是在程序设计中为程序动态地开辟存储空间。1.一维动态数组声明一维动态数组的语法格式为:Type array of;也可在变量声明中直接声明动态数组,其语法格式为:Var:array of;动态数组的声明中没有给出数组的下标类型,因此具有不确定的大小。在程序设计中
41、,动态数组的大小通过调用标准过程Setlength来指定。,4.5.2 动态数组,2.多维动态数组声明多维动态数组采用递归定义的语法格式如下:Type array of array of array of;或Var:array of array of array of;多维动态数组声明后,使用SetLength过程创建动态数组的实例,例如将Msgs分配成一个2行3列的数组:SetLength(Msgs,2,3);此时,动态数组Msgs被初始化。比如,此时Msgs0,1=。Object Pascal允许创建行的长度不等的动态数组。释放动态数组 Nil.,4.6 记录类型,前面介绍的几种数据类型,
42、构成类型的元素必须是同一种数据类型。然而在现实中,往往需要把一些数据类型不同的数据集中在一起,并作为一个整体操作。典型的例子是客户的登记表,一般是由下列信息组成:编号ID(整型)。客户姓名(字符串型)。产品数量(实型)。联系地址(字符串型)。是否已付款(布尔型)。1.记录类型的声明声明一个记录类型的一般语法格式为:Type=Record:;:;:;end;其中,类型标识符必须合法,类型1n可以是任意预定义类型或用户定义类型,域名表中可以是多个合法的域名标识符,这些标识符可以和记录域外的标识符相同。由于已经由记录类型名加以限定,所以不会发生标识符名称冲突。但在同一记录的域中域名不能相同。域名也可
43、以称为字段。,4.6 记录类型,2.访问记录域与With语句在程序设计中,记录类型经过声明并建立实例之后就可以使用了。使用记录类型实际上是对记录的字段进行访问,由于记录类型中元素的类型不同,因此不能像使用数组一样使用下标。访问记录域的方法有两种:限定访问记录字段和使用With语句。(1)限定访问记录中的字段声明了一个记录类型的变量后,就可以访问记录中的每一个字段了。在Object Pascal中,限定访问记录中某个字段的语法格式是:.;(2)使用With语句前面讲到,记录变量中的字段是通过记录变量名加一个小圆点和字段名来访问的。如果程序中有多处要访问的字段,可以使用With语句加以简化,其语法
44、格式是:With Do Do后面可以是单条语句(单条语句用With的意义不大),也可以是复合语句(用Begin和End括起来)。在这些语句中,对字段的访问不需要再加记录变量名。,4.6 记录类型,具有变体部分的记录类型 Type 记录类型名=Record 域名表1:类型1;域名表2:类型2;域名表n:类型n;Case 标识域名:标识域类型 of 常数表1:(变体1);常数表2:(变体2);End;1.变体部分应位于记录域的最后;2.变体部分类似Case语句,(标识域名:)可以省略。标识域类型 必须是顺序类型。3.每个变体i的声明语法与一般记录类型中域名表相同,但类型不能是长字符串,动态数组,v
45、ariant,接口类型,也不能是含有这些类型的结构类型。,4.7 指针类型,1.指针类型的声明指针类型在任何语言中都是比较难以理解也是比较灵活的一种数据类型,指针通常是它所指的变量的内存地址。声明指针类型的语法格式如下:Type=;其中,指针类型标识符即是指针类型名,基类型可以是简单类型,如整型、实型、字节型等,也可以是结构类型,如数组、记录、集合等类型。声明了指针类型后,就可以声明指针类型的变量。与通常的变量一样,一旦声明了指针变量,编译器将给指针变量分配存储单元,但存储单元中的值(所指向的内存地址)尚未确定。要想让指针指向确定的地址,必须通过赋值语句或New标准过程来实现。,4.7 指针类
46、型,2.指针的运算Delphi提供专门的过程和函数来操作指针,这些过程和函数是:New过程,运算符,PTR函数,GetMem过程。这里主要介绍用于指针运算的基本用法。3.无类型指针无类型的指针是指指针变量在声明时没有指明基类型。无类型指针在声明中只使用Pointer。例如:Var pAnyPoint:Pointer;指针pAnyPoint可以指向任何变量类型。无类型的指针的作用是它可以指向任何类型,但是,不能用指针变量符后加的形式来引用它的动态变量。如,类似Ptr的形式不可引用其动态变量。要引用Pointer类型指针(无类型指针)指向的变量,应先将其转换成确定的类型。4.字符指针类型字符指针类
47、型即PChar数据类型,是一个指向以NULL(不是零)字符结尾的字符(Char)串的指针。这种类型主要用于与外部函数如在Windows API中所用的函数兼容。,4.7 指针类型,5.动态存储结构的实现指针常用来描述动态存储结构的实现。动态存储结构中较常用的有链表、堆栈、队列等存储结构。可以把堆栈和队列看成特殊的链表。因此,本节只是简单介绍一下如何利用指针和记录来实现链表结构。链表是一组元素的序列,在这个序列中每个元素总是与它前面的元素相链接(第一个元素除外)。这种链接关系可通过指针来实现。图所示的就是一个链表。链表中的元素通常称为节点,第一个节点称为表头,最后一个节点称为表尾。指向表头的指针
48、称为头指针,在这个头指针中存放着表头的地址。节点一般用记录来描述,描述节点的记录至少含有两个域,一个域用来存放数据,该域的类型根据要存放的数据类型而定,称为值域;另一个域用来存放下一个节点的地址,称为指针域。表尾不指向任何节点,其指针的值为NIL。,4.7 指针类型,应用Object Pascal的指针和记录类型,图所示的链表可以声明如下:type Node:=record Data:Char;Next:Node;end;var Head:Node;,或type Link=Node;Node:=record Data:Char;Next:Node;end;var Head:Link;,4.8
49、过程类型,过程类型定义Type Tprocedure=procedure;Tmycallback=procedure(h:word);TMyFunc=procedure(a,b:integer;c:float);stdcall;TmouseEvent=procedure(sender:Tobject;button:TmouseButton;Shift:TshiftState;X,Y:Integer)of object方法指针过程,4.8 过程类型,一个过程类型变量实际上是一个过程指针,它指向过程或函数的地址。如果同时满足如下条件,两个过程类型将是兼容的:两个过程的调用约定是相同的;具有相同的返
50、回值类型;具有相同数量的参数,并且相应位置上的参数类型相同;可以将NIL赋给任何一个过程类型变量嵌套在一个子程序中的函数或过程不能作为一个过程值赋给一个过程变量,也不能使用它们来定义过程类型。要定义一个过程类型,应在程序单元的接口部分或在实现部分的隐含声明部分进行定义。过程类型变量可在赋值语句中和表达式中使用。,4.9 variant类型,Variant类型是对象 Pascal中的一种预定义的数据类型。声明Variant类型变量 var V:Variant;可以赋给它除Int64,指针和结构类型以外的所有类型的值。处理速度慢,所以除了编写OLE、COM、CORBA和一些数据库应用程序外,应尽量