Tivoli 服务台 6.0 开发工具包脚本程序设计指南

第 2 章:数据类型

返回目录


简介

本章向用户介绍在开发工具包中最经常使用的数据类型。除了讨论数据类型本身外,本章还有关于常量、变量和表达式的信息。

简单数据类型

数据类型定义变量或常量中的数据的属性。可能的属性包括:

开发工具包数据类型

开发工具包有六种简单数据类型。

其它数据类型

句柄类型

句柄是包括另一变量地址的变量。地址是变量的位置。句柄使程序能访问特定资源。

句柄类型有特定用途,不从任何其它类型导出。开发人员使用句柄标识逻辑实体(在其上执行操作)。下列是句柄类型列表:

外部参数类型

外部参数类型是简单类型的带注释版本,它帮助开发工具包解释器在调用外部 DLL 前,把开发工具包值转换为响应的 C 或 Pascal 类型:

聚集类型

三种聚集类型不能单独使用,但可与任何其它类型一起使用,以创建用户定义类型:

常量

常量是已命名的项,在程序执行过程中它保持不变,即始终如一。在知识库的 CONSTANTS 段进行所有的常量说明。

说明常量

要在知识库中说明常量,用户必须完成下列步骤:

像所有开发工具包语句一样,常量说明总以分号(;)结尾。

使用不同数据类型进行常量说明的实例如下:

CONSTANTS
   (* 字符串常量 *)
   fileName IS 'MYFILE.DAT'; 
   pathName IS 'EADVISOR\ADVISOR\DATA'; 
   driveName IS 'E:'; 
  (* 整常数 *)
  MAX_EMPLOYEES IS 500; 
  ERROR_CODE IS -1; 
  (* 实常数 *)
  PI_VALUE IS 3.14159; 
  MAX_SALARY IS 999999.99; 
  LO_VALUE IS -5134.1348; 
  (* 布尔常量 *)
  SAVE_TO_DISK IS TRUE; 
  OVERWRITE_FILE IS FALSE; 
  (* 日期常量 *)
  CHRISTMAS IS {12,25,1996}: DATE; 
  BIRTH_DAY IS {2,13,1956}: DATE; 
  (* 时间常量 *)
  START_OF_DAY IS {8,30,0}: TIME; 
  END_OF_DAY IS {18,0,0}: TIME; 

注:国际用户应了解,在开发工具包初始状态中日期“部分”顺序是(月,日,年),且不随语言环境更改。

变量

变量是已命名的项,包括程序执行过程中可修改的数据类型。在知识库的 VARIABLES 段中说明变量。

说明变量

要在知识库中说明变量,用户必须完成下列步骤:

如下例所示,通过用逗号分隔变量名,用户可说明同类型的多个变量:

VARIABLES 
  first_name, last_name        : STRING; 
  i,j                          : INTEGER; 
  salary                       : REAL; 
  married                      : BOOLEAN; 
  entryDate                    : DATE; 
  startTime                    : TIME; 

为变量赋值

用赋值运算符(:=)为变量赋值。

下列代码段显示为在上例中定义的变量进行变量赋值:

first_name        := 'Amy'; 
last_name         := 'Alec'; 
i                 := 7; 
j                 := 32; 
salary            := 37500.00; 
married           := FALSE; 
entryDate         := {1,31,1991}: DATE; 
startTime         := {10,30,0}: TIME; 

数据类型转换

用户有时可能需要转换数据类型。当表示信息的方法有所更改时,需要进行数据转换。例如,用户可把二进制表示法更改为十进制或十六进制表示法,或把整数更改为字符串。

简单数据类型转换

开发工具包使用大括号{}指示要转换哪个值。

在此例中,把大括号中的值转换为整数:

i := {s}: INTEGER; 

当开发工具包遇到此行时,它完成下列工作:

转换数值不破坏原值。

带数据类型转换的计算

下面是数据转换的更复杂的实例,显示开发工具包如何计算两个给定日期间的天数:

d1                := {1,1,1990}: DATE; 
d2                := $Today; 
daysBetween        = {d2}: INTEGER - {d1}: INTEGER; 

要完成此操作,开发工具包使用存储在{d1}{d2}中的日期值,把它们转换为其阳历值,并用这些值相减。

此例假定{d1}和{d2}是日期变量,变量 daysBetween 是整数。

赋值错误

开发工具包是强类型语言,这意味着如果把一个类型的变量赋值给另一类型的变量,会出现错误。

例如,如果假定 entryDate 是日期变量,startTime 是时间变量,则下列赋值操作产生运行时错误:

entryDate := startTime; 

自动类型转换

开发工具包自动转换整数和实数。例如,假使变量 i 是整数,则语句

i := 37.0; 

把 37 赋值给 i 变量,不需显式类型转换。
同样,如果 r 是实数,语句

r := i; 

把 37.0 赋值给 r 变量。

知道赋值时,总把混合表达式作为实数处理,这样可以保持精度。

而且,当需要时,开发工具包自动把所有数据类型转换为字符串。例如,语句:

s := i; 

把字符串值 37 赋值给 s 变量。

带简单数据类型的字符串表达式

字符串表达式函数

开发工具包中的字符串是由单引号括起来的一系列字符。开发工具包提供字符串处理运算符和语句,使用户可执行操作以:

运算符和语句

在下述列表中总结字符串运算符和语句。

整数和实数表达式

算术表达式和运算符

开发工具包支持算术表达式和运算符,于下表中总结。

运算符 说明
+ 把两个数字表达式相加(i:=3+5)
- 从一个数字表达式中减去另一个数字表达式(r:=3.7-2.0)
* 把两个数字表达式相乘(i:=3.0*6)
/ 把两个数字表达式相除(r:=3.0/4.0)
MOD 当一个整数被另一个整数除时,计算余数(6 MOD 4=2)

附加的运算符

除了这些运算符,开发工具包支持下列函数:

三角函数 对数函数 指数函数
Sin Log Exp
Cos Ln Power
Tan Sqrt n/a
ACos n/a n/a
ASin n/a n/a
ATan n/a n/a
CosH n/a n/a
SinH n/a n/a
TanH n/a n/a


布尔表达式

逻辑运算符

可使用逻辑运算符 AND、OR 和 NOT 来创建复杂的布尔表达式,如:

b := (i > 0) AND (j = 0); 

开发工具包执行短路布尔判定。这种判定形式保证对布尔表达式只判定到可确定其值的地方。

在上面的实例中,如果 i 是 0,在判定 j 前,确定 b 变量的值为 FALSE。规则如下:

关系运算符

开发工具包提供下列关系运算符,供在布尔表达式中使用。

运算符 说明
< 小于
<= 小于或等于
> 大于
>= 大于或等于
= 等于
<> 不等于

注:当比较两个字符串时,上面列出的运算符忽略大小写。这意味着下列表达式是 TRUE:

'F:\MYFILE' = 'f:\myfile' 

区分大小写的运算符

下列运算符用于区分大小写的字符串比较。

运算符 说明
<< 小于
<<== 小于或等于
>> 大于
>>== 大于或等于
== 等于
<<>> 不等于

参考页面上的注,获取实例。

日期表达式

虽然被认为是简单数据类型,但是日期值使用不可见结构,该结构使用户能获得月、日和年值。使用加点的表示法,如下例所示。

dayValue := $Today.day; 
monthValue := $Today.month; 
yearValue := $Today.year; 
(* $Today 是系统日期*) 

如上例所示,任何日期表达式后面可跟一个点和一个关键字(day、month 或 year),他用来访问日期的相应值。在上面的实例中,dayValuemonthValueyearValue 是整数变量。

更改日期变量

用户可更改日期变量的月、日或年值,如下所示:

d := $Today; 
d.year := d.year + 1; 

在上面实例中,把当前系统日期值赋值给日期变量(d)。d 的年值增加一。

开发工具包保证用户不使用无效日期。在下面实例中,日期变量使用“2/1/1999”(而不是“1/32/1999”):

d := {1,31,1999}: DATE; 
d.day := d.day + 1; 

计算日期间隔

开发工具包提供 DateDif 函数,来以月、日或年计算两个日期间的间隔。

DateDif 需要三个自变量:

例如:

    age := DateDif($Today,birthDate,$Years);


时间表达式

开发工具包提供几个工具,使用户可以操纵时间表达式。像日期一样,时间包括多个值:小时、分钟和秒。

可使用加点表示法(在日期中也这样用)来访问时间值的不同部分:

currentHour   := $Now.hour; 
currentMinute := $Now.minute; 
currentSecond := $Now.second; 
(* $Now 是系统时间*)

更改时间变量

用户也可更改时间变量的特定部分:

t      := $Now; 
t.hour := t.hour + 3; 

时间变量(t)包括的时间值距现在三小时。时间值使用内部 24 小时格式,可以表示半夜。下例的结果是 t 包括值{1,0,0}:TIME,即凌晨 1 点:

t := {23,0,0}: TIME; 
t.hour := t.hour + 2; 

计算时间间隔

开发工具包提供 TimeDif 函数,计算两个时间之间的间隔。下例以小时、分钟和秒计算当前时间和前一时间 startTime 之间时间间隔:

hoursDiff := TimeDif($Now,startTime,$Hours); 
minutesDiff := TimeDif($Now,startTime,$Minutes); 
secondsDiff := TimeDif($Now,startTime,$Seconds); 

数组

数组是相同数据类型的数据值列表。它也是一种结构化数据类型。结构化数据类型允许对数据执行特定的操作。

数组名后跟下标表达式组成的表达式可引用数组中的任何单个元素(数据值)。数组中的元素是有顺序的,从一(1)开始。要访问特定的元素,使用值,或下标。

在下例中,每个下标由中括号括起来:

VARIABLES
  name[10]: ARRAY OF String; 
ACTIONS 
  name[1] := 'Tom'; 
  name[2] := 'Dick'; 
  name[3] := 'Harry'; 

在此实例中,name 是字符串数组。name 变量可保存最多十个字符串值,放在标号 1 到 10 的元素中。

访问数组

一般用变量访问数组。下例显示如何使用整数变量 i 访问给定数组元素,把 name 数组的所有十个值写入文件:

FOR i := 1 TO 10 DO 
  FWriteLN(outputFile,name[i]); 
END; 

试图在定义的数组界限之外访问数组元素,会导致出现运行时错误消息。这些语句都会产生错误:

name[-1] := 'Dick'; 
name[45] := 'Harry';

作为数组的字符串

可把字符串值当作字符数组处理。在下列代码实例的结束后,s 变量的值是 G:\EADVISOR\ADVISOR\DATA。

VARIABLES
  s : STRING; 
ACTIONS 
  s := 'F:\EADVISOR\ADVISOR\DATA';
  s[1] := 'G'; 

改变数组大小

开发工具包数组可动态改变大小。即在运行时可更改数组大小。开发工具包语句 SetArrayLength 用来更改任何数组的大小。例如:

SetArrayLength(name,100);

给前面说明的十槽数组增加 90 个新元素。前十槽中的信息不受影响。也可减小数组的大小,如下例所示:

SetArrayLength(name,5); 

在这种情况下,会丢失 6 到 10 槽中的任何值。

列表

与数组类似,开发工具包列表是结构化数据类型,可包括相同类型的多个值。使用方括号括住的整数,可为列表标下标。

列表的优势

使用开发工具包,用户不需要地址、内存分配或内存释放以创建完全链接表结构。列表比数组更容易改变大小。用户还可以在列表中间插入新值,这在数组中很费事。

使用列表

下例显示如何说明和使用列表:

VARIABLES 
  name: List of String; 
ACTIONS 
  ListInsert(name,'Tom'); 
  ListInsert(name,'Dick'); 
  ListInsert(name,'Harry'); 

此代码实例结束时,name 列表包括三个值:'Tom'、'Dick'和'Harry'。

列表指针

每个列表有一个指针,指示列表中的当前元素。这称为列表指针。当把新元素插入列表时,列表指针指示新插入的元素。在前面实例结束处,当前指针指向'Harry'。

下一个实例显示如何在前面列表的中部插入新元素。

ListSetPos(name,1); 
ListInsert(name,'Ellen'); 

Name 现在包括四个值:'Tom'、'Ellen'、'Dick'和'Harry'。

注:'Ellen'在第二个位置是因为 $ListInsert 缺省情况是 $After。列表指针指向'Ellen'。ListSetPos 把列表指针移到给定元素。

其它列表函数

开发工具包提供许多其它函数,使用户可操纵列表。

函数 说明
ListDelete 从列表删除元素。(List Delete(name,2)从前面实例中删除'Ellen')。
ListLength 返回列表中的元素数。
ListNext 在列表中把指针移到下一个元素。
ListPrev 在列表中把指针移到前一个元素。
ListPos 返回当前元素的下标。
ListFind 扫描列表,查找给定值。如果找到该值,返回 TRUE。列表指针移到匹配值。例如,ListFind(name, 'Dick')返回 TRUE 并把当前指针移到'Dick'。
ListSort 按升序排序列表。
ListPush 向列表的前面添加新元素。
ListPop 删除列表中的第一个元素并返回它。

因为列表可像数组一样标下标,语句,

s:= name[1];

把值'Tom'赋给 s 变量。

FOR 循环

开发工具包为列表提供特殊循环结构。FOR 语句可用来重复列表中的值。嵌套在 FOR...END 块中的语句为列表中的每个元素执行一次。列表指针总指向列表中的第一个数。循环每执行一遍,列表中的当前项增加一。

下例显示 FOR 语句的使用:

FOR name DO 
  FWriteLN(outputFile,name[$Current]); 
END; 

特殊列表常量

前面的实例也显示名为 $Current 的特殊常量的使用。此常量可用来访问列表的当前元素。其它列表常量包括:

这些常量分别用来访问列表的第一个和最后一个元素。例如:

FWriteLN(outputFile,name[$First]); 
FWriteLN(outputFile,name[$Last]); 

这两行把"Tom"和"Harry"写到输出文件。

列表碎片

很多开发工具包语句支持自动列表“碎片”。在列表碎片中,语句接受给定类型的单个项或项的列表。

如果传送一列表,则语句作用于列表中的所有元素。这也称作带隐含 FOR 循环的语句。

WinWriteLN 是这种语句的一个例子:

WinWriteLN(myWindow,name); 

此语句把变量 name 的每个值写到名为 myWindow 的窗口。有几个 Window 语句和 SQL 语句支持列表碎片。

记录

数组和列表可保存类型相同的多个值,与它们不同,记录可保存类型不同的多个值。

说明记录变量

说明记录类型变量有两步:

注:当说明记录类型变量时,用户用自己的数据类型扩展开发工具包语言。

变量代码实例

阅读下列代码实例:

TYPES 
EmployeeRecord IS RECORD 
      first_name, last_name: String; 
      age : Integer; 
      salary : Real; 
      married : Boolean; 
      hireDate : Date; 
      startTime, stopTime : Time; 
END; 
VARIABLES 
  employee: EmployeeRecord; 

前面实例说明名为 EmployeeRecord 的新记录类型。此记录包括八个字段,每个字段是简单数据类型。

引用变量字段

像使用日期和时间一样,用户可使用<变量>.<字段>(加点) 表示法来引用记录中的任何字段。
例如,下列语句可用来初始化前面说明的 employee 变量:

employee.first_name := 'Calbert'; 
employee.last_name  := 'Chaney'; 
employee.age        := 21; 
employee.salary     := 2500000.0; 
employee.married    := FALSE; 
employee.hireDate   := {2,15,1993}: DATE; 
employee.startTime  := {8,30,0}: TIME; 
employee.stopTime   := {17,30,0}: TIME; 

赋值兼容变量

相同记录类型的变量是赋值兼容的。如果说明变量(employee2) 为 EmployeeRecord 类型,添加下列语句会使 employee 变量的所有字段复制到 employee2 变量:

employee2 := employee; 

用户也可创建记录的列表和数组:

employeeList: List Of EmployeeRecord; 

记录说明可包括数组、列表和其它记录。例如,可用下列方法更改 EmployeeRecord 说明:

EmployeeRecord IS RECORD 
      first_name, last_name: String;
      age : Integer; 
      salary : Real; 
      married : Boolean; 
      hireDate : Date; 
      startTime, stopTime : Time; 
      manages : List of String;
END; 

manages 值可用来记录由给定员工管理的员工姓名。

输入和输出语句

开发工具包提供几个语句,执行数据库记录输入和输出。

例如,下列语句可用来把 EMPLOYEES 表的一行装载到前面说明的 employee 变量:

SQLSelectInto('SELECT * FROM EMPLOYEES WHERE
    EMPLOYEE_ID=105',employee); 

开发工具包:

类似的,开发工具包允许用户把记录中的字段映射到表单。完成表单后用户按 ENTER 键时,屏幕上的信息保存到记录的相应字段,用户可以检查和操纵记录。

用户定义数据类型

除了记录,用户可创建其它用户定义类型。用户定义类型是在程序中定义的数据类型,它通常由数据类型的组合组成。用户定义类型经常用来创建数据结构。

对于在变量说明中使用的列表、数组、记录和简单数据类型的任意组合,可在数据类型说明中可给它一个重复使用的名称。例如,用户可定义一个新的数据类型,如下例所示:

TYPES 
StringList = LIST OF STRING; 

一旦说明后,用户就可使用 StringList 可用 LIST OF STRING 来说明变量。

赋值兼容性

下列规则涉及用户定义数据类型和结构化数据类型的赋值兼容性。

当在两个变量或表达式之间检查赋值兼容性时,开发工具包只检查类型名称是否匹配。它不检查记录说明是否一样。

初始化变量

初始化一个已说明的变量意味着给它赋初始值。在说明变量时,开发工具包允许用户初始化变量,如下例所示:

VARIABLES 
 i {1}                                : INTEGER; 
 s {'F:\MYFILE'}                      : STRING; 
 d {2,11,1956}                        : DATE; 
 l {'Tom','Dick','Harry'}             : LIST OF STRING;
 r {'Steve','Wantz',32,189000.00,TRUE,
   {3,30,1986}                        : DATE, 
   {6,30,0}                           : TIME,
   {4,30,0}                           : TIME,
   {'Tom','Dick','Harry'} : LIST OF STRING :
    EmployeeRecord; 

变量约定

一般情况下,变量名后面是:

对于像列表、数组和记录这样的结构化类型的变量,可用同样的方法初始化。

注意初始值化与变量相关联,而与类型无关。所以在下列行中,

VARIABLES 
  i, j {27}: INTEGER; 

只初始化了 j 变量;未初始化 i 变量。每个变量必须单独初始化。

$Unknown 值

在开发工具包中没有赋值的所有未初始化的变量都以值 $Unknown 开始。这一点不同于 C 和 Pascal,它们的变量以随机值开始。

把所有变量初始化为 0、1或空字符串防止公共错误。例如,如果在下行:

newSalary := oldSalary*1.05; 

未把变量 oldSalary 初始化为非 $Unknown 值,运行时间会发生错误,因为 1.05 会与 $Unknown 相乘。


Tivoli 服务台 6.0 开发工具包脚本程序设计指南

返回目录

版权所有