C PARM MYDS 与 C CALL ‘FHS01ILE’ C PARM FHS01 2 C PARM FHS02 2 C PARM FHS03 2 是等价的。
可以看到,参照外部文件定义结构做为入口参数时,可以有效的节省代码行,而且不会出现遗漏。所以在实际使用中,常会看到,将一些公共程序的入口参数定义成一个PF文件。而调用它的程序,就参照这个PF文件,定义结构做为调用的接口参数。
当接口参数不一致时,如FHS02ILE中漏了第二个参数时: C CALL ‘FHS01ILE’ C PARM FHS01 3 此时,并不是一开始运行FHS01ILE程序,系统判断入口参数不符就报错;实际上,此时,FLD01的值还是正确的,但FLD02的值就处于一个未初始化的状态。于是,当代码执行到与FLD02有关的操作码时,才会报错;如果FHS01ILE在运行的过程中,因为逻辑判断(如IF条件判断)的关系,而未执行任何与FLD02有关的操作码,那么程序会正常运行完毕,不会有报错。
这时,FHS02ILE调用了程序FHS01ILE之后,程序中原有的接口参数的数据就可能因为这次调用程序而发生错位,从而导致数据的错误、混乱。数据的错误、混乱其实还不是最大的问题,更大的问题在于“这时我们不知道数据已经出错了”。解决之道,也是如上所说,对于调用频繁,且入口参数较多的公共程序,考虑将其入口参数写成一个PF文件。这样调整入口参数时,只要修改PF文件并重新编译,再编译相关程序即可(至少发生遗漏时,程序会报错异常中断,不会出现错误的数据而不自知)
2.8 C行说明 2.8.1
写在前面
终于说到程序的执行部分,也是我们写程序的平时接触的最多的一部分:“C”行了。在这里,我想先说一下我个人的看法: 400系统,提供了一些语法,可以大大减少程序代码行数。但是如果这个用法并不普遍,那么并不建议使用(当然自己用来练习无妨),否则会给其它读代码的人带来困难,同时也会给自己带来麻烦(比如出了问题,别人看不懂,自然会打电话来问原作者) 基于这样的道理,同样,我认为FREE格式的程序,虽然可以自由书写,有缩进等优势,但是除非整个项目组所有成员都已熟练掌握FREE格式的程序,或已进行过完善、系统的FREE格式的培训,才能正式使用。如果只是知道几个与RPG,RPGLE对应的语法就用来进行实际处理,可能会造成的维护的不便,尤其是在出现一些不那么明显的错误之后。 至于cycle,不知道是不是基于这个原因,现在用得也比较少了。感觉RPGLE中,至少有一半的内容是与cycle相关的。
2.8.2 内容说明
Level N01 Factor 1 Operation Factor 2 Result
Decimal Length Positions HI LO EQ Comment
Level: 和cycle相关,没研究过,一般不填 N01: 这个含义比较丰富,我只用过其中一种: 首位不带N,后面填写01—99的数字时,表示相应的指示器打开时,执行后面的操作,如: C 12 EVAL FHS01=’01’ 等价于 IF *IN12=’1’ EVAL FHS01=’01’ ENDIF 首位带N,后面填写01—99的数字,表示相应的指示器关闭时,执行后面的操作 要注意,该项内容仅作用于该行操作码。如果指示器打开后,需要执行多条语句,那么每条语句前面,该项都要赋值。 即 C IF *IN12=’1’ C EVAL FHS01=’01’ C EVAL FHS02=’02’ C ENDIF 如果用这种方式来表达,就要写作 C 12 EVAL FHS01=’01’ C 12 EVAL FHS02=’02’ 所以说,根据指示器状态来执行的语句,在执行少量操作码时,可以使用这种方法;如果语句较多,修改起来不方便,还是直接用IF—ENDIF的判断语句比较合适。 该项还有针对其它指示器的用法,看上去似乎又是与CYCLE相关,暂不介绍了。 Factor 1: 操作内容一,将在后面与操作码一起讲 Operation: 操作码,后面有专门章节讲解操作码 Factor 2: 操作内容二,同上 Result: 操作结果,同上 Length: 长度。
变量的定义,除了在D行定义之外,还可以在C行通过赋值语句直接定义 如
D FLD01 S 2 INZ(‘01’) 与 C MOVE ‘01’ FLD01 2 //2在length处,右对齐 是等价的
一个变量,在整个程序中,只要定义一次就可以了,对定义的顺序没有强制要求。 Decimal Positions: 与length相呼应,当此项有值时,表示定义的是一个数字型变量,该项表示小数位长度。 如 C Z-ADD 2 FLD02 3 2 即是说,将FLD02定义为一个3位长,其中1位整数,2位小数的数字变量,并赋值为2.00
HI、LO、EQ 这是三个指示器位置项。可赋值的内容是从01—99,在以后的说明中,如果HI项填写10,LO项填写20,EQ项填写30,那么我所说的HI指示器,即是指*IN10,LO指示器即是*IN20,EQ指示器即是*IN30,依此类推。(也就是说,HI指示器,并不是*INHI,事实上,也没有*INHI这个指示器) Comment:
注释行,源自RPG,不用填,填了也没用。
2.8.3 ILE操作码分类:
1. 程序流程控制
DO、DOU、DOUxx、DOW、DOWxx、ITER、LEVAE IF、ELSE、ELSEIF、IFxx、ORxx、ANDxx SELECT、WHEN、WHENxx、OTHER、 ENDxx、
GOTO、TAG 、
EXSR、BEGSR、ENDSR CABxx 2. 初始化操作
CLEAR、RESET 3. 文件操作
OPEN、CLOSE、
CHAIN、SETGT、SETLL、
READ、READC、READE、READP、READPE、 DELETE、UPDATE、WRITE 、UNLOCK ROLBK、COMMIT、 EXFMT、
ACQ、EXCEPT、FEOD、FORCE、NEXT、POST、REL 4. 程序调用
CALL、CALLB、CALLP、PARM、PLIST、RETURN 5. 赋值语句
6. 7.
8. 9. 10. 11. 12. 13. 14.
MOVE、MOVEA、MOVEL、 EVAL 字符操作
CAT、CHECK、CHECKR、SCAN、SUBST、XLATE 数字操作
ADD、DIV(除)、MULT(乘)、MVR(除法取余)、SQRT(开方)、SUB、XFOOT、Z-ADD、Z-SUB 数组操作符
LOOKUP、MOVEA、SORTA、XFOOT 数据区操作(没用过) IN、OUT、UNLOCK 日期操作
ADDDUR、EXTRCT、SUBDUR、TEST 指示器操作
SETOFF、SETON
信息操作(前两个没用过)
DUMP、SHTDN、TIME、DSPLY 内存管理操作(完全没用过)
ALLOC、DEALLOC、REALLOC 位操作(没用过)
BITOFF、BITON、TESTB
2.8.4 ILE操作码
A--C
2.8.4.1
ACQ {(E)} (Acquire) 取地址位。其实400的程序中也有指针型变量,那么也就会有地址位,这个命令是取地址位的。我试过,不过不知道取出了地址位能干嘛,所以没有实际运用过。 ADD {(H)} (Add) 加法操作
1. 基本语法: Factory 1 Operation Factory 2 Result FHS01 ADD FHS02 FHS03 // RPG的语法 等价于 EVAL FHS03=FHS01+FHS02 //RPGLE的语法 FHS01、FHS02、FHS03必须都为数字型变量(P型,或S型),或者就是数字 意思是将Factory 1项的数据,加上Factory 2项的数据,赋值到Result项上
2. 语法二:
如果这样写的话:
Factory 1 Operation Factory 2 Result ADD FHS02 FHS03
就等价于: EVAL FHS03=FHS03+FHS02
即Factory 1项未填时,就表示将Result 项的数据,加上Factory 2项的数据,然后赋值到Result项上 3. 四舍五入:
(H)表示四舍五入,如FHS02=12.50(4,2),FHS03=3(2,0),那么 ADD(H) FHS02 FHS03 执行之后,FHS03=16(因为进位了) 而 ADD FHS02 FHS03 执行之后,FHS03=15
不过实际使用中,我们都尽可能使相加的字段小数位数相等,所以ADD操作码一般都没有使用到四舍五入的功能。
4. 可以在ADD操作时,对Result项的变量进行定义
Factory 1 Operation Factory 2 Result
FHS01 ADD FHS02 FHS03 10 2
EVAL语句不能对在赋值的同时,对变量进行定义。
5. 关于结果数据超长时的问题:
当加出的结果超长,比如FHS03定义为3,2(1位整数,2位小数,下同)时,再假设FHS01=10,FHS02=4。那么FHS01+FHS02本来应该等于14,但用ADD操作之后,系统会自动将超长位截去,即FHS03最后等于4; 而用EVAL语句时,系统判断超长后,会直接报错“The target for a numeric operation is too small to hold the result”,然后异常中断。
使用ADD操作码程序不会异常中断,但有可能发生了错误的数据我们也不知道;使用EVAL操作码可以避免产生错误的数据,但程序会异常中断,需要进行人工干预。可根据实际情况选择使用ADD还是EVAL. ADDDUR {(E)} (Add Duration) 日期时间相加
1. 对日期型变量进行加操作,比如说已定义日期型变量MYDATE1,MYDATE2,将
MYDATE1的日期加上3天,赋值到MYDATE2中:
Factory 1 Operation Factory 2 Result MYDATE1 ADDDUR 3:*D MYDATE2
其中,Factory 1,Result项,都必须为日期型变量(即在D行,Internal Data Type项为“D” )
2. 与ADD操作码相同,Factory 1项为空时,表示直接在Result项上进行日期相加,
如将MYDATE1直接加上3个月(即结果也是赋值到MYDATE1中):
Factory 1 Operation Factory 2 Result ADDDUR 3:*M MYDATE1
3. 日期型变量的参数含义: *D表示天,也可用*DAYS *M表示月,也可用*MONTHS *Y表示年,也可用*YEARS
4. 除了日期型之外,还有时间型,日期时间型,都可以使用ADDDUR操作码.
在D行,Internal Data Type定义为“T”,表示时间型(时、分、秒) Internal Data Type定义为“Z”,表示日期时间型(年、月、日、时、分、秒、微秒) 在使用ADDDUR操作码,时间型的参数如下: