CL変数の長さ
Question
ハードコーディングしなくても CL の文字列の長さを簡単に計算できる方法はありますか。末尾ブランクがある場合とない場合の、両方の長さを計算できますか。
Answer
実は、今週のSystem iNetwork フォーラムにこの件に関して、ちょうどよいディスカッションがありました。この記事では、最善と思った回答を記載して、そのコードがどのように動作するかを説明します。また、自分で読んでいただけるよう、フォーラムのオリジナル・スレッドへのリンクも掲載します。
スレッドの中でベスト・アンサーと思ったのはユーザー DeesseT 氏の回答でした。非常に短く、簡単な CL プログラムをいくつか使用して、文字列長を計算するためのコマンドをシステムに作成できます。いったんコマンドをコンパイルしたら、何度もそれらを使用できます。まるで、コマンドが言語に組み込まれているような感じです。
最初のコマンドは RTVDTALEN で、データの長さ、つまり、末尾ブランクを取り去った後の変数の長さを計算します。
Member RTVDTALEN, file QCMDSRC:
CMD 'Retrieve length of data'
PARM Var +
*X +
MIN(1) +
EXPR(*YES) +
VARY(*YES *INT2) +
PROMPT('CL variable name')
PARM DtaLen +
*INT2 +
RTNVAL(*YES) +
MIN(1) +
PROMPT('Variable for DTALEN (INT2)')
Member RTVDTALEN, file QCLSRC:
PGM (&Var &DtaLen)
DCL &Var *INT 2 /* CL variable name */
DCL &DtaLen *INT 2 /* Data length */
CHGVAR &DtaLen &Var
ENDPGM
このコードは、コマンドの第 1 パラメーターに指定された VARY(*YES) オプションを利用して動作します。PARM コマンドのヘルプ・テキストに、このパラメーターについてこんなことが書かれています。
可変長 (VARY) - ヘルプは、コマンド処理プログラムに渡される値に先行して、コマンド・パラメーターに入力された文字数を示す長さの値が指定されているかどうかを指定します。注: 長さの値は、コマンド・パラメーターに入力された実際の文字数で、末尾ブランクは削除されています。渡された長さの値は、定義されたパラメーター長または宣言された可変長と異なる場合があります。文字列データを含むフィールド長は、パラメーターに定義された値または CL プログラム変数に宣言された LEN により決まります。長さの値は、文字列データ・フィールドの文字が、実際に何個コマンド・パラメーターに入力されたかを定義します。
したがって、CPP に渡されたパラメーターの最初の 2 バイトには、末尾ブランクが削除された文字列の長さが自動的に取り込まれます。このため、このコマンドの CPP が非常にシンプルになっているのです。(長さを取得するのに) 第 1 パラメーターの最初の 2 バイトだけを読み取り、それを戻された長さパラメーターにコピーする必要があります。なんと賢いのでしょう。
このコマンドをコンパイルして、ライブラリー・リストに置いたら、次のように CL のどの文字列の長さもわかります。
PGM
DCL VAR(&TEST) TYPE(*CHAR) LEN(100)
DCL VAR(&LEN) TYPE(*INT) LEN(2)
CHGVAR VAR(&TEST) VALUE('this is 9')
RTVDTALEN VAR(&TEST) DTALEN(&LEN)
ENDPGM
文字列の最大長を計算するため、DeesseT 氏は、以下に示すように、非常によく似た別のコマンドを提供していました。この例と前の例との主な違いは、第 1 パラメーターが RTNVAL(*YES) で定義されていることです。この違いは大きいです。というのも、RTNVAL(*YES) を指定すると、CL プログラムではその変数にデータを出力するよう求められるためです。したがって、(どれだけのスペースで作業しなければならないかわかるよう) 出力できるデータの最大サイズに等しい長さが設定されます。
Member RTVVARSIZ, file QCMDSRC:
CMD 'Retrieve size of CL variable'
PARM Var +
*X +
1 +
MIN(1) +
EXPR(*YES) +
VARY(*YES *INT2) +
PROMPT('CL variable name')
PARM Size +
*INT2 +
RTNVAL(*YES) +
MIN(1) +
PROMPT('Variable for DTALEN (INT2)')
Member RTVVARSIZ, file QCLSRC:
PGM (&Var &Size)
DCL &Var *INT 2 /* CL variable name */
DCL &Size *INT 2 /* Size of CL variable */
CHGVAR &Size &Var
ENDPGM
したがって、RTNVAL(*YES) を使用して、短くした長さではなく、文字列の最大長を計算できます。それだけでなく、前述の例と同様に動作します。また使い方は同じです。
PGM
DCL VAR(&TEST) TYPE(*CHAR) LEN(100)
DCL VAR(&LEN) TYPE(*INT) LEN(2)
CHGVAR VAR(&TEST) VALUE('this is 9')
RTVVARSIZ VAR(&TEST) SIZE(&LEN)
ENDPGM
これは非常に賢いやり方だと思いました。
ここで説明したユーティリティーをコンパイルするには、以下のコマンドを実行します。
CRTCLPGM PGM(RTVDTALEN) SRCFILE(QCLSRC)
CRTCMD CMD(RTVDTALEN) PGM(RTVDTALEN) SRCFILE(QCMDSRC)
ALLOW(*IPGM *BPGM *IMOD *BMOD)
CRTCLPGM PGM(RTVVARSIZ) SRCFILE(QCLSRC)
CRTCMD CMD(RTVVARSIZ) PGM(RTVVARSIZ) SRCFILE(QCMDSRC)
ALLOW(*IPGM *BPGM *IMOD *BMOD)
