在RPGLE中实现模糊检索的例程(带详细注释)

发表于:2007-05-26来源:作者:点击数: 标签:
说明: 1、这是一个在 数据库 中模糊检索地址的RPGLE程序。在画面上输入检索字串(用空格分开),回车后,SFL中显示DB中所有带有这些字串的地址 2、子程序说明:@KEN01为模糊检索,@C LR 01为SFL初始化,@WRT01为写SFL,@DEF为变量定义,@END为结束程序。[co

说明:
1、这是一个在数据库中模糊检索地址的RPGLE程序。在画面上输入检索字串(用空格分开),回车后,SFL中显示DB中所有带有这些字串的地址
2、子程序说明:@KEN01为模糊检索,@CLR01为SFL初始化,@WRT01为写SFL,@DEF为变量定义,@END为结束程序。[color=red:d18865074c]红色的代码为全角检索专用。如果仅用于半角检索,可以删去。[/color:d18865074c]
3、ADDR01D为画面程序(只带最基本的SFL功能,仅供测试用),ADDRES为PF文件(只有地址一个字段)。画面入力项及DB字段长度均定义为40,使用时可根据实际情况修改(全角检索时需同时修改配列长度)。
4、为了提高效率,应将@KEN01中的字串截取部分单独写成一个子程序,并将截取的各子串赋给配列,这样就不用每读一条记录都重复执行字串截取了。我有空的时候会做如上修改。同时也欢迎大家多提宝贵意见。 [color=red:d18865074c](已修正,见后贴)[/color:d18865074c]

RPGLE程序:

     H DATEDIT(*YMD)
     FADDRES    IF   E           K DISK
     FADDR01D   CF   E             WORKSTN SFILE(SFL01:#RRN01)
     [color=red:d18865074c]D AR1             S              1    DIM(40)[/color:d18865074c]
     C*
     C                   DO        *HIVAL
     C*
     C                   WRITE     FMT99
     C*
     C                   IF        #RRN01 <> 0
     C                   SETON                                        29
     C                   ENDIF
     C*
     C                   SETON                                        28
     C                   EXFMT     CTL01
     C                   SETOFF                                       2829
     C*
     C                   IF        *IN03 = *ON
     C                   EXSR      @END
     C                   ENDIF
     C*
     C                   EXSR      @CLR01
     C                   EXSR      @KEN01
     C*
     C                   ENDDO
     C*****************************************************************
     C     @END          BEGSR
     C*
     C                   SETON                                        LR
     C                   RETURN
     C*
     C                   ENDSR
     C*****************************************************************
     C     @KEN01        BEGSR
     C*
     C                   SETOFF                                       92
     [color=red:d18865074c]C                   MOVEA     D#ADDR        AR1[/color:d18865074c] 
     C*
     C     *LOVAL        SETLL     ADDRESR
     C                   READ      ADDRESR                                90
     C                   DOW       *IN90 = *OFF AND #RRN01 < 9999
     C*
     C* 模糊检索
     C                   Z-ADD     1             W#FROM
     C*
     C                   DO        *HIVAL
     C*
     C* 第一个空格以外的字符位置 = W#FROM
     C     ' '           CHECK     D#ADDR:W#FROM W#FROM                   91
     C  N91              LEAVE
     C*
     C* 下一个空格的位置 = W#TO
     C     ' '           SCAN      D#ADDR:W#FROM W#TO                     91
     C  N91              LEAVE
     [color=red:d18865074c]C*
     C* 判断子字符串开头是否为汉字起始控制符
     C                   IF        AR1(W#FROM) = X'0E'
     C                   ADD       1             W#FROM
     C                   ENDIF
     C*
     C* 判断子字符串结尾是否为汉字结束控制符
     C                   IF        AR1(W#TO - 1) = X'0F'
     C                   SUB       1             W#TO
     C                   ENDIF[/color:d18865074c]
     C*
     C* 子字符串长度 = W#LEN
     C     W#TO          SUB       W#FROM        W#LEN
    C* 
    C                   IF        W#LEN <> *ZERO 
     C*
     C* 子字符串 = W#SUB
     C     W#LEN         SUBST(P)  D#ADDR:W#FROM W#SUB
     C*
     C* 检索
     C     W#SUB:W#LEN   SCAN      ADADDR                                 92
     C  N92              LEAVE
     C*
     C                   ENDIF
     C*
     C* 下一次取子字符串的开始位置 = W#FROM
     C     1             ADD       W#TO          W#FROM
     C                   ENDDO
     C*
     C   92              EXSR      @WRT01
     C*
     C                   READ      ADDRESR                                90
     C                   ENDDO
     C*
     C                   ENDSR
     C*****************************************************************
     C     @CLR01        BEGSR
     C*
     C                   SETON                                        27
     C                   WRITE     CTL01
     C                   SETOFF                                       27
     C*
     C                   Z-ADD     *ZERO         #RRN01
     C
     C                   ENDSR
     C*****************************************************************
     C     @WRT01        BEGSR
     C*
     C                   ADD       1             #RRN01
     C                   MOVEL     ADADDR        S#ADDR
     C                   WRITE     SFL01
     C*
     C                   ENDSR
     C*****************************************************************
     C     @DEF          BEGSR
     C*
     C                   Z-ADD     *ZERO         #RRN01            4 0
     C                   Z-ADD     *ZERO         W#FROM            2 0
     C                   Z-ADD     *ZERO         W#TO              2 0
     C                   Z-ADD     *ZERO         W#LEN             2 0
     C                   MOVEL     *BLANK        W#SUB            40
     C*
     C                   ENDSR

画面文件

     A                                      CF03(03 '终了')
     A*****************************************************************
     A          R SFL01                     SFL
     A            S#ADDR        40O     5 15TEXT('地址')
     A*****************************************************************
     A          R CTL01                     SFLCTL(SFL01)
     A                                      OVERLAY
     A                                      SFLSIZ(9999)
     A                                      SFLPAG(0016)
     A  27                                  SFLCLR
     A  28                                  SFLDSPCTL
     A  29                                  SFLDSP
     A*
     A                                  1 30'地址模糊检索'
     A                                      DSPATR(RI)
     A                                  1 63DATE
     A                                      EDTWRD('0  /  /  ')
     A                                  1 72TIME
     A                                  3  2'地址:'
     A            D#ADDR        40O  B  3 15
     A*****************************************************************
     A          R FMT99
     A                                 24  3'F3:终了'
     A                                      DSPATR(HI)

PF文件:

     A          R ADDRESR
     A*
     A            ADADDR        40O

 zhu_jihui 回复于:2005-09-01 13:10:56
很好,偶看可行!建议加精

 xuguopeng 回复于:2005-09-01 13:11:08
不错 加精~

不过如果把RPGLE的代码逐句注解出来 相信会成为一个好的模糊查询教材~~

 zhu_jihui 回复于:2005-09-01 13:15:24
楼主,是原创吗?

 teresa99 回复于:2005-09-01 13:15:39
楼主,俺对你的敬仰如滔滔江水。。。

 armycat 回复于:2005-09-01 13:16:50
是俺今天上午抽空瞎写的,多多指教,多多指教。

 Inyan 回复于:2005-09-01 13:17:41
呵呵,看起来比我们那个模糊查询代码要少些。
 :wink:

 zhu_jihui 回复于:2005-09-01 13:19:47
那时当然了呵呵!!

 mamei 回复于:2005-09-01 13:30:38
我正在搞模糊查询的东东!

多谢了

 armycat 回复于:2005-09-01 14:00:51
刚刚把说明4中提到的问题修正了一下:

1、增加了两个配列:AR2中存放各字串的内容(长度40的入力项最多有20个字串,每个字串最大长度40),AR3中存放各字串的长度。

     D AR2             S             40    DIM(20)
     D AR3             S              2  0 DIM(20)

2、@KEN01做以下修正:

     C     @KEN01        BEGSR
     C*
     C* 取得各子字符串放入配列
     C                   Z-ADD     1             W#FROM
     C                   Z-ADD     *ZERO         W#N
     [color=red:fa551973d8]C                   MOVEA     D#ADDR        AR1[/color:fa551973d8]
     C*
     C                   DO        *HIVAL
     C*
     C* 第一个空格以外的字符位置 = W#FROM 
     C     ' '           CHECK     D#ADDR:W#FROM W#FROM                   91
     C  N91              LEAVE
     C*
     C* 下一个空格的位置 = W#TO 
     C     ' '           SCAN      D#ADDR:W#FROM W#TO                     91
     C  N91              LEAVE
     [color=red:fa551973d8]C*
     C* 判断子字符串开头是否为汉字起始控制符 
     C                   IF        AR1(W#FROM) = X'0E' 
     C                   ADD       1             W#FROM 
     C                   ENDIF 
     C* 
     C* 判断子字符串结尾是否为汉字结束控制符 
     C                   IF        AR1(W#TO - 1) = X'0F' 
     C                   SUB       1             W#TO 
     C                   ENDIF[/color:fa551973d8] 
     C* 子字符串长度 = W#LEN 
     C     W#TO          SUB       W#FROM        W#LEN
     C*
     C                   IF        W#LEN <> *ZERO
     C*
     C* 子字符串 = W#SUB 
     C     W#LEN         SUBST(P)  D#ADDR:W#FROM W#SUB
     C*
     C* 写入配列
     C                   ADD       1             W#N
     C                   MOVEL(P)  W#SUB         AR2(W#N)
     C                   Z-ADD     W#LEN         AR3(W#N)
     C*
     C                   ENDIF
     C*
     C* 下一次取子字符串的开始位置 = W#FROM
     C     1             ADD       W#TO          W#FROM
     C*
     C                   ENDDO
     C*
     C                   SETOFF                                       92
     C     *LOVAL        SETLL     ADDRESR
     C                   READ      ADDRESR                                90
     C                   DOW       *IN90 = *OFF AND #RRN01 < 9999
     C*
     C* 模糊检索
     C     1             DO        W#N           W#I
     C                   Z-ADD     AR3(W#I)      W#L
     C     AR2(W#I):W#L  SCAN      ADADDR                                 92
     C  N92              LEAVE
     C                   ENDDO
     C*
     C   92              EXSR      @WRT01
     C*
     C                   READ      ADDRESR                                90
     C                   ENDDO
     C*
     C                   ENDSR

3、@DEF中增加三个工作变量的定义:

     C                   MOVEL     *BLANK        W#N               2 0      
     C                   MOVEL     *BLANK        W#I               2 0      
     C                   MOVEL     *BLANK        W#L               2 0      

可能有仔细的朋友会发现我定义了一个不必要的变量W#L。这是没有办法的事情,否则AR2(W#I):W#L  SCAN      ADADDR 一行会超长。

 nhxingliang 回复于:2005-09-01 16:46:18
谢谢.........

认真学习.....................

原文转自:http://www.ltesting.net