RPG

411. RPGでポインタを使った動的配列の作成

I5/OS Ver7.4 でRPGの動的配列の定義が可能になったのだが
それは別の機会に紹介するとして、それ以前のバージョンでも
配列をポインタを使って定義すれば動的配列を使うことができる。

※動的配列とは

 配列の要素数が最初は不明であるかまたは演算の途中で最大配列の要素数が
オーバーしそうであればその場で配列の要素数を拡張できる配列のことを
動的配列と呼ぶ。

 ここで紹介する動的配列はかつて「44.ILE-RPGの動的配列の使用法」で
紹介したサンプルRPGを最新の技術で書き直したものである。
当時は米国の「NEWS400」からの記事として紹介したのだが
CEE APIを使っていたので少しわかりにくいものであった。
(NEWS400は米国雑誌であるが現在は廃刊となっている)
今では %ALLOCなどの組込み関数が追加されておりフリー・フォーマットも
使えるようになったので当時のRPGソースは比べれば
格段と見やすくわかりやすくなっている。

[ RPG : TESTARY2 ]

ソースはこちらから

0001.00 H DFTNAME(TESTARY2) DATEDIT(*YMD/) BNDDIR('QC2LE')                         
0002.00 F********** TESTARY2: 動的配列のテスト ********************************    
0003.00 F*                                                                         
0004.00 F**********************************************************************    
0005.00                                                                            
0006.00  * CRTBNDRPG PGM(MYLIB/TESTARY2) SRCFILE(MYSRCLIB/QRPGLESRC) DFTACTGRP(*NO)
0007.00  *   ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)                               
0008.00                                                                            
0009.00  *-------------------------------------------------------------------*     
0010.00  *  2021/10/27 : 作成                                                      
0011.00  *-------------------------------------------------------------------*     
0012.00  *( 作業変数 )                                                             
0013.00 D STR             S              7A   DIM(5000) BASED(ARYPTR)              
0014.00                                                                            
0015.00 D N               S              5P 0                                      
0016.00 D SIZE            S              5P 0                                      
0017.00 D ELEM            S              4S 0 INZ(1000)                            
0018.00 D SAVLEN          S              4S 0 INZ(4500)                            
0019.00 D NULL            C                   CONST(X'00')                         
0020.00                                                                            
0021.00  /FREE                                                                     
0022.00    //( 最初に 1000 個 (SIZE) の配列を %ALLOC でメモリ確保する )            
0023.00    SIZE = %SIZE(STR) * ELEM;                                               
0024.00    ARYPTR = %ALLOC(SIZE);                                                 
0025.00    FOR N = 1 TO ELEM;                                                     
0026.00       CLEAR STR(N);                                                       
0027.00    ENDFOR;                                                                
0028.00    //( 配列数 1000 を超える値として SAVLEN=4500 を配列要素数に設定する )  
0029.00    DOW  SAVLEN > ELEM;                                                    
0030.00      ELEM += 1000;                                                        
0031.00      SIZE  = %SIZE(STR) * ELEM;                                           
0032.00    ENDDO;                                                                 
0033.00    //( REALLOC- メモリーを再割振りする。 )                                
0034.00    ARYPTR  = %REALLOC(ARYPTR: SIZE);                                      
0035.00    //( 4500 番目に MOVE する )                                            
0036.00    STR(SAVLEN) = 'TESTDTA';                                               
0037.00    //( DEALLOC- メモリーを解放する )                                      
0038.00    DEALLOC ARYPTR;                                                        
0039.00  /END-FREE                                                                
0040.00 C                   SETON                                        LR       
0041.00 C                   RETURN   


                                              

[コンパイル]

CRTBNDRPG PGM(TEST.COM/TESTARY2) SRCFILE(R610SRC/QRPGLESRC) DFTACTGRP(*NO)
ACTGRP(*NEW) DBGVIEW(*SOURCE) AUT(*ALL)

[解説]

配列 STR は

0013.00 D STR             S              7A   DIM(5000) BASED(ARYPTR)

と定義されているので最大要素数5000個ではあるが最初は全くメモリは
確保されていない。
ここではサンプルとして5000個と小さな数字であるが48000個など
十分大きな数字を指定したほうがよい。
次の演算 %ALLOCによって初めてメモリが確保される。

0022.00    //( 最初に 1000 個 (SIZE) の配列を %ALLOC でメモリ確保する )            
0023.00    SIZE = %SIZE(STR) * ELEM;                                               
0024.00    ARYPTR = %ALLOC(SIZE);

ELEM は

0017.00 D ELEM            S              4S 0 INZ(1000) 

として定義されているのでここでは%ALLOCによって1000個の要素を持つ配列STRが
定義されたことになる。

次に拡大する目標のサンプルとして

0018.00 D SAVLEN          S              4S 0 INZ(4500)

を定義しておいて
%REALLOCで次のようにメモリを再割振りする。

0033.00    //( REALLOC- メモリーを再割振りする。 )                                
0034.00    ARYPTR  = %REALLOC(ARYPTR: SIZE); 

これによって配列STRの要素数は4500個になったはずなので

0035.00    //( 4500 番目に MOVE する )                                            
0036.00    STR(SAVLEN) = 'TESTDTA';

として4500番目に値を代入することができる。
最後に使い終わったら動的配列は DEALLOC によってメモリを
解放しておかねばならない。

0037.00    //( DEALLOC- メモリーを解放する )                                      
0038.00    DEALLOC ARYPTR;

… 以上の方法によってポインタによって定義された配列は
動的配列として使うことができることがわかる。