ここでは高度な SORT
の事例を紹介する。
SORTA
については既に多くの読者もご存知であると思うが社内事情によって
文字列の並び順とはいかない、独自の順序で並べることができるだろうか ?
例えば品種コード順に単純に分類するのではなく、品種の中でもある重要な
品種については先頭に表示したいような場合である。
このような独自の分類を行いたい場合には C言語で用意されている関数 : qsort が
効果的である。
qsort 関数を活用することができれば、どのような順序にでも思いのままに
SORT することができる。
------------------------------------------------------------------------------- 0001.00 H DFTNAME(TESTSORTC) DATEDIT(*YMD/) 0002.00 H DFTACTGRP(*NO) BNDDIR('QC2LE') 0003.00 F********** SORTのサンプル **************************************** 0004.00 F* QSORT による SORT 0005.00 F***************************************************************** 0006.00 D COMPARE PR 10I 0 0007.00 D FLDA * VALUE 0008.00 D FLDB * VALUE 0009.00 0010.00 D QSORT PR EXTPROC('qsort') 0011.00 D ARRAY * VALUE 0012.00 D ITEMSU 10I 0 VALUE 0013.00 D SIZE 10I 0 VALUE 0014.00 D COMPARE * VALUE PROCPTR 0015.00 0016.00 D CDR S 4 DIM(3) CTDATA PERRCD(1) 0017.00 D NMR S 14 DIM(3) CTDATA PERRCD(1) 0018.00 D STR S 18 DIM(3) 0019.00 0020.00 C MOVEL CDR STR 0021.00 C MOVE NMR STR 0022.00 C* SORT 前のデータの表示 0023.00 C 1 DO 3 N 4 0 0024.00 C STR(N) DSPLY 0025.00 C END 0026.00 C '*END OF DATA'DSPLY ANS 1 0027.00 C* 0028.00 C* QSORT によって昇順に並べる 0029.00 C CALLP QSORT(%ADDR(STR):3:18:%PADDR(COMPARE)) 0030.00 C* 0031.00 C 1 DO 3 N 4 0 0032.00 C STR(N) DSPLY 0033.00 C END 0034.00 C '*END OF SORT'DSPLY ANS 1 0035.00 C SETON LR 0036.00 ********************************************************* 0037.00 P COMPARE B 0038.00 ********************************************************* 0039.00 D PI 10I 0 0040.00 D FLDAP * VALUE 0041.00 D FLDBP * VALUE 0042.00 0043.00 D FLDA S 18A BASED(FLDAP) 0044.00 D FLDB S 18A BASED(FLDBP) 0045.00 0046.00 C SELECT 0047.00 C WHEN FLDA > FLDB 0048.00 C RETURN 1 0049.00 C WHEN FLDA < FLDB 0050.00 C RETURN -1 0051.00 C OTHER 0052.00 C RETURN 0 0053.00 C ENDSL 0054.00 P E 0055.00 ** CDR 0056.00 0002 0057.00 0001 0058.00 0003 0059.00 ** NMR 0060.00 ビデオデッキ 0061.00 カラーTV 0062.00 コンボ -------------------------------------------------------------------------------
CRTBNDRPG MYLIB/TESTSORTC SRCFILE(MYSRCLIB/QRPGLESRC) AUT(*ALL)
まず H-仕様書では
H DFTACTGRP(*NO) BNDDIR('QC2LE')
によって QC2LE
という C関数のバインド・ディリクトリーを定義することによって
C関数を取り込むようにする。
qsort 関数は
qsort(SORTする配列のポインター : 配列の項目数 : 項目の長さ : 比較関数のポインター)
として関数の型が定義されていると解釈してよいだろう。
実際は
( void qsort(void *base, size_t num, size_t, width, int(*compare)(const void *elem1,const void *elem2)); )
として定義されているが RPG開発者にとっては上記の解釈で十分である。
ここで qsort が汎用的であるのは SORT のために比較を判断する関数 compare
が
ユーザー定義であることである。
そこで比較関数を
0006.00 D COMPARE PR 10I 0 0007.00 D FLDA * VALUE 0008.00 D FLDB * VALUE
としてユーザー定義する。バラメータは2つの項目のポインターが渡されるので
1 を戻り値として戻せば、その比較は正常であることを qsort に伝えて、
-1 を戻り値として戻せば、その比較は入れ替えが必要であることを qsort に伝えることができる。
このようにして qsort はユーザーが定義した比較関数の指示に従って SORT を行うのである。
従って比較関数 COMPARE
の中でユーザーはどのような分類順序であっても自由に定義することが
できるのである。
これよって COMPARE を工夫しさえすれば自由度の高いユーザー定義による SORT をいくらでも
実現することができる。
次はこの SORT による実行の様子を示している。