字符类型
字符有两种不同的表示法:: ANSIChar 和 WideChar。第一种类型代表 8 位的字符,与Windows一直沿用的ANSI(美国国家标准协会)字符集相应;第二种类型代表 16 位的字符,与Windows NT、Windows 95 和 98支持的双字节字符(Unicode)相应。在Delphi 3 中,Char 类型字符与ANSIChar一致。切记,不管在什么环境,前 256 个Unicode 字符与ANSI 字符是完全一致的。
常量字符可用代表它们的符号表示,如‘k’,也可用数字符号表示,如 #78。后者还可用Chr函数表示为 Chr(78),用Ord函数可作相反的转换Ord(k)。
一般来说,对字母、数字或符号,用代表它们的符号来表示较好;而涉及到特殊字符时用数字符号较好。下面列出了常用的特殊字符:
· #9 跳格 (Tab 键)
· #10 换行
· #13 回车 (Enter 键)
序类型系统例程
Pascal 语言和Delphi System 单元中定义了一系列有序类型操作例程,见表 3.2。C 程序员会注意到其中的Inc 例程,它可与 和 = 运算符对应(Dec 例程也同样)。
表 3.2: 有序类型系统例程
例程 |
作用 |
Dec |
将例程中的参数值递减1或一个特定的值,其中特定值可在第二个可选参数中定义 |
Inc |
将例程中的参数值增加1或一个特定的值 |
Odd |
如果参数为奇数返回真 |
Pred |
根据参数在其数据类型定义中的序列,返回参数值的前驱值 |
Succ |
返回参数值的后继值 |
Ord |
返回参数值在其数据类型值集合中的序号 |
Low |
返回参数对应的有序数据类型的最小取值 |
High |
返回参数对应的有序数据类型的最大取值 |
注意,当有些例程用于常量时,编译器会自动用计算值替代例程。例如你调用High(X) ,设定X为一个整数,那么编译器会用整数类型中最大的可能值代替这个表达式。
实数类型
实数类型代表不同格式的浮点数。Single类型占的字节数最小,为4个字节;其次是Double 浮点类型,占8个字节;Extended 浮点类型,占10个字节。这些不同精度的浮点数据类型都与IEEE( 电气和电子工程师协会)标准的浮点数表示法一致,并且 CPU数字协处理器直接支持这些类型,处理速度也最快。
Real 类型在Delphi 2 和 Delphi 3 中的定义与 16 位版本一样,都占 6 个字节。不过Borland公司一直不提倡使用这种类型,而建议用Single、 Double、 Extended 类型代替。这是由于 Real 这种 6 字节的旧格式既不受 Intel CPU 的支持,又没有列在官方的IEEE 实型中。为了完全解决这一问题,Delphi 4 不得不修改 Real 类型的定义,将其改成标准的 8 字节浮点型, 由此引起了兼容性问题,不过如果有必要,你可以采用下面编译指令克服兼容性问题,恢复Delphi 2 和 Delphi 3 的Real 类型定义:
{$REALCOMPATIBILITY ON}
另外还有两种奇怪的数据类型: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浮点数运算标准,Object Pascal 语言完全适合于各类数值计算编程。如果对这部分感兴趣,你可以参考Delphi 在System单元中提供的算术函数(详细见Delphi 帮助)。
注意:Delphi 带有一个Math 单元,其中定义了一些高级数学例程,这些例程包括三角函数(如ArcCosh 函数)、金融函数(如InterestPayment 函数)和统计函数(如MeanAndStdDev 过程)。有些例程,它的名字听起来很怪,如MomentSkewKurtosis 例程,它是作什么用的呢? 还是留你自己查吧。
日期和时间
Delphi 也用实型数表示日期和时间数据。但为了更准确起见,Delphi 特别定义了TDateTime 数据类型,这是一个浮点类型,因为这个类型必须足够宽,使变量能容纳年、月、日、时、分和秒、甚至毫秒。日期值按天计数,从1899-12-30开始,放在TDateTime 类型的整数部分;时间值则位于十进制数的小数部分。
TDateTime 不是编译器可直接识别的预定义类型,它在System单元定义:
type
TDateTime = type Double;
使用TDateTime 类型很简单,因为Delphi 为该类型定义了一系列操作函数,表3.3列出了这些函数。
表3.3: TDateTime类型系统例程
例程 |
作用 |
Now |
返回当前日期及时间 |
Date |
返回当前日期 |
Time |
返回当前时间 |
DateTimeToStr |
按缺省格式将日期和时间值转换为字符串;特定格式转换可用 FormatDateTime函数 |
DateTimeToString |
按缺省格式将日期和时间值拷贝到字符串缓冲区 |
DateToStr |
将TDateTime值的日期部分转为字符串 |
TimeToStr |
将TDateTime值的时间部分转为字符串 |
FormatDateTime |
按特定格式将日期和时间值转换为字符串 |
StrToDateTime |
将带有日期和时间信息的字符串转换为TdateTime类型值,如串有误将引发一个异常 |
StrToDate |
将带有日期信息的字符串转换为TDateTime类型格式 |
StrToTime |
将带有时间信息的字符串转换为TDateTime类型格式 |
DayOfWeek |
根据传递的日期参数计算该日期是一星期中的第几天 |
DecodeDate |
根据日期值返回年、月、日值 |
DecodeTime |
根据时间值返回时、分、秒、毫秒值 |
EncodeDate |
组合年、月、日值为TDateTime类型值 |
EncodeTime |
组合时、分、秒、毫秒值为TDateTime类型值 |
类型映射及类型转换
正如所知,你不能把一个变量赋给另一个不同类型的变量,如果你需要这么做,有两种方法供选择。第一种方法是采用类型映射(Typecasting),它使用一个带有目标数据类型名的函数符号:
var
N: Integer;
C: Char;
B: Boolean;
begin
N := Integer ('X');
C := Char (N);
B := Boolean (0);
你可以在字节长度相同的数据类型之间进行类型映射。在有序类型之间或实型数据之间进行类型映射通常是安全的,指针类型及对象之间也可以进行类型映射 ,只要你明白自己在做什么。
然而,一般来说类型映射是一种较危险的编程技术,因为它允许你访问一个似是而非的值,该值好象是其它值的替身。由于数据类型的内部表示法之间通常互相不匹配,所以当遇到错误时会难以追踪,为此你应尽量避免使用类型映射。
第二种方法是使用类型转换例程。表3.4中总结了各种类型转换例程。注意表中没有包括特殊类型(如TDateTime 和variant)的转换例程,也没包括用于格式化处理的特殊例程,如Format 和FormatFloat 例程。
表3.4:类型转换系统例程
例程 |
作用 |
Chr |
将一个有序数据转换为一个ANSI字符 |
Ord |
将一个有序类型值转换为它的序号 |
Round |
转换一个实型值为四舍五入后的整型值 |
Trunc |
转换一个实型值为小数截断后的整型值 |
Int |
返回浮点数的整数部分 |
IntToStr |
将数值转换为字符串 |
IntToHex |
将数值转换为十六进制数字符串 |
StrToInt |
将字符串转换为一个整型数,如字符串不是一个合法的整型将引发异常 |
StrToIntDef |
将字符串转换为一个整数,如字符串不合法返回一个缺省值 |
Val |
将字符串转换为一个数字(传统Turbo Pascal例程用于向后兼容) |
Str |
将数字转换为格式化字符串(传统Turbo Pascal例程用于向后兼容) |
StrPas |
将零终止字符串转换为Pascal类型字符串,在32位Delphi中这种类型转换是自动进行的 |
StrPCopy |
拷贝一个Pascal类型字符串到一个零终止字符串, 在32位Delphi中这种类型转换是自动进行的 |
StrPLCopy |
拷贝Pascal类型字符串的一部分到一个零终止字符串 |
FloatToDecimal |
将一个浮点数转换为包含指数、数字及符号的十进制浮点记录类型 |
FloatToStr |
将浮点值转换为缺省格式的字符串 |
FloatToStrF |
将浮点值转换为特定格式的字符串 |
FloatToText |
使用特定格式,将一个浮点值拷贝到一个字符串缓冲区 |
FloatToTextFmt |
同上面例程,使用特定格式,将一个浮点值拷贝到一个字符串缓冲区 |
StrToFloat |
将一个Pascal字符串转换为浮点数 |
TextToFloat |
将一个零终止字符串转换为浮点数 |
注意:在最近版本的Delphi Pascal 编译器中,Round 函数是以 CPU 的 FPU (浮点部件) 处理器为基础的。这种处理器采用了所谓的 "银行家舍入法",即对中间值 (如 5.5、6.5) 实施Round函数时,处理器根据小数点前数字的奇、偶性来确定舍入与否,如 5.5 Round 结果为 6,而 6.5 Round 结果也为6, 因为 6 是偶数。
Pascal 语言的一个重要特征是它能自定义数据类型。通过各种类型构造器,你可以定义自己的数据类型,如子界类型、数组类型、记录类型、枚举类型、指针类型和集合类型。最重要的用户定义数据类型是类(class),类是Object Pascal的面向对象扩展部分。