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という関数があったな、と思いだしたらこの記事を参照して欲しい。
