*H 表示小时,也可用*HOURS *MN表示分钟,也可用*MINUTES *S 表示秒, 也可用*SECONDS
而日期时间型,除了可以使用*Y、*M、*D、*H、*MN、*S(以及相应的全称)之外,还可以对微秒进行处理,参数为*MS,或*MSECONDS
5. Factory 2项中的数字,可以使用负数,使用负数时,表示减去相应的年、月、日,
不过通常我会使用SUBDUR这个操作码来进行日期的减法,语法与ADDDUR相同
6. 既然说到这里,就顺便说一下对于日期型变量(时间型,日期时间型也类似)的处
理。在实际运用时,常需要将日期型变量与8位数字型变量转换。这时要使用MOVE操作码。如MOVE 日期型变量 数字型变量,反之也是。不能用Z-ADD。
ALLOC {(E)} (Allocate Storage) 好象是给指针型变量分配空间的,没有用过 ANDxx (And) 条件判断语句—“与”
1. 在RPG的用法中,有ANDEQ,ANDNE之类的,与IF语句一起联用。 Factory 1 Operation Factory 2 Result FLD01 IFEQ ‘A’ FLD02 ANDEQ ‘B’ 。。。处理内容 ENDIF
2. AND后面跟的xx,可以有如下用法:
EQ Factory 1 = Factory2 NE Factory 1 <> Factory2 GT Factory 1 > Factory2 LT Factory 1 < Factory2 GE Factory 1 >= Factory 2 LE Factory 1 <= Factory 2
3. 不过在实际上,因为RPGLE可以使用类似自由语言的风格,而且可以使用括号来
处理逻辑判断先后顺序(这个是我用RPG写起来比较麻烦的,尤其是ANDxx与ORxx的关系,很复杂的判断写起来就不那么顺畅),所以一般都不会这么写,而是用如下的风格: Factory 1 Operation Factory 2 Result
IF FLD>FLD2 AND FLD2
当逻辑判断条件太长,一行写不下要分行写时,AND在上一行,还是下一行,都没有关系。
Operation项用EVAL操作码时,再按F4,会看到Factory2项变成了一个很长的Extended Factory2项,而原来的Result、Length、Decimal Positions、HI、LO、EQ项都没了。
我们的逻辑判断语句,就都写在这个Extended Factory 2项中
BEGSR (Beginning of Subroutine) 子过程的开始处 Factory 1 Operation Factory 2 Result BEGSR 子过程名
在前面,讲述程序流程时,已经对子过程进行了解释。这里,BEGSR本身用法没什么特别的,只是要注意有BEGSR语句,就一定要有ENDSR对应。否则程序编译会报错。所以这里建议,如果是自已从头到尾写一个程序,最好写了BEGSR语句后,马上写一个ENDSR,然后再来写中间的内容,避免遗漏。 在程序中,可以写一个子过程,但是不调用它。(也允许就是子过程没有相应的EXSR语句) 也允许写一个空的子过程。(也就是BEGSR语句与ENDSR语句之间没有别的执行语句了)
BITOFF (Set Bits Off) 没用过
BITON (Set Bits On) 没用过
CABxx (Compare and Branch) 没用过
CALL {(E)} (Call a Program) 调用外部程序 Factory 1 Operation Factory 2 Result CALL ‘外部程序名’
1. 如果是直接调用外部程序,那么程序名称需要用单引号括起来,且该程序必须存在。
如
CALL ‘FHSILE01’
就表示调用“FHSILE01”这个外部程序
2. 如果没有用单引号,如
CALL FHSILE01
就表示,FHSILE01这时是个字符型变量(即并非调用“FHSILE01这个程序),调用的是变量内容所代表的程序。如: FHSILE01=’FHS01’时,表示调用“FHS01”这个外部程序; FHSILE01=’FHS02’时,表示调用“FHS02”这外外部程序 也就是说,CALL操作码调用的程序名,可以是一个变量名。
3. 被调用的外部程序如果有接口参数,那么CALL操作码之后,也需要有“PARM”
操作码相对应。详细内容可参考之前的“入口参数”一节。
4. 这一点要注意:虽然400的程序段代码中,是不区分大小写;但调用的程序名,要
区分大写小。即’FHSILE01’,与fhsile01,表示的是两个不同的程序。在使用时要注意,尤其是程序名使用字符变量来表达时,可能会因为大小写的问题而导致CALL不到想CALL的程序,从而导致程序异常中断。
CALLB {(D | E)} (Call a Bound Procedure) 也没用过,不过有不少人用,望举例说明
CALLP {(M | R | E)} (Call a Program or Procedure) 也没用过,不过有不少人用,望举例说明
CASxx (Conditionally Invoke Subroutine) 带条件的调用子过程
1. 表示根据xx项对Factory 1与Factory 2进行判断,当符合条件时,执行Result处
的子过程。需要配合“END”或“ENDCS”语句来表示条件判断的结束。不需要“SELECT”操作码。 2. 举例如下:
Factory 1 Operation Factory 2 Result
FLD01 CASEQ ‘1’ SUB01 FLD01 CASEQ ‘2’ SUB02 CAS SUB03 ENDCS 表示当FLD01等于’1’时,执行子过程SUB01; 当FLD01等于’2’时,执行子过程SUB02; 当不满足以上两个条件时,执行子过程SUB03 最后的“ENDCS”必须要有,表示条件判断结束;但不需要SELECT。 上面这段语句,与下面这一段是等价的:
Factory 1 Operation Factory 2 Result
SELECT WHEN FLD01=’1’ EXSR SUB01 WHEN FLD01=’2’ EXSR SUB02 OTHER EXSR SUB03 ENDSL
3. 可以看出来,CASxx这种语句,是用于逻辑判断仅一个条件时的分支处理,这样
的写法在代码的阅读上会很直观。而当逻辑判断大于一个条件时,这个语句就不适用了。
CAT {(P)} (Concatenate Two Character Strings) 字符连接
1. 基本语法:
Factory 1 Operation Factory 2 Result
FLD01 CAT FLD02:0 FLD03
这句话的意思,是将FLD02拼在FLD01后面,中间没有空格,然后将拼出的结果赋值到FLD03中。 FLD02:0,表示FLD02与FLD01之间的空格数为0,依此类推 FLD02:1,就表示FLD01后面加一个空格,再拼上FLD02 FLD02:3,就表示FLD01后面加三个空格,再拼上FLD02 Factory 1项,与Factory 2项可以是字符型变量,也可以就是字符。当是字符时,需要用单引号将字符括起来
2. 其实根据RPG的语法,大家应该也可以想得到,Factory1项如果不填值,就表示
将Factory 2项的内容直接拼在Result项上,这里就不举例了。 3. 字段FLD01如果内容后面有空格,如“ABC ”,那么在CAT操作时,系统会自
动将后面的空格截去,只取’ABC’。举例:
FLD01=’ABC ‘ (8位字符型), FLD02=’1’ (1位字符型), FLD03=’’ (8位字符型) 那么,执行了下述语句之后
FLD01 CAT FLD02:0 FLD03 FLD03就等于’ABC1 ’ 而如果执行:
FLD01 CAT FLD02:1 FLD03 FLD03就等于’ABC 1 ‘ (C与1之间有一个空格) 4. 表示空格个数时,可以使用数字型的变量来表达,如
EVAL N=1
FLD01 CAT FLD02:N FLD03
5. CAT操作码,其实也可以通过EVAL来实现部分。比如将FLD01与FLD02拼起来,
中间无空格,赋值到FLD03中,也可以写做:
EVAL FLD03=FLD01 + FLD02
6. EVAL操作码的优势,在于可以在一行语句中,就把多个字符拼在一起,如:
EVAL FLD05=FLD01+FLD02+FLD03+FLD04
如果要用CAT写,就要写多行,不简洁。
7. EVAL操作码的不足之处,在于只能进行最简单的拼接,无法自动将字符后面的空
格去除,如:
FLD01=’ABC ‘ (8位字符型), FLD02=’1’ (1位字符型), FLD03=’’ (8位字符型) 在执行语句 EVAL FLD03=FLD01+FLD02 后, FLD03=’ABC ‘
因为FLD01是8位,FLD03也是8位,在操作时,不能去掉ABC后面的5位空格,此时后面再拼FLD02已无意义,所以FLD03仍是’ABC ‘
CHAIN {(N | E)} (Random Retrieval from a File) 按键值对文件记录进行查询定位
1. 基本语法:
举例,对逻辑文件PFFHSL1进行定位操作。逻辑文件PFFHSL1,是以FHS01为键值,文件记录格式名叫FMTFHS
Factory 1 Operation Factory 2 Result HI LO EQ
FHS01 CHAIN FMTFHS 17 18
这个例子中,FHS01应该是一个与文件PFFHSL1中键值(FLD01)类型、长度都相等的一个字符型变量,或者字符。
Factory 2项中,要填文件的记录格式名,而不是文件名
HI指示器表示是否查询到相应记录,查询不成功时,打开HI指示器 LO指示器表示查询时,文件是否被锁。文件被锁时,打开LO指示器 也就是说:
*IN17=’0’,表示查询到了目标记录。
*IN17=’1’, *IN18=’0’,表示无相应的目标记录
*IN17=’1’, *IN18=’1’, 表示查询时,文件被锁(不确定有没有相应的目标记录) 2. 用修改方式声明的文件,当查询成功后,目标记录被锁定,其它程序无法以修改的
方式定位到当前目标记录上。(但可以用只读的方式定位)
3. LO指示器,仅于用修改方式声明的文件。对于只读方式声明的文件其实无意义 4. 如果用修改方式声明文件,但在LO处未填写指示器,且有程序锁住目标记录时,
当前程序会根据PF中定义的WAITRCD(Maximum record wait time)参数,等待相应的秒数(如WAITRCD处为10,即表示锁表时,等待10秒;如果填的是*IMMED,就表示不等待,一判断目标记录被锁就结束操作);如果在等待时间内,对方仍未解锁,当前程序就会异常中断退出;如果LO处填写指示器,那么程序就不会中断退出,且LO指示器打开。
5. 当FHS01键值,在文件PFFHSL1中,对应有多条记录时(即键值不唯一),程序
将会按照文件的内部记录号由小到大的顺序,定位到符合条件的第一条记录。 6. 当一个逻辑文件,KEY值有多项时,可以使用KLIST操作码先定义一个组合键值,
然后再用这个组合键值来进行CHAIN操作。需要注意,组合键值中,必须每一个成员字段都与目标记录所对应的字段相等,才能查询成功。(所以组合键值,通常使用SETLL定位较多)
7. 当用修改方式声明文件,但希望进行不锁记录的查询操作时,可以将CHAIN操作
码写为CHAIN(N),这个括号(N),就表示当前的查询定位,不对记录进行锁定操作(也就是用只读的方式来处理目标记录,所以只能取出目标记录的信息,不能做修改;如果要修改目标记录的话,还必须进行一个CHAIN操作) 8. 这一条要特别注意:
当没有填写HI指示器时,RPGLE是允许编译通过的。而在某些情况之下(以前见过),运行程序时,如果CHIAN操作成功,找到了符合条件的记录时,没有任何问题;但如果CHAIN操作没有找到符合条件的记录时,实际上系统会按照键值的排序以及内部记录号,定位到下一条记录上,这时再取出来的数据,就统统都是下一条记录的数据。所以,除非有绝对的把握,CHAIN操作肯定成功,否则就一定要养成填写HI指示器的良好习惯。
(不好意思,这里好象又写错了,几经测试仍未测出这种情况,不过印象中的确出现过这种找到错误记录的情况,可能具体情况/条件记混了)。
CHECK {(E)} (Check Characters) 检查目标变量中的字符
1. 基本语法:
Factory 1 Operation Factory 2 Result HI LO EQ
FLD01 CHECK FLD02:2 N 42
语句CHECK的意思,是指字段FLD02中,从第二位字符开始,向右查找(含第二位字符),是否包含有FLD01中没有的字符。
如果的确有在FLD01中没有的字符,将字符所在位置赋值到变量N中,同时打开EQ指示器;
如果从第二位字开始,向右读取的所有字符,都可以在变量FLD01中找到,那么N为0,EQ指示器处于关闭状态。
“FLD02:2”表示从变量FLD02的第二位开始,向右作比较。如果仅仅只是“FLD02”,那么就表示从变量FLD02的首位开始,向右查找
2. 实例
假设FLD01为8位长字符,且当前值为’12345678’ 而FLD02为5位长字符,且当前值为’A3456’
那么执行上述CHECK操作后,N=0, *IN42=’0’(从第二位开始,3456都存在于变量FLD01中)