首页 > 代码库 > 第五课 详解数据类型

第五课 详解数据类型

delphi中声明数据类型用关键字Var,关键字Var可以在很多地方使用,如放在函数或过程的开始部分的叫局部变量。放在单元中的叫全局变量。delphi中数据类型分为三大类:即有序数据类型,实数类型和字符类型。在细分可以分成。整数类型,布尔类型,字符类型,实数类型,日期和时间类型,自定义数据类型。等等。现在具体讲解各种类型。

  其中有序数据类型,布尔类型和字符类型按取值范围划分

大小有符号无符号
8 Bits

shortInt

-128 to 127

Byte

0 to 255

16 bits

SmallInt

-32768 to 32767

Word

0 to 65535

32 bits

LongInt

-2147483648 to 2147483647

LongWord

0 to 4294967295

64 bits Int64 
16/32 bitsInteger  Cardinal

  布尔类型

布尔值不同于布尔类型,平时很少用到。ByteBool、 WordBool 和LongBool这三种布尔类型的布尔值比较特殊,只在Windows API 函数中才用到它们。我们常用的Boolean类型,真为True值为1,假为False值为0.

  字符类型

字符类型有两种表示法:ANSIchar 和WideChar,第一种类型有8位字符,它属于美国标准字符。第二种代表16位的字符,它是用Unicode字符,也就是双字节。

  常量字符

常量字符可以代表用一个符号来表示如‘K’,也可以用#78,后者也可以用chr(78)表示。用Ord函数可以相反的转换Ord(k).

还有一些特殊的字符:

#9跳格(Tab键)

#10换行

#13回车(Enter键)

  有序类型

说明作用
DEC将参数值递减1或一个特定的值
inc将参数值增加1或一个特定的值
Odd如果参数为奇数返回真
Pred根据参数在其数据类型定义中的序列,返回参数的前驱值
Succ返回参数值的后继值
Ord返回参数在其数据类型值集合中的序号
Low返回参数对应有序数据类型的最小值
High返回参数对应有序数据类型的最大值

  实数类型

     实数类型代表不同格式的浮点数。如single类型为4个字节,Double类型为8个字节,Extended浮点类型,占10个字节。

  Read类型在Delphi早期版本中占6个字节,基本现在不使用该类型。

  另外还有两种奇怪的数据类型: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 也用实型数表示日期和时间数据。但为了更准确起见,Delphi 特别定义了TDateTime 数据类型,这是一个浮点类型,因为这个类型必须足够宽,使变量能容纳年、月、日、时、分和秒、甚至毫秒。日期值按天计数,从1899-12-30开始,放在TDateTime 类型的整数部分;时间值则位于十进制数的小数部分。

  TDateTime 不是编译器可直接识别的预定义类型,它在System单元定义:

type  TDateTime = type Double;

使用TDateTime 类型很简单,因为Delphi 为该类型定义了一系列操作函数,表3.3列出了这些函数。

例程作用
Now返回当前日期及时间
Date返回当前日期
Time返回当前时间
DateTimeToStr按缺省格式将日期和时间值转换为字符串;特定格式转换可用 FormatDateTime函数
DateTimeToString按缺省格式将日期和时间值拷贝到字符串缓冲区
DateToStr将TDateTime值的日期部分转为字符串
TimeToStr将TDateTime值的时间部分转为字符串
FormatDateTime按特定格式将日期和时间值转换为字符串
StrToDateTime将带有日期和时间信息的字符串转换为TdateTime类型值,如串有误将引发一个异常
StrToDate将带有日期信息的字符串转换为TDateTime类型格式
StrToTime将带有时间信息的字符串转换为TDateTime类型格式
DayOfWeek根据传递的日期参数计算该日期是一星期中的第几天
DecodeDate根据日期值返回年、月、日值
DecodeTime根据时间值返回时、分、秒、毫秒值
EncodeDate组合年、月、日值为TDateTime类型值
EncodeTime组合时、分、秒、毫秒值为TDateTime类型值

  为了显示怎样使用日期时间类型及其相关例程,我建了一个简单的例子TimeNow。该例子在主窗体中设置了一个按钮和一个列表框(ListBox)。开始执行时,程序自动计算并显示当前的时间及日期,以后每次单击按钮 ,显示从程序开始至当前的时间。

  下面列出了窗体的OnCreate 事件代码:

procedure TFormTimeNow.FormCreate(Sender: TObject);begin  StartTime := Now;  ListBox1.Items.Add (TimeToStr (StartTime));  ListBox1.Items.Add (DateToStr (StartTime));  ListBox1.Items.Add (‘Press button for elapsed time‘);end;

  第一句中调用了Now 函数,这个函数返回当前的日期和时间,它的值保存在StartTime 变量中,StartTime 变量是全程变量,其声明如下:

var  FormTimeNow: TFormTimeNow;  StartTime: TDateTime;

我只添加了第二个声明,第一个是由Delphi自动添加的。默认情况下的代码如下:

var  Form1: TForm1;

  窗体名改变后,这个声明被自动更新。使用全程变量实际上不是最好的办法,更好的方法是使用窗体类的私有域,这涉及到面向对象的编程技术。

  接下来的三个语句向位于窗体左面的列表框添加三个条目,结果见图3.3。列表框中的第一行显示了TDateTime 值的时间部分字符串、第二行显示的是同一值的日期部分,最后一行显示了一个简单的提示。

图 3.3:例TimeNow启动时的输出显示

 

 

当用户单击Elapsed 按钮时,上图第三行字符串被程序的计算结果代替:

procedure TFormTimeNow.ButtonElapsedClick(Sender: TObject);var  StopTime: TDateTime;begin  StopTime := Now;  ListBox1.Items [2] :=  FormatDateTime (‘hh:nn:ss‘,    StopTime - StartTime);end;

这串代码再次计算当前的时间,并显示当前与程序开始之时的时间差,其中用到了其它事件中的计算值,为此不得不把该值存入全程变量。实际上,最好是采用基于类的变量。

注意:上面代码中所用ListBox的索引号为2,,而它代表的是第三行的显示输出,其原因是listbox的数据项是从零开始计数的:第一项计为0,第二项为1,第三项为2,依次类推,后面涉及数组时再详细讨论这方面内容。

除了调用TimeToStr和 DateToStr 外,以上例子中还用到了功能强大的FormatDateTime 函数(关于格式化参数详见Delphi 帮助文件)。需要注意的是:当时间和日期转换成字符串时,其转换格式取决于Windows 的系统设置。Delphi 从系统中读这些值,并把它们拷贝到SysUtils 单元中声明的几个全程常量中,例如:

DateSeparator: Char;ShortDateFormat: string;LongDateFormat: string;TimeSeparator: Char;TimeAMString: string;TimePMString: string;ShortTimeFormat: string;LongTimeFormat: string;ShortMonthNames: array [1..12] of string;LongMonthNames: array [1..12] of string;ShortDayNames: array [1..7] of string;LongDayNames: array [1..7] of string;

大部分全程常量与currency 和浮点数格式化有关,在 Delphi 帮助的 Currency and date/time formatting variables 主题下,你可找到完整的清单。

注意:Delphi 中有一个DateTimePicker 控件,它提供了选择日期的常用途径,即从一个日历中选择日期。

特定的Windows 类型

到目前为止,我们所看到的预定义数据类型都是Pascal 语言自身定义的类型。 Delphi 中还包含Windows系统定义的数据类型,这些数据类型不是Pascal语言的组成部分,而是Windows 库的一部分。Windows 类型包括新增的缺省类型(例如DWORD 或UINT)、各种记录(或结构)类型及指针类型等。

Windows 定义的数据类型中,最重要的类型是句柄(handle),第九章中将讨论这一类型。

类型映射及类型转换

正如所知,你不能把一个变量赋给另一个不同类型的变量,如果你需要这么做,有两种方法供选择。第一种方法是采用类型映射(Typecasting),它使用一个带有目标数据类型名的函数符号:

var  N: Integer;  C: Char;  B: Boolean;begin  N := Integer (‘X‘);  C := Char (N);  B := Boolean (0);

你可以在字节长度相同的数据类型之间进行类型映射。在有序类型之间或实型数据之间进行类型映射通常是安全的,指针类型及对象之间也可以进行类型映射 ,只要你明白自己在做什么。

然而,一般来说类型映射是一种较危险的编程技术,因为它允许你访问一个似是而非的值,该值好象是其它值的替身。由于数据类型的内部表示法之间通常互相不匹配,所以当遇到错误时会难以追踪,为此你应尽量避免使用类型映射。

第二种方法是使用类型转换例程。表3.4中总结了各种类型转换例程。其中有些例程所涉及的数据类型将在下一节中讨论。 注意表中没有包括特殊类型(如TDateTime 和variant)的转换例程,也没包括用于格式化处理的特殊例程,如FormatFormatFloat 例程。

表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的基本数据类型。Pascal语言还有一个非常重要的特征:它允许编程者自定义数据类型,称为“用户自定义数据类型”,这在下一章进行讨论。

 

下一章: 用户自定义数据类型

 

第五课 详解数据类型