pml基础手册与总结
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
PML开发介绍与总结
1 pml语言简介 (2)
1.1 pml变量 (2)
1.2 变量类型 (2)
1.3 自定义变量类型 (3)
1.4 定义变量 (3)
1.5 函数(Function)和方法(Method) (4)
1.6 使用ANY类型的变量作为函数参数 (5)
1.7 变量的方法 (6)
1.8 自定义变量类型的方法 (7)
1.9 方法的重载 (8)
1.10 Unset和Undefined (9)
1.11 删除变量 (10)
2 Pml的一些特点 (10)
3 Pml表达式 (11)
4 pml流程控制 (11)
4.1选择结构 (12)
4.2 do循环 (13)
4.3 GoLabel跳转语句 (14)
5 pml数组 (15)
5.1 定义数组 (15)
5.2 数组的赋值 (15)
5.3 多维数组 (15)
5.4 数组的方法 (16)
5.5 利用数组进行字符串处理 (17)
5.6 数组排序 (18)
5.7 Do values循环和Do indices循环访问数组变量 (19)
6 pml宏文件概念及其运行 (19)
6.1 概念 (19)
6.2 带参数的宏文件 (20)
语言简介介
1pml语言简
pml是用于pdms二次开发的面向对象的编程语言,它的面向对象属性是与其他脚本语言的最大区别,也是现代高级语言的基本特征。
pml提供了编辑窗体和菜单的功能,且语法简单方便,使得pml能实现高级语言的大部分功能,用户可以开发自己的菜单窗体,完成需求定制。
pml提供了大量的变量类型(object type)及与变量类型相对应的方法(method)。
pml 提供的方法实用,具有针对性。
比如数组(Array object)可以存放不同的数据类型,可以进行排序、清空没有赋值的元素、查找、删除等等方法,这是大多数高级语言没有提供的功能。
1.1pml变量
对于pml语言,每个变量即是一个object,对应一个变量类型object type。
不同类型的变量只能保存对应类型的数据。
pml变量的特点:
变量名称唯一,且不能重复。
每个object type即是一个类(class),有属于类的通用的方法和属性。
因此每个pml 的变量(object)都可以调用所属类的方法。
每个变量对应一个变量类型,在定义变量前,对应的变量类型必须存在。
1.2变量类型
Pml的变量类型比较多,可以分为三类,built-in、system-defined、user-defined。
Built-in变量类型包括以下几种:
字符串
实数
布尔
数组
system-defined变量类型包括Direction,Position,Orientation等多种类型,详细信息可以参考手册。
user-defined变量类型是指用户自定义的类型。
1.3自定义变量类型
Pml提供的变量类型可以满足大部分情况的使用,如果有需要,用户也可以定义自己的变量类型。
下面是一个自定义变量类型的示例。
define object FACTORY
member .Name is STRING
member .Workers is REAL
member .Output is REAL
endobject
自定义变量类型的名称是FACTORY,该变量类型有3个成员(member),分别是
Name,Workers和Output。
任意一个FACTORY类型的pml变量都默认有这3个成员。
比如设变量!MyFactory是FACTORY类型,则可以通过!访问或赋值变量的Name成员,如下面的表达式分别读取和设置了变量!MyFactory的Name属性,!FactoryName = !
! = ‘APPLE’
Pml对成员的类型没有限制,自定义变量类型的变量也可以作为成员,如下例,成员Site 的类型是FACTORY。
define object PRODUCT
member .Code is STRING
member .Total is REAL
member .Site is FACTORY
endobject
为了方便区分,变量类型一般用大写表示,变量一般首字母大写。
自定义变量类型一般以变量类型的名称为文件名(字母必须是小写),以.pmlobj为后缀保存到PMLLIB文件夹下面。
程序会自动加载定义文件。
1.4定义变量
Pml的变量分为全局变量(global)和局部变量(local)两种,全局变量在整个程序运行期间一直存在,而局部变量只在所在的宏文件或函数内有效。
比如一个宏文件包含下面的语句,
!Y = 3
!!X = 5
$p $!Y $!!X
运行后得到结果 3 5
运行完成后在pdms中分别查询变量!Y和!!X,!Y是Undefined,而!!X是实数类型变量,值是5。
因为!Y是局部变量,宏文件运行完成后自动释放。
Pml变量名的最大允许长度是16个字符(包含前面的符号!),变量名必须以字母开头,可以是字母和数字的组合。
确定变量名时要简单易懂、避免重复,可以添加自定义的前缀进行区分。
在编写程序时,为了避免重复和减少资源占用,应该尽量减少使用全局变量,使用!!CD为前缀的变量是系统预留的全局变量,在定义变量时要避免重复。
定义一个built-in类型变量(REAL,STRING,BOOL,ARRAY)可以通过直接赋值确定其变量类型,比如!MyVariable = 2,则变量! MyVariable会自动根据所赋值的类型确定为real 类型,不用另外指定变量类型。
当定义一个值为空的变量时,可以采用如下的方
式!MyVariable2 = STRING(),指定!MyVariable的类型为字符串,而值为空(UNSET)。
对应其他类型变量的定义需采用下面的形式,!MyVariable3 = object DIRECTION()
和方法((Method)
1.5函数
函数((Function)和方法
函数一般定义在一个单独的文件中,文件名必须是小写的函数名称,后缀为.pmlfnc。
函数定义文件一般存放在PMLLIB文件夹中。
每个函数定义文件只能包含一个函数,且文件的第一行必须是define function开头。
所有的用户自定义函数都是global类型变量。
函数和方法类似,都可以带有参数和指定返回值。
参数和返回值的类型必须在函数和方法定义时指定,当在主程序中调用函数或方法时必须把对应类型的值传递给函数或方法,经过处理后把返回值传递给主程序。
下面的语句定义了一个函数!!Area
Define Function !!Area( !Length is REAL, !Width is REAL ) is REAL
!Area = !Length * !Width
Return !Area
EndFunction
!!Area的功能是根据主程序传递过来的参数!Length和!Width计算矩形面积并将面积返回主程序。
参数!Length、!Width 和返回值都是REAL类型,返回值用关键词Return指定,
最后以endfunction结束函数定义。
一般在表达式中调用有返回值的函数,如:!MyLength = 15
!MyWidth = 10
!MyArea = !!Area(!MyLength, !MyWidth)
则得到!MyArea = 150,注意参数的顺序不能颠倒,否则可能会导致错误。
上面的语句也可以简化为!MyArea = !!Area(15, 10)
函数也可以用参数的方式返回运行结果(没有返回值的函数称为PML Procedure,用Call 关键词调用),即在调用函数前定义一个变量,并把变量包含在函数的参数列表里。
如下面的例子,
Define Function !!LengthAndTrim(!Name is STRING, !Length is REAL)
!Name = !Name.Trim()
!Length = !Name.Length()
EndFunction
函数的功能是计算字符串变量!Name的长度(去掉前后空格),REAL类型参数!Length 用于存放并返回计算结果。
函数的调用过程如下,
!Name = ' FRED '
!Length = REAL()
Call !!LengthAndTrim(' FRED ', !Length)
运行完后,字符串长度的计算结果存放在了变量!Length中。
注意,必须是一个变量存放返回的计算结果,不能是常量,如!!LengthAndTrim(' FRED ', 2)是错误的,因为函数不能修改一个常数。
对于特殊的情况,当函数或Procedure没有参数时,函数名后面的括号也必须保留,如Define Function !!LengthAndTrim()。
对有返回值的函数也可以采用Call关键词调用,但会由于无法保存而导致返回值丢失。
1.6使用ANY类型的变量作为函数参数
某些特殊情况下,可以指定函数的参数或返回值的类型为ANY,即可以接受任何类型的变量。
如下面的例子定义参数!Argument为ANY类型。
Define Function !!Print(!Argument is ANY)
$P $!Argument
在使用ANY类型的变量前需要确定变量的具体类型,可以使用变量的pmlobjectType()方法如下。
Define Function !!AnyType(!Argument is ANY)
Type = !Argument.pmlobjectType()
if ( !Type EQ 'STRING' ) then
- - do something with a STRING
elseif ( !Type EQ 'REAL' ) then
- - do something with a REAL
elseif ( !Type EQ 'DBREF' ) then
- - do something with a DB Reference
else
- - do something with all other types or give an error
endif
EndFunction
1.7变量的方法
方法是与具体的变量类型相对应、且可以由任意一个变量调用的函数。
每种变量类型包含的方法可以参考手册。
下面以STRING类型为例说明如何使用变量的方法。
!Mystring = STRING() 定义一个STRING类型的变量
截取部分字符,取指定的字符串右侧的剩余部分赋值给新变量
!Mystring ='Iwanttolearnenglish'
!newstring = !Mystring.after('Iw')
则!newstring = 'anttolearnenglish'
同理可以调用before()方法取指定字符串左侧的部分。
计算字符串的长度
!Mystring ='Iwanttolearnenglish'
!length = !Mystring.length()
转为小写
!Mystring ='ENGLISH'
!lowercase = !Mystring.lowcase()
!lowercase = ‘englis’
替换部分字符串
!Mystring ='ENGLISH'
!NewString = !Mystring.Replace('E','LearnE')
!NewString = 'LearnENGLISH'
1.8自定义变量类型的方法
对应自定义的变量类型,可以同时定义变量类型的方法,写在同一个文件中变量类型定义结束之后(endobject语句之后)。
方法定义时以!this代表当前object,并用其调用object的方法(method)和成员变量(member)。
define object LIFE
member .Answer is REAL
endobject
define method .Life()
!This.Answer = 42
Endmethod
和变量类型同名且没有参数的方法Life()称为构造方法,在定义该类型的变量时程序会自动调用该方法用于变量的初始化。
变量的方法可以带有返回值,与函数的功能类似,如下面的方法,调用时会返回成员Answer的值。
define method .Answer() IS REAL
return !This.Answer
endmethod
也可以用方法对类成员进行赋值
define method .Answer( !Value Is REAL)
!This.Answer = !Value
endmethod
上面两个方法的调用过程如下,
!Marvin = object LIFE() 定义!Marvin为LIFE类型变量
!Number = !Marvin.Answer() 给!Number赋值为!This.Answer
!Marvin.Answer(40) !This.Answer的值设为40
!Number = !Marvin.Answer() !Number赋值为40
创建新的自定义变量类型后,需要输入pml reload object objectname 加载定义文件后,才能正常使用自定义的变量类型。
1.9方法的重载
重载是指同一个变量类型的两个或多个方法具有相同的方法名称和不同的参数列表,在进行调用时,程序会根据传递的参数类型和数量自动匹配对应的方法。
如下面两个方法,
define method .mymethod( !Value Is REAL)
$p ‘It is a real number’
Endmethod
define method .mymethod( !Value Is STRING)
$p ‘It is a string’
Endmethod
调用时,若输出的参数时REAL类型,则打印It is a real number,若参数是STRING类型,则打印It is a string。
当添加新的方法后,需要输入pml reload object objectname进行重新加载,以便程序加载最新的定义。
1.10Unset和Undefined
变量类型都有一个string()方法,即把当前变量类型转为一个字符串。
!X = 2.5
!S = !X.String()
变量!S是字符串类型,值为’2.5’
对于空值的情况,调用String()方法后,得到值如下
!X = REAL()
!S = !X.String() !S为空
!X = BOOLEAN()
!S = !X.String() !S为空
!X = STRING()
!S = !X.String() !S为‘Unset’
!X = ARRAY()
!S = !X.String() !S为‘ARRAY’
UNSET是指已经定义的变量,但还没有给变量赋值。
程序编写时经常需要预先对变量进行判断是否为UNSET,可以用函数和自带的方法两种方式进行判断。
Functions Methods
if ( Unset(!X) ) then if ( !X.Unset() ) then
if ( Set(!X) ) then if ( !X.Set() ) then
Undefined是指还没有定义的变量,即系统中不存在。
可以用下面的函数进行判断if ( Undefined(!!Y) ) then
if ( Defined(!!Y) ) then
1.11 删除变量
删除一个已定义的变量可以调用delete()方法,
!X.delete() 即删除了变量!X
2Pml的一些特点
宏、函数和方法都是pml命令的集合,但在写程序时应尽量的使用函数和方法,因为函数和方法可以方便的包含任意类型的参数,且可以有返回值,使得程序的整体性和可读性比较好,同时符合面向对象编程语言的特点。
Pml文件的注释语句分三种。
用符号”--”开头的是注释行;写在pml语句末尾且同行的注释用$* 开头;多行注释用$( 开头,用$) 结尾。
Return命令用于立即停止当前的pml文件,返回上一层的文件继续执行。
Pml文件一般以Return语句结尾。
Pml语言不区分大小写,IF和if具有相同的作用。
但对于字符串中的字符,需要对大小写进行区分。
Pml命令可以进行简写,如POSITION可以简写为POS。
但为了程序的可读性和避免混淆,一般不建议这样做。
特殊字符$。
$与其他字符的组合表示特别的含义,如$p表示打印。
当pml语句中需要$字符时,需要输入$$。
另外,$也是续行的标识符。
Pml中的字符串表示方法。
可以用单引号或竖杠表示,如'ENGLISH',|ENGLISH|。
Pml文件的类型。
.pmlobj 变量类型定义文件
.pmlfnc 函数定义文件
.pmlfrm 窗体定义文件
PDMS程序启动时,会根据依次加载文件pml.index(在PMLLIB文件夹下)中指定路径下的文件。
如果在程序运行过程中,在已有的路径下添加了新的文件,则需要输入命令pml rehash 加载新文件。
如果其他用户已经更新了pml.index,则只需要
输入pml index。
Pml rehash all命令用于重新扫描PMLLIB路径下的所有pml文件,并同时更新文件pml.index。
查询指定文件路径的方法,q var !!PML.getpathname( 'filename.pmlobj' )
3Pml表达式
常见的数值运算符有+ - * /,逻辑运算符有GT LT EQ 等。
一个表达式里的变量类型比较匹配,否则会报错。
!X = 22
!X + 'text'
REAL类型和STRING类型不匹配,程序出错。
表达式书写时必须在运算符的前后各留一个空格。
一般情况下,在括号的前后不用留空格,但如果与括号相邻的是一个字符串,则需要与括号之间留一个空格,避免混淆。
运算符的优先级规定如下,由上至下依次降低。
括号用于调整表达式的优先级。
BRACKETS ()
FUNCTIONS
*/
+ -
NE NEQ GT LT GE GEQ LE LEQ
NOT
AND
OR
连接运算符&。
&可以把任意类型的两个变量首先转换为字符串类型,然后把两个变量值前后连接在一起。
!X = 64
!Y = 32
!Z = !X & !Y
则!Z = '6432'
对比之前的pml1版本,pml2更简洁实用,功能也更强大。
可以在表达式中包含对函数的调用,也不用在变量前加$符号。
4pml流程控制
pml流程控制语句包括下面几种,
选择语句(if)
循环语句(do)
跳转语句(golable)
错误处理(handle)
4.1选择结构
Pml中if结构和其他编程语言一样,通过判断表达式的值确定程序的执行路径,if结构可以有多个分支,每个分支对应一个判断条件。
典型结构如下,
If( BoolA ) then
(BoolA为true时执行)
Elseif(BoolB) then
(BoolB为true时执行)
Elseif(BoolC) then
(BoolC为true时执行)
Else
(上面条件都不满足时执行)
Endif
括号内的bool表达式可以是一个bool变量,也可以是一个值为bool变量的表达式。
If 结构中各个分支只能执行一个,即程序在执行完任意一个分支后立即退出选择结构,继续下面的语句。
If结构不支持简写为一行的格式,if() then endif,类似的格式是错误的。
If结构可以嵌套使用,下面的例子是合法的,
If(!num GT 1) then
If(!num GT 5) then
$p ‘good’
Else
$p ‘passed’
Endif
Endif
布尔表达式
布尔表达式的运算符包括EQ、GT、LT等,布尔表达式的运算结果必须是布尔变量(true 或false)。
为了向上兼容,pml支持用字符$和字符串格式的‘TRUE’‘FALSE’组合表达布尔变量,如variable = ‘TRUE’, if($variable)是合法的。
另外,字符串类型的自带方法.boolean()可以把字符格式的’TRUE’ ‘FALSE’转为bool类型。
如,!mystr = ‘true’ 则!mystr.boolean()表示一个bool类型变量。
.boolean()方法可以把所有的非0实数转为
TRUE,把0转为FALSE。
4.2do循环
典型的do循环结构如下,
Do !x From startvalue to endvalue By increment
<pml block>
Enddo
循环变量!x从startvalue按步长increment变化到endvalue,重复执行block中语句。
对于简化形式的循环结构,!x、startvalue、endvalue和increment都可以省略,上面的例子可以简化为
Do
<pml block>
Enddo
简化为这种形式后,pml block中必须有语句在满足一定条件时结束循环,否则会形成无限循环而出错。
循环控制语句:Break、Break if、Skip、Skip if
Break和Break if语句可以用于退出循环的操作,如下面的例子,
do !Number
if (!Number GT 100) then
break
endif
!Result = !Result + !Number
Enddo
当!number值大于100时,会执行break语句退出循环。
其中的if结构也可以替换为break if (!Number GT 100),效果相同。
Skip和skip if语句是在满足一定条件时忽略掉(不执行)skip后面的语句而直接执行下一次循环。
如下例,可以用skip语句忽略掉所有的奇数,只对偶数进行操作。
do !X
!Number = !Sample[!X]
if ((INT(!Number/2) NE (!Number/2)) then
skip
endif
!Result = !Result + !Number
enddo
do !X
!Number = !Sample[!X]
skip if (INT(!Number/2) NE (!Number/2))
!Result = !Result + !Number
Enddo
Do循环的嵌套
do !X From 1 to 10
!Z = ‘’
do !Y From !X to 10
!Z = !Z + ‘ ’ + !Y.string()
Enddo
$p $!Z
Enddo
循环的结果应该打印出如下的数字序列
1 2 3 4 5 6 7 8 9 10
2 3 4 5 6 7 8 9 10
3 4 5 6 7 8 9 10
4 5 6 7 8 9 10
5 6 7 8 9 10
6 7 8 9 10
7 8 9 10
8 9 10
9 10
10
4.3GoLabel跳转语句
Golabel /labelname语句用于跳转到/labelname下一行继续执行。
见下例
do !A
do !B to 3
!C = !A * !B
golabel /finished if (!C GT 100)
!Total = !Total + !C
enddo
enddo
label /finished
$P Total is $!Total
在变量!C大于100时程序跳转到label /finished的下一行继续执行,即跳出了循环体。
但是使用golabel语句不能用循环外面跳转到循环内部,否则程序报错。
5pml数组
5.1定义数组
和其他编程语言的概念一样,pml中数组是可以包含多个元素的object。
数组定义的方式有两种,一种是提前定义,即在使用前首先对数组进行定义,如!X = ARRAY()定义了一个数组!X。
需要注意的是,pml中数组不需要指定类型和数组大小,即可以在同一个数组中存放不同类型的元素也可以任意增加数组元素的数量。
另外一种数组定义方法是在给数组中元素赋值时同时完成数组的定义,即不提前进行定义。
如表达式!NewArray[1] = !NewValue,如果数组!NewArray没有提前定义,则该表达式会自动完成数组的定义,同时给其中第一个元素赋值。
数组在书写时注意数组名和后面的中括号之间不能有空格,pml的变量名不区分大小写,可以用自己喜欢的方式书写,但尽量前后保持统一,方便阅读和检查。
数组名称不能与其他变量名或数组名相同,否则会报错。
5.2数组的赋值
Pml数组赋值时没有顺序限制,也可以不连续赋值,即在赋值的两个元素之间可以有任意多个没有赋值的元素。
如对于数组!X,可以只对!X[1]和!X[10]进行赋值,中间没有赋值的元素认为是不存在的,可以用UNDEFINED方法进行判断。
数组的索引值可以是表达式形式,但表达式的结果必须是一个real类型的数组(pml中没有整型变量)。
Pml数组的索引可以从0开始,但一般从1开始,避免一些混淆。
5.3多维数组
Pml支持多维数组,用两个连续中括号表达第一第二维的索引值,如
!Employee[1][1] = 'Smith'
!Employee[1][2] = 'Samuel'
定义!Employee是一个二维数组,!Employee的第一维的每个个元素可以认为是一个一维数组。
因此上面的定义可以改写为
!Employeename[1] = 'Smith'
!Employeename[2] = 'Samuel'
!Employee[1] = !Employeename
5.4数组的方法
Pml是面向对象的编程语言,因此和其他面向对象的语言(如C#,)一样,每一种变量类型(即class或object)都内置了一系列的属性和方法,用于完成一些通用的操作。
Pml数组的方法完整列表可以参考用户手册。
数组方法可以分为两种,即不改变原数组的方法和改变原数组的方法。
例如获取数组的元素数量!Nelements = !MyArray.Size(),执行后数组的大小会存到变量!Nelements中,而数组!MyArray没有任何变化。
但对于数组的clear()方法,则是进行清除数组所有元素的操作,改变了原数组。
常用的数组方法:
RemoveFrom(),清除指定范围内的元素并赋值给新数组,如下面的例子。
!arrayA[1] = 'sd1'
!arrayA[2] = 'sd2'
!arrayA[3] = 'sd3'
!arrayA[4] = 'sd4'
!arrayA[5] = 'sd5'
!arrayB = !arrayA.removefrom(3,2)
RemoveFrom方法执行完成后,原数组!arrayA和新数组!arrayB均发生了变化,!arrayA的元素列表,
!arrayA [1] = 'sd1'
!arrayA [2] = 'sd2'
!arrayA [3] = 'sd5'
!arrayB的元素列表,
!arrayB [1] = 'sd3'
!arrayB [2] = 'sd4'
Append(),在数组的末尾追加元素
此方法只针对已经存在的数组,否则会报错。
追加的元素是在已定义的索引值最高的元素后添加,如果原数组为空,则Append()方法会将追加的值赋给第一个元素即!MyArray[1] = ‘newvalue’。
需要注意,不是赋值给!MyArray[0]。
Delete(),删除指定位置的元素或删除整个数组
MyArray[n].delete()删除索引位置n的元素
MyArray.delete()删除整个数组
Width(),返回数组元素中类型为字符串的最大字符数
!Mylist[1] = 'sd1'
!Mylist[2] = 'sd2'
!Mylist[3] = 'sd22'
!Mylist[4] = 3322322323
则!Mylist.width()方法返回最大字符串宽度为4
5.5利用数组进行字符串处理
在对文件进行操作时,经常需要处理其中的字符串,要提取其中的数据,经常会用到数组的方法。
Pml的字符串(string)变量提供了split()方法,用于按指定的字符对字符串进行拆分。
如下面的例子。
!Line = '123 456 789'
!ArrayOfFields = !Line.split()
计算结果为
!ArrayOfFields [1] = '123'
!ArrayOfFields [2] = '456'
!ArrayOfFields [3] = '789'
用默认的空格作为分隔符时,字符串前后的空格自动忽略不计。
可以采用空格外的其他字符作为分隔符,如下例,
!Line = '123 ,456 ,,789'
!ArrayOfFields = !Line.split(',')
结果为,
!ArrayOfFields [1] = '123 '
!ArrayOfFields [2] = '456 '
!ArrayOfFields [3] = ''
!ArrayOfFields [4] = '789'
注意1和2元素值后面的空格不能丢。
5.6数组排序
数组提供了sort()方法进行元素升序排序,对于字符类型元素按照ASCII,对于数值类型元素按大小进行排序。
Sort()方法没有返回值,结果是对原数组的修改。
对于需要降序的情况,可以用Invert() 方法对排序后的数组进一步操作,得到降序数组。
另外一种排序的方法是SortedIndices(),即原数组中元素在排序后数组中的索引值,并保存到一个新数组(real类型)中。
如!newposition = !MyArray.SortedIndices()。
!newposition是新生成的real数组,依次存放数组!MyArray中的元素排序后的位置。
此时!MyArray数组没有改变,需要用ReIndex()方法把得到索引数组应用到数组!MyArray 中完成排序操作。
排序举例,
!myarray[1] = 'dd'
!myarray[2] = 'cc'
!myarray[3] = 'bb'
!myarray[4] = 'aa'
如果执行sort()方法,即!myarray.sort(),则原数组发生改变
!myarray[1] = 'aa'
!myarray[2] = 'bb'
!myarray[3] = 'cc'
!myarray[4] = 'dd'
如果执行SortedIndices()方法,即!newposition = !MyArray.SortedIndices(),则生成的新数组!newposition为
!newposition[1] = 4
!newposition[2] = 3
!newposition[3] = 2
!newposition[4] = 1
5.7Do values循环和Do indices循环访问数组变量
Do values循环提供了直接访问数组元素的方法,可以通过循环变量依次访问数组中的每个元素,并对数组中元素进行相同的操作。
下面的例子可以通过循环变量访问数组!MyArray中的元素并打印出来。
Do !dovariable Values !MyArray
$p $!dovariable
enddo
Do indices循环是依次访问数组中每个元素的索引值,
Do !dovariable Indices !MyArray
!value = !MyArray[!dovariable]
$p $!value
enddo
6pml宏文件概念及其运行
6.1概念
宏文件是由多个pml命令行组成的文本文件,一般文件的后缀设为.mac(也可以是其他后缀比如.txt)。
对于一般赋值语句或定义语句,从宏文件中运行和手动输入到command window中运行的效果一样的。
但是对于流程控制结构,手动输入会报错,只能以文件的形式运行。
比如下面的do循环,
Do !x from 1 to 5 by 1
$p $!x
Enddo
逐行手动输入运行时会报错,保存到宏文件中运行时则会正确运行,一次打印出数据1
2
3
4
5
宏文件的运行方法是在命令窗口输入$m filepath,其中filepath是宏文件所在的完整路
径,且须包含完整的宏文件名,如$m C:\Windows\myfirstmacro.mac
如果没有输入文件所在的路径,程序会在当前运行目录(pdms安装路径)下查找文件,如果找不到指定文件就会报错。
6.2带参数的宏文件
使用参数化的宏可以方便的用一个宏处理一类相同的问题,只需要在调用宏时按需要赋值给参数就可以得到对应的结果。
比如下面的例子,
!result = $1 + $2 + $3
$p $!result
宏的运算是求三个参数的和,调用时输入$m filepath 1 2 3,则输出结果6。
输入的参数也可以是字符串类型,如$m filepath 'str' 'ing' '()',则输出结果string()。
需要注意,作为参数的字符串中间不能有空格,否则程序会把空格作为分隔符对字符串进行拆分,得到错误的结果。
如$m filepath 'st r' 'ing' '()',则三个参数依次赋值为'st r' 'ing'。
对于需要在参数中包含空格的情况,可以采用下面的格式书写,$m filepath $<'st r'$> 'ing' '()',则三个参数依次赋值为,'st r' 'ing' '()'。
如果在调用参数化宏文件时没有指定参数值,则宏中的参数会被忽略掉,由此可能会导致程序报错。
宏文件中的参数可以通过在宏中设置默认值的方式避免出现参数没有被赋值的情况发生,具体语法是在宏文件的开头定义参数的默认值(也可以在宏文件其他任意位置,但默认值只对定义默认值所在行后面的表达式有效)。
$D3 = ‘defaultvalue’ 注意,参数的默认值只在参数没有被赋值时有效。
字符$,可以代替空格作为参数之间的分隔符,具体格式如下,
$m filepath $,'str'$, 'ing'$, '()'$.
注意最后是以$.结尾。
另外,$,也可以用于在调用宏文件时忽略指定位置的参数,如$M /demo.mac $,$,arg2$,arg3$. 忽略了第一个参数。
也可以用$<$> 忽略指定的参数,如$M/demo.mac arg1 $<$> arg3 忽略了第二个参数。
如果忽略参数表中的最后一个参数,可以直接忽略不输入,不用特殊符号表示,如$M/demo.mac arg1 arg2
另外注意在用变量作为参数调用参数化宏时,必须把变量转为字符串类型,比如,!X = 12
!Y = 15
$m filepath $!X $!Y。