RPG のほとんどの文字変数は実際には固定長です。これは、有限の長さを意味します。50a として定義された文字には、常に正確に 50 文字が含まれます。Eval myChar = 'A'; は、50 文字 (文字 A の後に 49 個の空白が続く) を含む myChar になります。これは退屈ですが重要です。
つまらないが重要な 2 番目のビットは、呼び出し先ではなく、呼び出し元がメモリを割り当てることを理解することです。呼び出し元が myChar 50a を宣言し、呼び出し先が myParm 65535a を宣言した場合、呼び出し元は 50 バイトのストレージのみを初期化しています。呼び出し先が 50 バイトを超えて myParm を操作しようとすると、状態が不明なストレージを操作しています。彼らが言うように、予測できない結果が生じる可能性があります。
これは、サイズが事前にサブプロシージャーに知られていない文字変数を処理するサブプロシージャーに関する質問の背景です。これを処理する古典的な方法は、文字変数だけでなく、その長さも渡すことです。eval myProcedure(myChar: %len(myChar)); これはちょっと見栄えが悪く、すべての呼び出し元が myChar の長さを計算する必要があります。サブプロシージャーが着信パラメーターに問い合わせて、呼び出し元がどのように定義したかを調べることができれば、それは確かに素晴らしいことです。
IBM は、運用記述子と呼ばれるものを通じて、まさにそのような機能を提供しています。操作記述子を使用して、呼び出し元は文字パラメーターに関するメタデータを呼び出し先に渡します。CEEDOD APIを介してそれを取得します。ここに CEEDOD の使用例があります。
基本的に、サブプロシージャーは、操作記述子が必要であることを宣言する必要があります。
dddeCheck pr n opdesc
d test 20a const options(*varsize)
呼び出し元は、サブプロシージャーに対して通常の呼び出しを行います。
if ddeCheck(mtel) = *on; // 10 bytes
...
endif;
if ddeCheck(mdate: *on) = *on; // 6 bytes
...
endif;
呼び出し元は、異なるサイズの固定長変数をサブプロシージャーに渡すことに注意してください。
サブプロシージャーは、CEEDOD を使用して着信パラメーターの長さを調べる必要があります。
dddeCheck pi n opdesc
d test 20a const options(*varsize)
...
dCEEDOD pr
d parmNum 10i 0 const
d descType 10i 0
d dataType 10i 0
d descInfo1 10i 0
d descInfo2 10i 0
d parmLen 10i 0
d ec 12a options(*omit)
d parmNum s 10i 0
d descType s 10i 0
d dataType s 10i 0
d descInfo1 s 10i 0
d descInfo2 s 10i 0
d parmLen s 10i 0
d ec s 12a
...
CEEDOD (1: descType: dataType: descinfo1: descinfo2: parmlen: *omit);
この時点で、parmlen には、呼び出し元が着信変数を定義した長さが含まれています。今、その情報を使って何かをするのは私たち次第です。文字ごとに処理している場合は、次のようにする必要があります。
for i = 1 to parmLen;
char_test = %subst(test: i: 1);
...
endfor;
単一の文字列として処理している場合は、次のようにする必要があります。
returnVar = %xlate(str_lc_letters_c: str_uc_letters_c: %subst(s: 1: parmLen));
重要なことは、その参照が呼び出し元によって定義された実際の変数の長さによって何らかの形で制限されない限り、決して入力パラメーターを参照しないことです。これらの注意事項は、固定長変数にのみ必要です。コンパイラは、可変長文字変数の長さを既に認識しています。
コンパイラが CONST を介して myFixed を myVarying にマップする方法について、その仕組みを理解してください。コンパイラは、myFixed から MyVarying にすべてのバイトをコピーします。myFixed が 10a の場合、myVarying は 10 バイトの長さになります。myFixed が 50a の場合、myVarying は 50 バイトの長さになります。末尾の空白はすべての固定長文字変数の一部であるため、常に含まれます。これらの空白は、空白を無視する変換手順ではそれほど重要ではありませんが、文字列を中央揃えにする手順では重要になる場合があります。この場合、操作記述子に頼るか、次のようなことをする必要がありますupperVary = str_us(%trimr(myFixed));