Delphi基础.doc_第1页
Delphi基础.doc_第2页
Delphi基础.doc_第3页
Delphi基础.doc_第4页
Delphi基础.doc_第5页
已阅读5页,还剩55页未读 继续免费阅读

下载本文档

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

文档简介

DELPHI语法基础注释在Pascal中,注释括在大括号中或带星号的圆括号中。Delphi也认可C+风格的注释,即把注释放在双斜线后。例如thisisacomment(*thisisanothercomment*)/thisisacommentuptotheendoftheline第一种注释方式较简略,使用也较为普遍;第二种方式在欧洲使用较广,因为欧洲的键盘缺少大括号;第三种方式的注释是从C+借用来的,只在32位版本的Delphi中可用,它在给一行代码加短注释时非常有用。上述三种不同的注释方式有益于进行嵌套注释。例如你要注销一段代码,而代码行中又包含真正的注释行,这时采用同一种注释方式是不对的:.codecomment,creatingproblems.code正确的方法是插入第二种注释方式:.code/thiscommentisOK.code注意:如果左大括号或圆括号-星号后面跟美元符号($),那么其中的内容就成了编译指令,如$X+。使用大写字母Pascal编译器(不象其他语言的编译器)不考虑字符的大小写,因此标识符Myname、MyName、myname、myName、和MYNAME是完全相同的。总体上来说,这是Pascal的一大优点,因为在大小写敏感的语言中,许多语法错误是由不正确的大写引起的。然而大小写不敏感也有不便之处:第一,你必须注意大小写不一致的标识符实际上是相同的,以避免把他们当成不同的元素使用;第二,你必须尽量保持大写使用的一致性,以提高代码的可读性。大写使用的一致性不是编译器强制要求的,但是保持大写使用的一致性是值得提倡的好习惯。一个常用的方法是将每个标识符的第一个字母大写,标识符若由几个词组合而成(中间不能插入空格),每个词的第一个字母应大写:MyLongIdentifierMyVeryLongAndAlmostStupidIdentifier此外,编译器不编译代码中的空格、空行和Tab键空格,这些元素通称为空白,它们只用来提高代码的可读性,不影响编译过程。1不同于BASIC,Pascal语句允许分行书写,即将一条长指令分割成两个或更多的代码行。允许语句分行的缺点(至少对许多BASIC程序员)是:语句结束时不能忘了加分号,更确切地说,必须记着把语句和紧接它的语句分开。语句分行唯一的限制是字符串不能跨行。关于空格和语句分行的使用没有既定的规则,以下是几点经验:Delphi代码编辑器中有一条竖线叫右边线(RightMargin),你可以把右边线设置在60或70个字符处。如果以这条线为基准,代码不超过这条界限,那么打印到纸上的代码看起来会很好看。否则,打印时长语句会被随意分行,甚至在一个词的中间断开。当一个函数或过程有多个参数,通常的做法是把各参数放在不同的行上。你可以在注释行前留一行空白,或把长的代码句分成较小的部分,这样能提高代码的可读性。用空格隔开函数调用的参数,表达式中的运算符也最好用空格隔开。优化版面关于代码编写风格的最后一条建议是:尽量使用空白优化版面。这一条很容易做到,只需要在写复合句时,以上一句为参照,下一句向右缩进两个空格,复合句内嵌的复合句缩进四个空格,依此类推。例如:if.thenstatement;if.thenbeginstatement1;statement2;end;if.thenbeginif.thenstatement1;statement2;end;相似的缩进格式常用于变量或数据类型声名区,也可用于语句的续行:typeLetters=setofChar;varName:string;beginlongcommentandlongstatement,goingoninthefollowinglineandindentedtwospacesMessageDlg(Thisisamessage,2mtInformation,mbOk,0);提出以上代码编写格式只是向你建个议而已,这样代码能更加易读,其实代码格式并不影响编译结果。关键字关键字是ObjectPascal的保留标识符,在语言中有着特殊含义。保留字不能用作标识符,指令字也同样不应该用作标识符,即使编译器允许也最好不用。在实际中你不应该把任何关键字用作标识符。表2.1是面向对象Pascal语言(Delphi4)中特殊标识符的完整列表,其中包括关键字及保留字。表2.1:面向对象Pascal语言中的关键字及保留字3关键字作用absolute指令(变量)abstract指令(方法)and运算符(布尔)array类型as运算符(RTTI)asm语句assembler向后兼容(汇编)at语句(异常处理)automated访问类别符(类)begin块标记case语句cdecl函数调用协定class类型const声明或指令(参数)constructor特殊方法contains运算符(集合)default指令(属性)destructor特殊方法dispiddispinterface界面类别符dispinterface类型div运算符do语句downto语句(for)4dynamic指令(方法)else语句(if或case)end块标记except语句(异常处理)export向后兼容(类)exports声明external指令(函数)far向后兼容(类)file类型finalization单元结构finally语句(异常处理)for语句forward函数指令function声明goto语句if语句implementation单元结构implements指令(属性)in运算符(集合)-工程结构index指令(dipinterface界面)inherited语句initialization单元结构inline向后兼容(见asm)interface类型is运算符(RTTI)label声明library程序结构message指令(方法)mod运算符(数学)name指令(函数)near向后兼容(类)nil数值nodefault指令(属性)not运算符(布尔)5object向后兼容(类)of语句(case)on语句(异常处理)or运算符(布尔)out指令(参数)overload函数指令override函数指令package程序结构(控件包)packed指令(记录)pascal函数调用协定private访问类别符(class)procedure声明program程序结构property声明protected访问类别符(类)public访问类别符(类)published访问类别符(类)raise语句(异常处理)read属性类别符readonlydispatch界面类别符record类型register函数调用协定reintroduce函数指令repeat语句requires程序结构(控件包)resident指令(函数)resourcestring类型safecall函数调用协定set类型shl运算符(数学)shr运算符(数学)stdcall函数调用协定stored指令(属性)string类型表达式和运算符建立表达式没有通用的方法,因为要取决于所用的运算符,Pascal包括有逻辑运算符、算术运算符、布尔运算符、关系运算符和集合运算符等等。表达式可用于确定赋给一个变量的值、计算函数或过程的参数、或者判断一个条件,表达式也可以包含函数调用。表达式是对一个标识符的值而不是标识符本身进行运算。所有编程语言中的表达式都是常量、变量、数值、运算符和函数值的合法组合。表达式可以传递给过程或函数的值参,但不能传递给过程或函数中的引用参数。运算符及其优先级如果你以前写过程序,那么你已经知道表达式是什么了。这里我专门讲一下Pascal运算符的特殊部分:运算符的优先级。表2.2中按优先级分组列出了Pascal语言的运算符。与大多数编程语言相反,Pascal语言中and和or运算符的优先级比关系运算符高。因此,如果你的代码为abandcd,编译器首先会编译and运算符,由此导致编译出错。为此你应该把每个表达式用小括号括起来:(ab)and(cd)。同一种运算符用于不同数据类型时它的作用不同。例如,运算符+可以计算两个数字的和、连接两个字符串、求两个集合的并集、甚至给PChar指针加一个偏移量。然而,你不能象在C语言中那样将两个字符相加。另一个特殊的运算符是div。在Pascal中,你能用/计算两个数字(实数或整数)的商,而且你总能得到一个实型结果。如果计算两个整数的商并想要一个整型结果,那么就需要用div运算符。6then语句(if)threadvar声明to语句(for)try语句(异常处理)type声明unit单元结构until语句uses单元结构var声明virtual指令(方法)while语句with语句write属性类别符writeonlydispatch界面类别符xor运算符(布尔)表2.2:Pascal语言中的运算符及其优先级集合运算符7单目运算符(最高优先级)取变量或函数的地址(返回一个指针)not逻辑取反或按位取反乘除及按位运算符*相乘或集合交集/浮点相除div整数相除mod取模(整数相除的余数)as程序运行阶段类型转换(RTTI运算符)and逻辑或按位求和shl按位左移shr按位右移加减运算符+相加、集合并集、字符串连接或指针增加一个偏移量-相减、集合差集或指针减少一个偏移量or逻辑或按位或运算xor逻辑或按位异或运算关系及比较运算符(最低优先级)=判断是否相等判断是否不相等判断是否大于=判断是否大于或等于,或是否是一个集合的父集in判断是否是集合成员is判断对象是否类型兼容(又一个RTTI运算符)集合运算符包括并(+)、差(-)、交(*)、成员检测(in),及一些关系运算符。要把一个元素添加到集合中,你可以采用集合并运算。下面是一个选择字体的Delphi例子:Style:=Style+fsBold;Style:=Style+fsBold,fsItalic-fsUnderline;另一种方法是利用标准过程Include和Exclude,它们效率更高(但不能用于控件的集合类型属性,因为只能操纵一个元素):Include(Style,fsBold);变量Pascal变量在使用前必须声明,声明变量时必须指定一种数据类型。下面是变量声明的例子:varValue:Integer;IsCorrect:Boolean;A,B:Char;关键字var可以在许多地方使用,例如放在函数或过程的开始部分,用来声明函数或过程的局部变量;也可以放在单元中,用于声明全程变量。var关键字之后是一组变量名列表,每个变量名后跟一个冒号和数据类型名,一行中可以声明多个变量,如上例中最后一句。一旦变量的类型被指定,你只能对变量执行该变量类型支持的操作。例如,在判断操作中用布尔值,在数字表达式中用整型值,你不能将布尔值和整型值混用(在C语言中可以这样)。使用简单的赋值语句,可写出下面的代码:Value:=10;IsCorrect:=True;但下面的语句是不正确的,因为两个变量数据类型不同:Value:=IsCorrect;/error在Delphi中编译这句代码,会出现错误信息:Incompatibletypes:IntegerandBoolean.(类型不兼容:整型和布尔型)。象这样的错误通常是编程错误,因为把一个True或False的值赋给一个整型变量没有什么意义。你不该责怪Delphi提示这样的错误信息,代码中有不对的地方Delphi当然要提出警告。把变量的值从一种类型转换到另一种类型往往不难做到,有些情况下类型转换会自动实现,不过一般情况下需要调用特殊的系统函数,通过改变数据内部表示来实现类型转换。在Delphi中,当你声明全程变量时,你可以赋给它一个初值。例如,你可以这样写:varValue:Integer=10;Correct:Boolean=True;这种初始化方法只能用于全程变量,不能用于过程或方法的变量。常量8对于在程序运行期间保持不变的值,Pascal允许通过常量来声明。声明常量不必特定数据类型,但需要赋一个初值。编译器会根据所赋初值自动选用合适的数据类型。例如:constThousand=1000;Pi=3.14;AuthorName=MarcoCant;Delphi根据常量的值来决定它的数据类型。上例中的Thousand变量,Delphi会选用SmallInt数据类型(短整型-能容纳Thousand变量的最小整数类型)。如果你想告诉Delphi采用特定的类型,你可在声明中加入类型名,方法如下:constThousand:Integer=1000;对于声名的常量,编译器有两种编译选择:第一种为常量分配内存,并把常量的值放入内存;第二种在常量每次使用时复制常量值。第二种方法比较适合简单常量。注意:16位的Delphi允许你在程序运行期间改变已定义的常量值,就象一个变量一样。32位的Delphi为了向后兼容仍容许这种操作,只要你附加$J编译指令,或选择工程选项对话框中Compiler(编译器)页的Assignabletypedconstants复选框就行。资源串常量当定义字符串常量时,你可这样写:constAuthorName=MarcoCant;从Delphi3开始,你可以用另一种方式写:resourcestringAuthorName=MarcoCant;上面两个语句都定义了一个常量,也就是定义了一个在程序运行期间保持不变的值,但两者的实现过程却不同,用resourcestring指令定义的字符串变量将被保存到程序资源的字符串表中。从例子ResStr你可了解资源串的实际作用,例子中设置了一个按钮,相应代码如下:resourcestringAuthorName=MarcoCant;BookName=EssentialPascal;procedureTForm1.Button1Click(Sender:TObject);beginShowMessage(BookName+#13+AuthorName);end;以上代码中的两个字符串将分两行输出显示,因为字符串被分行符#13隔开。有趣的是,当你用资源编辑器打开执行文件时,你会在程序资源中看到你所定义的字符串。这意味着字符串并没有进入编译代码,而是保存在执行文件(EXE文件)的一个单独区域。9注意:简而言之,采用资源的好处一方面可让Windows来完成有效的内存处理,另一方面不用更改源代码就可实现程序的本地化(把字符串翻译成不同的语言)。数据类型Pascal中有多种预定义的数据类型,它们可分为三大类:有序数据类型,实数类型和字符串类型。Delphi还包括一种无类型的可变数据类型,称作variant,variant是一种无需类型检测的数据类型,它在Delphi2中引入,用于处理OLEAutomation(OLE自动化)。有序类型有序类型是建立在概念“顺序”或“序列”基础上的数据类型。你不仅可比较两个有序值的大小,而且可以求取给定有序值的前驱及后继,或者计算它们的最大或最小值。三种最重要的预定义有序类型是整数类型、布尔类型和字符类型(Integer,Boolean,Char)。各种类型根据其内部表示和取值范围不同又可进一步细分。表3.1列出了表示数字的有序数据类型。表3.1:表示数字的有序数据类型从表中可看到,不同数据类型与不同的数据表示法相对应,这要取决于数据值的数位和符号位。有符号类型的数值可正可负,但取值范围较小,因为符号位占一个数位。下一节在例Range中说明了每种类型的实际取值范围。表中最后一组类型标志着16/32,它表明其数值表示方法在16位和32位Delphi中不同,该组的Integer及Cardinal类型比较常用,因为它们与CPU内部的数字表示法相对应。布尔类型布尔值不同于布尔类型,平时很少用到。ByteBool、WordBool和LongBool这三种布尔类型的布尔值比较特殊,只在WindowsAPI函数中才用到它们。在Delphi3中,为了与VisualBasic和OLEAutomation兼容,修改了ByteBool、WordBool和LongBool的布尔值,将TRUE值设置为1,FALSE值仍为0;Boolean类型布10大小有符号值域无符号值域8bitsShortInt-128to127Byte0to25516bitsSmallInt-32768to32767Word0to65,53532bitsLongInt-2,147,483,648to2,147,483,647LongWord(从Delphi4)0to4,294,967,29564bitsInt6416/32bitsIntegerCardinal尔值保持不变(TRUE为1,FALSE为0)。如果在Delphi2代码中使用了布尔值显式类型转换,那么在以后的Delphi中可能会出错。字符类型字符有两种不同的表示法::ANSIChar和WideChar。第一种类型代表8位的字符,与Windows一直沿用的ANSI(美国国家标准协会)字符集相应;第二种类型代表16位的字符,与WindowsNT、Windows95和98支持的双字节字符(Unicode)相应。在Delphi3中,Char类型字符与ANSIChar一致。切记,不管在什么环境,前256个Unicode字符与ANSI字符是完全一致的。常量字符可用代表它们的符号表示,如k,也可用数字符号表示,如#78。后者还可用Chr函数表示为Chr(78),用Ord函数可作相反的转换Ord(k)。一般来说,对字母、数字或符号,用代表它们的符号来表示较好;而涉及到特殊字符时用数字符号较好。下面列出了常用的特殊字符:#9跳格(Tab键)#10换行#13回车(Enter键)序类型系统例程Pascal语言和DelphiSystem单元中定义了一系列有序类型操作例程,见表3.2。C+程序员会注意到其中的Inc例程,它可与+和+=运算符对应(Dec例程也同样)。表3.2:有序类型系统例程注意,当有些例程用于常量时,编译器会自动用计算值替代例程。例如你调用High(X),设定X为一个整数,那么编译器会用整数类型中最大的可能值代替这个表达式。实数类型实数类型代表不同格式的浮点数。Single类型占的字节数最小,为4个字节;其次是Double浮点类型,占8个字节;Extended浮点类型,占10个字节。这些不同精度的浮点数据类型都11例程作用Dec将例程中的参数值递减1或一个特定的值,其中特定值可在第二个可选参数中定义Inc将例程中的参数值增加1或一个特定的值Odd如果参数为奇数返回真Pred根据参数在其数据类型定义中的序列,返回参数值的前驱值Succ返回参数值的后继值Ord返回参数值在其数据类型值集合中的序号Low返回参数对应的有序数据类型的最小取值High返回参数对应的有序数据类型的最大取值与IEEE(电气和电子工程师协会)标准的浮点数表示法一致,并且CPU数字协处理器直接支持这些类型,处理速度也最快。Real类型在Delphi2和Delphi3中的定义与16位版本一样,都占6个字节。不过Borland公司一直不提倡使用这种类型,而建议用Single、Double、Extended类型代替。这是由于Real这种6字节的旧格式既不受IntelCPU的支持,又没有列在官方的IEEE实型中。为了完全解决这一问题,Delphi4不得不修改Real类型的定义,将其改成标准的8字节浮点型,由此引起了兼容性问题,不过如果有必要,你可以采用下面编译指令克服兼容性问题,恢复Delphi2和Delphi3的Real类型定义:$REALCOMPATIBILITYON另外还有两种奇怪的数据类型:Comp类型和Currency类型,Comp类型用8个字节描述非常大的整数(这种类型可支持带有18位小数的数字);Currency类型(16位版的Delphi不支持该类型)表示一个有四位小数位的值,它的小数位长度是固定的,同Comp类型一样也占8个字节。正如名字所示,Currency数据类型是为了操作很精确的四位小数货币数值才添加的。对实型数据,我们没办法编一个类似Range的程序,因为High、Low及Ord函数不能用于实型值。理论上说实型类型代表一个无限的数字集合;有序类型代表一个有限的数字集合。注意:让我进一步把上述问题解释一下。对于整数23,你能确定23后面的数是什么,因为整型数是有限的,它们有确定的值域范围及排列顺序。而浮点数即使在一个很小的值域范围内也无限、无序。事实上,在23和24之间有多少值?哪个值是23.46后面的值?23.47还是23.461,或者23.4601?这是很难说清的。因此,如问Char类型字符w的顺序位置是有意义的,但同样的问题对浮点类型数7134.1562就毫无意义。对于一个实型数,你能确切知道有没有比它大的实型数,但是,如想探究给定的实数前到底有多少个实型数(这是Ord函数的作用),是得不到结果的。实型类型在用户界面编程中用得不多,但是Delphi从各方面支持实型类型,包括在数据库方面的支持。由于支持IEEE浮点数运算标准,ObjectPascal语言完全适合于各类数值计算编程。如果对这部分感兴趣,你可以参考Delphi在System单元中提供的算术函数(详细见Delphi帮助)。注意:Delphi带有一个Math单元,其中定义了一些高级数学例程,这些例程包括三角函数(如ArcCosh函数)、金融函数(如InterestPayment函数)和统计函数(如MeanAndStdDev过程)。有些例程,它的名字听起来很怪,如MomentSkewKurtosis例程,它是作什么用的呢?还是留你自己查吧。日期和时间Delphi也用实型数表示日期和时间数据。但为了更准确起见,Delphi特别定义了TDateTime数据类型,这是一个浮点类型,因为这个类型必须足够宽,使变量能容纳年、月、日、时、分和秒、甚至毫秒。日期值按天计数,从1899-12-30开始,放在TDateTime类型的整数部分;时间值则位于十进制数的小数部分。TDateTime不是编译器可直接识别的预定义类型,它在System单元定义:type12TDateTime=typeDouble;使用TDateTime类型很简单,因为Delphi为该类型定义了一系列操作函数,表3.3列出了这些函数。表3.3:TDateTime类型系统例程类型映射及类型转换正如所知,你不能把一个变量赋给另一个不同类型的变量,如果你需要这么做,有两种方法供选择。第一种方法是采用类型映射(Typecasting),它使用一个带有目标数据类型名的函数符号:varN:Integer;C:Char;B:Boolean;beginN:=Integer(X);13例程作用Now返回当前日期及时间Date返回当前日期Time返回当前时间DateTimeToStr按缺省格式将日期和时间值转换为字符串;特定格式转换可用FormatDateTime函数DateTimeToString按缺省格式将日期和时间值拷贝到字符串缓冲区DateToStr将TDateTime值的日期部分转为字符串TimeToStr将TDateTime值的时间部分转为字符串FormatDateTime按特定格式将日期和时间值转换为字符串StrToDateTime将带有日期和时间信息的字符串转换为TdateTime类型值,如串有误将引发一个异常StrToDate将带有日期信息的字符串转换为TDateTime类型格式StrToTime将带有时间信息的字符串转换为TDateTime类型格式DayOfWeek根据传递的日期参数计算该日期是一星期中的第几天DecodeDate根据日期值返回年、月、日值DecodeTime根据时间值返回时、分、秒、毫秒值EncodeDate组合年、月、日值为TDateTime类型值EncodeTime组合时、分、秒、毫秒值为TDateTime类型值C:=Char(N);B:=Boolean(0);你可以在字节长度相同的数据类型之间进行类型映射。在有序类型之间或实型数据之间进行类型映射通常是安全的,指针类型及对象之间也可以进行类型映射,只要你明白自己在做什么。然而,一般来说类型映射是一种较危险的编程技术,因为它允许你访问一个似是而非的值,该值好象是其它值的替身。由于数据类型的内部表示法之间通常互相不匹配,所以当遇到错误时会难以追踪,为此你应尽量避免使用类型映射。第二种方法是使用类型转换例程。表3.4中总结了各种类型转换例程。注意表中没有包括特殊类型(如TDateTime和variant)的转换例程,也没包括用于格式化处理的特殊例程,如Format和FormatFloat例程。表3.4:类型转换系统例程14例程作用Chr将一个有序数据转换为一个ANSI字符Ord将一个有序类型值转换为它的序号Round转换一个实型值为四舍五入后的整型值Trunc转换一个实型值为小数截断后的整型值Int返回浮点数的整数部分IntToStr将数值转换为字符串IntToHex将数值转换为十六进制数字符串StrToInt将字符串转换为一个整型数,如字符串不是一个合法的整型将引发异常StrToIntDef将字符串转换为一个整数,如字符串不合法返回一个缺省值Val将字符串转换为一个数字(传统TurboPascal例程用于向后兼容)Str将数字转换为格式化字符串(传统TurboPascal例程用于向后兼容)StrPas将零终止字符串转换为Pascal类型字符串,在32位Delphi中这种类型转换是自动进行的StrPCopy拷贝一个Pascal类型字符串到一个零终止字符串,在32位Delphi中这种类型转换是自动进行的StrPLCopy拷贝Pascal类型字符串的一部分到一个零终止字符串FloatToDecimal将一个浮点数转换为包含指数、数字及符号的十进制浮点记录类型FloatToStr将浮点值转换为缺省格式的字符串FloatToStrF将浮点值转换为特定格式的字符串FloatToText使用特定格式,将一个浮点值拷贝到一个字符串缓冲区Pascal语言的一个重要特征是它能自定义数据类型。通过各种类型构造器,你可以定义自己的数据类型,如子界类型、数组类型、记录类型、枚举类型、指针类型和集合类型。最重要的用户定义数据类型是类(class),类是ObjectPascal的面向对象扩展部分。命名及不命名的类型为了后续使用或直接用于变量,需要给自定义类型命名。如果自定义一个命名的类型,你必须将代码放在特定的type区,如下所示:type/subrangedefinitionUppercase=A.Z;/arraydefinitionTemperatures=array1.24ofInteger;/recorddefinitionDate=recordMonth:Byte;Day:Byte;Year:Integer;end;/enumeratedtypedefinitionColors=(Red,Yellow,Green,Cyan,Blue,Violet);/setdefinitionLetters=setofChar;你也可使用类型定义构造器直接定义一个变量,此时无需显式命名,如下面的代码:varDecemberTemperature:array1.31ofByte;ColorCode:arrayRed.VioletofWord;Palette:setofColors;15FloatToTextFmt同上面例程,使用特定格式,将一个浮点值拷贝到一个字符串缓冲区StrToFloat将一个Pascal字符串转换为浮点数TextToFloat将一个零终止字符串转换为浮点数注意:在最近版本的DelphiPascal编译器中,Round函数是以CPU的FPU(浮点部件)处理器为基础的。这种处理器采用了所谓的银行家舍入法,即对中间值(如5.5、6.5)实施Round函数时,处理器根据小数点前数字的奇、偶性来确定舍入与否,如5.5Round结果为6,而6.5Round结果也为6,因为6是偶数。注意:一般来说,你应该避免使用上述不命名类型,因为你不能把它们作为参数传给例程,也不能用于声名同一类型的其他变量。实际上,Pascal的类型兼容规则是基于类型名的,而不是基于实际的类型定义。两个类型相同的变量仍有可能是不兼容的,除非他们的类型有完全相同的名字。对于不命名类型,需要编译器给它分配一个内部名字,因此对于数据结构复杂的变量,要习惯于定义命名数据类型,你一定不会为此白费工夫的。子界类型子界类型定义了某种类型的取值范围(因此定名subrange)。你可定义整数类型的子界类型,如取值从1到10或从100到1000,或者定义字符类型的子界类型,如下所示:typeTen=1.10;OverHundred=100.1000;Uppercase=A.Z;定义子界类型时,你不需要指定基类的名字,而只需提供该类型的两个常数。所用基类必须是有序类型,定义结果将是另一种有序类型。如定义一个子界变量,那么赋给该变量的值必须是子界定义范围内的值。下面代码是正确的:varUppLetter:UpperCase;beginUppLetter:=F;以下代码则是不正确的:varUppLetter:UpperCase;beginUppLetter:=e;/compile-timeerror以上代码将导致一个编译错误:“Constantexpressionviolatessubrangebounds”。如果代之以下面代码:varUppLetter:Uppercase;Letter:Char;beginLetter:=e;UppLetter:=Letter;Delphi编译会通过,但在运行时,如果你开启了范围检查编译选项(在工程选项对话框的编译器页设置),你将得到Rangecheckerror(范围检测错误)信息。注意:建议你在开发程序时开启上述编译选项,以使程序更健壮并易于调试。这样即使遇上错误,你也会得到一个明确的信息而不是难以琢磨的行为。最终完成程序时你可以去掉这个选项,使程16序运行得快一些,不过影响很小。因此我建议你开启所有运行时的检测选项,如溢出检查和堆栈检查,甚至提交程序时仍然保留它们。枚举类型枚举类型又是一种自定义有序类型。在枚举类型中,你列出所有该类型可能取的值,而不是指定现有类型的范围。换句话说,枚举类型是个可取值的序列。见下例:typeColors=(Red,Yellow,Green,Cyan,Blue,Violet);Suit=(Club,Diamond,Heart,Spade);序列中每个值都对应一个序号,序号从0开始计数。使用Ord函数,即可得到一个枚举类型值的序号。例如,Ord(Diamond)返回值1。注意:枚举类型有多种内部表示法。缺省时,Delphi用8位表示法;如果有多于256个不同的值,则用16位表示法。还有一种32位表示法,需要与C、C+库兼容时会用到。使用$Z编译指令可改变缺省设置,请求更多位的表示法。集合类型集合类型表示一组值,该组值由集合所依据的有序类型定义。定义集合的常用有序类型不多,一般为枚举类型或子界类型。如果子界类型取值为1.3,那么基于它的集合类型值可以是1、或2、或3、或1和2、或1和3、或2和3、或取所有3个数、或一个数也没有。一个变量通常包含该类型对应的一个值,而集合类型可以不包含值、包含一个值、两个值、三个值,或更多,它甚至可以包含定义范围内所有的值。下面定义一个集合:typeLetters=setofUppercase;现在我可以用上面类型来定义变量,并把原始类型的值赋给变量。为了在集合中表示一组值,需要用逗号将值隔开,最后用方括号结尾。下例显示了多值、单值和空值的变量赋值:varLetters1,Letters2,Letters3:Letters;beginLetters1:=A,B,C;Letters2:=K;Letters3:=;在Delphi中,集合一般用于表示有多种选择的标记。例如下面两行代码(摘自Delphi库)声明了一个枚举类型,其中列出了窗口条上可选的图标,并声明了相应的集合类型:typeTBorderIcon=(biSystemMenu,biMinimize,biMaximize,biHelp);TBorderIcons=setofTBorderIcon;实际上,给定的窗口中可以没有图标,也可以有一个或多个图标。用ObjectInspector设置时(见图4.3),双击属性名,或单击属性左边的加号,自行选择,从而添加或删除集合中的值。17图4.3:ObjectInspector中的集合类型属性另一个基于集合类型的属性是字体。字体类型值可以是粗体、斜体、带下画线、带删除线等,一种字型可以既是斜体又是粗体,也可以没有属性,或者带有全部的属性。因此用集合类型来表示它。你可以象下面代码那样,在程序中给集合赋值:Font.Style:=;/nostyleFont.Style:=fsBold;/boldstyleonlyFont.Style:=fsBold,fsItalic;/twostyles你也能对一个集合进行许多不同方式的操作,包括把两个相同类型的集合变量相加(或更准确地说,计算两个集合变量的并集):Font.Style:=OldStyle+fsUnderline;/twosets数组类型数组类型定义了一组指定类型的元素序列,在方括号中填入下标值就可访问数组中的元素。定义数组时,方括号也用来指定可能的下标值。例如,下面的代码中定义了一个有24个整数的数组:typeDayTemperatures=array1.24ofInteger;在数组定义时,你需要在方括号中填入一个子界类型的值,或者用两个有序类型的常量定义一个新的子界类型,子界类型指定了数组的有效索引。由于子界类型指定了数组下标值的上界和下界,那么下标就不必象C、C+、JAVA和其他语言那样必须从零开始。由于数组下标基于子界类型,因此Delphi能够对它们进行范围检查。不合法的常量子界类型将导致一个编译时间错误;如果选上编译器范围检查选项,那么超出范围的下标值将导致一个运行时间错误。使用上述数组定义方法,定义一个DayTemperatures类型的变量如下:typeDayTemperatures=array1.24ofInteger;varDayTemp1:DayTemperatures;procedureAssignTemp;begin18DayTemp11:=54;DayTemp12:=52;.DayTemp124:=66;DayTemp125:=67;/compile-timeerror数组可以是多维的,如下例:typeMonthTemps=array1.24,1.31ofInteger;YearTemps=array1.24,1.31,Jan.DecofInteger;这两个数组建立在相同的核心类型上,因此你可用前面定义的数据类型声明它们,如下面代码所示:typeMonthTemps=array1.31ofDayTemperatures;YearTemps=arrayJan.DecofMonthTemps;上例的声明把索引的次序前后调换了一下,但仍允许变量之间整块赋值。例如:把一月份的温度值赋给二月份:varThisYear:YearTemps;begin.ThisYearFeb:=ThisYearJan;你也能定义下标从零开始的数组,不过这似乎不太合逻辑,因为你需要用下标2来访问数组第三项。然而,Windows一直沿用了从零开始的数组(因为它是基于C语言的),并且Delphi控件库也在往这方向靠拢。使用数组时,你总要用标准函数Low和High来检测它的边界

温馨提示

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

评论

0/150

提交评论