白金会员
已认证
XRD软件HighScore的Plus功能模块(即HighScore Plus)里包含了对脚本代码的支持;基于脚本的扩展性,软件也有了更大的可能让用户得以实现一些特殊的计算或自定义特定格式的结果输出,以补足原软件在设计时未预见未直接包含的功能。本文介绍了HighScore Plus的脚本编程语言的编辑方法以及开发环境,为研究者实现个性化的计算和结果提供指导。
HighScore Plus脚本所使用的语言是Object Pascal,继承自相对古老的Pascal编程语言,支持结构化和面向对象编程。它的优点包括代码的易读性、快速编译,以及支持多个单元文件从而实现模块化编程。作为已经不再流行的编程语言,可能在图书馆里才能翻得到它的出版教程了,但网络上依然保留了不少资源。Neil Moffatt的Delphi Basic、Marco Cantù的Essential Pascal(中文)和Tao Yue的Learn Pascal tutorial(Wiki化后的中文版)都可以给初学者提供不少帮助。
HighScore Plus软件里甚至内置了一个集成开发环境(IDE,Integrated Development Environment ),可以由菜单Tools - Script Editor调出,麻雀虽小五脏俱全,可以直接编辑、编译和调试代码。软件帮助系统的第11部分中罗列了HighScore Plus软件开放的可调用的对象模型及它们的属性、函数和过程。软件安装目录下的HelpExternals子目录下也放了不少.PAS的示例代码文件,可用于参考和学习;Documentation子目录下的Scripting in HighScore Plus.pdf文件中也举了大量的例子来告诉你如何实现某些功能。
本文的编写也参考了上述的文件和网络资源。
图1 HighScore Plus中内置的脚本编辑器
01丨程序结构
如下图,Pascal程序的基本结构由三部分组成:
图2 Pascal程序基本结构
程序首部:
以关键字program开头,用以标识这是一个程序;其后便是由用户自己定义的程序名称ExampleProgram;以半角分号(;)作为这一部分的结束。
声明部分:
声明部分可以省略,但凡是在程序中用到所有变量、常量、数组及自定义的数据类型、过程与函数等都必须在声明部分预先定义,也就是说,不允许不声明就使用;声明部分中可以包含:
使用指令:以关键字uses开头,指定要在程序中引用的单元(相当于模块),以便在程序中使用在单元中定义好的过程、函数和类等等;一般System单元不用特地声明引用;如程序中不需要引用额外的单元,此部分可省略;
类型声明:以关键字type开头,基于已有数据类型构建自定义的数据类型,以在程序中使用;如没有自定义新数据类型的必要,此部分可省略;
常量声明:以关键字const开头,定义在程序中会使用到的常量;如无必要可省略;
变量声明:以关键字var开头,定义在程序中会使用到的变量;如果程序中用不到自定义的变量,此部分可以省略;
子过程、子函数定义;如无必要可省略;
程序主体:
程序主体由begin开始,end.(注意,不要遗漏这个点符)结束,两者中间则是执行语句。
Pascal程序代码不管哪一部分,语句末尾都必须有半角分号(;)以示这一语句的结束,但允许end前面的那一个语句省略分号;多个语句可以用一对begin和end;(注意,这里有半角分号)包含起来作为一个程序块,程序块多用于子过程、子函数等的定义以及流程语句;代码里最后一个end后的点符(.)代表整个程序的结束。
Pascal语言中,程序名称、常量名称、变量名称等这种自定义的名称统称为标识符。标识符必须以一个英文字母或者下划线(_)开始,后面可以是英文字母、数字或下划线,长度不限;但不能与Pascal语言已占用的有特殊含义的关键字/保留字(如program)相同。标识符以及关键字都不区分大小写,因此exampleprogram、ExampleProgram、EXAMPLEPROGRAM和eXaMpLePrOgRaM这几个名称都是相同的,但为了代码的可读性,建议遵循一定的命名书写规范,有意义地使用大小写。
在图2中可以看到,在脚本编辑器默认的代码高亮规则下,部分代码以绿色斜体显示,这些是不被编译也不被执行的注释。注释同样是代码的一部分,主要用来写一些说明,以让代码更容易理解,也可以用来在不删除的情况下屏蔽有问题的代码。Pascal语言支持三种注释方式:一对半角大括号({ })、一对带星号的半角小括号((* *))以及双斜线(//)。
图3 注释
在HighScore Plus的脚本编辑器中,当点开工具栏中第一个按钮并点击New Script项新建一个脚本时,在Script Name框中输入的脚本名称同时默认为程序名称;输完名称后,点击OK按钮,即会新建一个完整结构的空白的脚本。
图4 新建脚本
02丨数据类型及赋值、运算
Pascal语言中包含了以下基本数据类型:
整数类型:最基础的是integer类型,其数据范围一般情况下已足够使用,如果需要更大的整数范围,可以用longint类型甚至int64类型;
实数类型:也称浮点数型,最基础的是real类型,但不提倡用,建议用single单精度实型或double双精度实型,要更大范围得话,还可以用extended扩展实型;
字符类型:最基础的是char类型,即ASCII字符,一般用一对半角单引号将单个字符括起来,如‘a‘、‘@’等(注:半角单引号需多用一个单引号转义,即’’’’),也可以用井号加0~255以内的整数表示第几个ASCII字符,如#65即为‘A’;双字节的Unicode字符可以用widechar类型来支持;多个字符组成的字符串则可以用string类型;
布尔类型:最基础的是boolean类型,只有TRUE(真,值为1)和FALSE(假,值为0)两个值;
常量的赋值直接在声明部分中声明常量的同时完成,而且不必特别指定其数据类型,编译器会根据所赋的值自动选用合适的数据类型;赋值时,直接用等号(=)赋值;赋值后,在程序中可以用常量的标识符来使用其值,但无法修改其值。对于一个在程序中到处会用到,而且程序运行中保持不变的值,建议用常量来存储,然后在执行代码中使用这个常量的标识符,这样当要改这个值时,就不用到执行代码中到处查找这个值然后修改,而是可以轻松地直接在常量声明中修改一次就成。
图5 常量的声明与赋值
变量的值在程序运行的过程中可以更改,但使用前必须先声明好。在程序的声明部分中声明的变量称为全程变量,可以在整个程序(包括子过程、子函数中)中使用;在子过程、子函数中声明的变量,称为局部变量,只能在声明它的子过程或子函数中使用。变量一般在执行语句中用赋值符(带半角冒号的等号,即:=)赋值;全程变量也可以在声明的同时用等号(=)赋初值,但不建议这么做。在声明变量时,必须用半角冒号(:)指定变量的数据类型;不赋初值的情况下,一个语句可以声明同一类型的多个变量,这些变量的标识符须用半角逗号(,)分隔开。
图6 变量的声明与赋值
一般的工作可能前面所讲的那些数据类型已经足够使用了,但涉及到相对复杂的、要处理大量数据的工作时,通过定义很多个变量去实现很显然不太现实,此时对于同一类型的大量数据,就可以用数组来处理。
数组可以通过“array[下标范围] of 数据类型”来定义,其中下标值一般是整数类型。[下标范围]可以省略:定义时省略了[下标范围]的数组称为动态数组,使用前必须先用函数setlength设置其大小,设置后,动态数组的下标总是从零开始;定义时指定了下标范围的数组称为静态数组,下标范围可以按需要设置,以[下标下届..下标上届](用两个半角点符隔开,相当于从几到几的连续整数)的格式定义,下标值甚至可以是负数;如果要定义多维数组,可以通过套娃的方式定义,也可以在[ ]里定义多组下标范围。当声明了一个数组变量,则该数组变量中的各个元素就共用一个数组名(即该数组变量标识符),通过下标的不同以区别不同的元素,可以通过“数组名[下标]”来引用数组元素;对数组的操作归根到底就是对数组元素的操作,数组元素可以像同类型的普通变量那样操作。
图7 数组的声明与赋值
上图中第30行中的“[true, true, true, true, true, false, false]”是一个直接常量(直接以字面形式,而非标识符表示的常量,如前面附图中赋值语句等号右侧的那些数值或字符,2.7182818、10086、true、’A’ 等)数组,用一对半角方括号([ ])将各元素括在其中,元素之间用半角逗号(,)分隔。
变量在赋值时,赋值号的右侧除了用直接常量外,也可以是一个运算表达式,运算表达式中可以带有变量或常量。
数字的计算使用算术运算符,除了常规的四则运算:加(+)、减(-)、乘(*)、除(/)外,还有整除(div)和取模(除法取余数,mod);运算时,先乘除(整除和取模和乘除同一优先级)后加减,当然括号优先级最高(由内向外逐层降低),相同优先级则从左往右顺序计算;
图8 数字的算数运算
关系运算符(=、<>、>、<、>=、<=)则可以用来判断两个数之间的大小关系,其结果是布尔类型;关系运算符的优先级是最低的;
图9 数字的大小比较
逻辑运算符则用来处理布尔类型的量,包含:not(非,只有一个运算对象,结果取运算对象的相反值)、and(且,只有两边都为真,结果才为真)、or(或,两边有一个真,则结果就为真)、xor(异或,两边不一样,则结果为真);not优先级最高,其次是and,与乘除同一级别, or和xor则与加减并列;
图10 布尔值的逻辑运算
对于字符(串),有连接运算符(加号,+)用来将两边的字符(串)连成一个字符串;关系运算符也可以用于字符串的比较,比较时,两个字符串从左往右按ASCII码值逐个比较,遇到不相等时,码值大的字符所在的字符串为大,因此小写字母>大写字母>数字。
图11 字符(串)的运算
除上述数据类型外,还有枚举、集合(图5中声明的常量Letters就是一个点亮大小写字母的52个字符的集合)、记录、指针、文件、类等等类型,本文中不再赘述,感兴趣的可以参考Essential Pascal、Delphi Basics、Learn Pascal tutorial等网络资源中的说明。