RPG

361. sscanf関数の組込みRPG

C言語には sscanfという関数がある。
これはスペースで区切られた文字列を各々の変数に配分する関数である。
例えばある文字列が

“テスト コーヒー 自動車 坂道”

という4つの項目を含んでいるとする。

sscanf(“テスト コーヒー 自動車 坂道”, “%s %s %s %s”, value1, value2, value3, value4);

を実行すると

value1=”テスト”, value2=”コーヒー”, value3=”自動車”, value4=”坂道”;

のようにそれぞれの変数に値が分配される。
文字列を扱うときにこのようにブランクで区切られた文字列を分解するのを
RPGで書くとしたら想像してみて欲しい。
かなり面倒なプログラムになることは容易に想像できる。
RPGにはsscanfのようにスペースで区切られた文字列を分配する関数は
ないのである。

C言語のsprintf関数の利用については「274.ポインターを使わない sprintf」で
紹介しているので復習して欲しい。

ここではスペースで区切られた文字列を分解するC言語の関数 sscanfを
RPGで使う方法を紹介する。

[ TESTSCNF: sscanfを使うRPGの例 ]

ソースはこちらから

0001.00 H DFTNAME(TESTSCNF) DATEDIT(*YMD/) BNDDIR('QC2LE')                          
0002.00 F********** SSCANF のテスト *******************************************     
0003.00 F*                                                                          
0004.00 F**********************************************************************     
0005.00                                                                             
0006.00  * CRTRPGMOD  OBJ(QTEMP/TESTSCNF)   SRCFILE(R610SRC/QRPGLESRC)              
0007.00  * DBGVIEW(*SOURCE) AUT(*ALL)                                               
0008.00  * CRTPGM PGM(ASNET.COM/AA_SAMPLE) MODULE(QTEMP/TESTSCNF) ACTGRP(*NEW)      
0009.00  *        AUT(*ALL)                                                         
0010.00                                                                             
0011.00  *-------------------------------------------------------------------*      
0012.00  *  2017/05/01 : 作成                                                       
0013.00  *-------------------------------------------------------------------*      
0014.00 D SSCANF          PR            10I 0 EXTPROC('sscanf')                     
0015.00 D  BUFF                      32767A   OPTIONS(*VARSIZE)                     
0016.00 D  FORMAT                         *   VALUE OPTIONS(*STRING)                
0017.00 D  VAR1                           *   VALUE OPTIONS(*STRING)                
0018.00 D  VAR2                           *   VALUE OPTIONS(*STRING)                
0019.00 D  VAR3                           *   VALUE OPTIONS(*STRING)                
0020.00 D  VAR4                           *   VALUE OPTIONS(*STRING)                
0021.00 D  VAR5                           *   VALUE OPTIONS(*STRING)                
0022.00                                                                             
0023.00 D DATA            C                   CONST('" 売上 " " 返品 "')            
0024.00 D FORMAT          C                   CONST('"%s %s %s %s %s"')              
0025.00 D VLR             S             10A   DIM(5)                                 
0026.00 D PLR             S               *   DIM(5)                                 
0027.00 D VL              S              4S 0                                        
0028.00 D BUFF            S             80A                                          
0029.00                                                                              
0030.00  *( 作業変数 )                                                               
0031.00 D AR              S              1A   DIM(256)                               
0032.00 D N               S              4S 0                                        
0033.00 D NULL            C                   CONST(X'00')                           
0034.00                                                                              
0035.00 C     1             DO        5             N                                
0036.00 C                   EVAL      PLR(N)= %ADDR(VLR(N))                          
0037.00 C                   ENDDO                                                    
0038.00  /FREE                                                                       
0039.00    BUFF = DATA;                                                              
0040.00    SSCANF(BUFF:'%s %s %s %s %s':PLR(1):PLR(2):PLR(3):PLR(4):PLR(5));         
0041.00  /END-FREE                                                                   
0042.00  *( SSCANF で取得した個数 VL を求める )                                      
0043.00 C                   Z-ADD     1             VL                               
0044.00 C     *BLANKS       LOOKUP    VLR(VL)                                50      
0045.00 C     *IN50         IFEQ      *ON                                            
0046.00 C     VL            ANDGT     2                                              
0047.00 C                   SUB       2             VL                               
0048.00 C                   ENDIF                                           
0049.00  *                                                                  
0050.00 C                   SETON                                        LR 
0051.00 C                   RETURN    


                                       

[解説]

BNDDIR(‘QC2LE’) でC言語のライブラリーをバインドして使えるように宣言している。

0014.00 D SSCANF          PR            10I 0 EXTPROC('sscanf')                     
0015.00 D  BUFF                      32767A   OPTIONS(*VARSIZE)                     
0016.00 D  FORMAT                         *   VALUE OPTIONS(*STRING)                
0017.00 D  VAR1                           *   VALUE OPTIONS(*STRING)                
0018.00 D  VAR2                           *   VALUE OPTIONS(*STRING)                
0019.00 D  VAR3                           *   VALUE OPTIONS(*STRING)                
0020.00 D  VAR4                           *   VALUE OPTIONS(*STRING)                
0021.00 D  VAR5                           *   VALUE OPTIONS(*STRING)

 

で sscanf関数を定義していてここでは5つのパラメータを定義しているが
 パラメータの数はいくつであってもよい。

0035.00 C     1             DO        5             N                                
0036.00 C                   EVAL      PLR(N)= %ADDR(VLR(N))                          
0037.00 C                   ENDDO

 

ではパラメータ用にポインターを定義しておいて

0040.00    SSCANF(BUFF:'%s %s %s %s %s':PLR(1):PLR(2):PLR(3):PLR(4):PLR(5));

 

で sscanf関数を実行している。
最後のパラメータには NULL が入っているので完全に*BLANKSになるのはその次である。
 従って

0047.00 C                   SUB       2             VL

 

によって取得した変数の個数を決定している。

… sscanfはRPGで使用する頻度は少ないかも知れないが文字列を扱うことの多い
C言語では sscanfを使用する頻度は高い。
RPG でも sscanfという関数があったな、と思いだしたらこの記事を参照して欲しい。