ここでは高度な 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 による実行の様子を示している。