メニューボタン
IBMi海外記事2025.06.25

RPGで%CONCATおよび%CONCATARRを活用する

Gregory Simmons 著

RPGで(特にモダンなフリーフォーマット コードで)ストリングの処理を行う場合、%CONCATおよび%CONCATARR組み込み関数(BIF)は、ストリングを結合するための効率的で判読しやすいソリューションを提供します。これらの関数を使用すると、複数のストリング値を連結するプロセスが簡素化されるため、コードはすっきりして読みやすくなり、保守も容易になります。この記事では、それらの関数の使い方について説明し、それらの実用的な用例について見て行きます。

%CONCAT BIFは、複数のストリングを結合することを可能にします。この関数は、+ 演算子を用いた従来の連結の、より効率的で判読しやすい代替手段となります。

以下に、シンプルな例を示します。

**Free
Ctl-Opt Main(CONCAT_1) ActGrp(*Caller);

Dcl-Pr pause ExtProc('sleep');
  time_to_sleep Uns(10) Value;
End-Pr;

Dcl-Proc CONCAT_1;

  Dcl-S firstName Char(20) Inz('John');
  Dcl-S lastName  Char(20) Inz('Doe');
  Dcl-S fullName  Char(50);

  fullName = %CONCAT(' ':firstName:lastName);
  SND-MSG *STATUS fullName %TARGET(*EXT);  // Output:John                Doe
  pause(3);

End-Proc CONCAT_1;

この例では、%Concatは、 firstName/span>、スペース、および lastName を単一の fullName 変数に結合しています。%Concatを使用することで、連結演算子を複数使用しなくて済むようになり、コードがすっきりします。このプログラムをコンパイルして実行すると、画面下部に以下が出力され、10秒間待機してから実行を続けます。

'John                Doe'

ちなみに、Snd-Msg命令を使用されたことはあるでしょうか。私は、Dsplyよりも、Snd-Msgの方がお気に入りです。Snd-Msgは、*Statusおよび%Target(*EXT)パラメーターと組み合わせて使用した場合に、メッセージがコマンド ラインの下に表示されるところが便利です。ほんの一瞬表示されるだけではないため、出力を確認するためにジョブログを表示する必要はありません。もちろん、Dsply命令を「pause(一時停止)」することもできますが、処理を続行するには、Enterを押す必要があります。私は、Snd-Msg命令で生じる処理の流れの方がお気に入りです。まだ使用したことがない場合は、試してみることをお勧めします。

では、先程の例に戻ります。出力は、見栄えがよくありません。これは、変数が20文字長であり、それらを初期化した値が、それぞれ4文字長および3文字長のみであるからです。見栄えをよくする方法は2通りあります。%Concatの実用的な使用法の1つは、以下のように、%Trim BIFと組み合わせて使用することでしょう。

  fullName = %Concat(' ':%Trim(firstName):%Trim(lastName));
  SND-MSG *STATUS fullName %TARGET(*EXT); // Output:John Doe

ずいぶんよくなりました。

そうした出力の体裁を整えるための方法としてさらに適切なのは、 firstName および lastName スタンドアロン変数の宣言をChar(20)からVarChar(20)へ変更することです。私はVarCharを使用する方が好みですが、どちらを使用しても、目的の結果が得られます。

%CONCATARR BIFは、配列の要素を連結する必要がある場合に特に有用です。%CONCATARRを使用しない場合は、配列をループして値を結合することになりますが、%CONCATARRを使用することで単純化できます。

**Free
Ctl-Opt Main(CONCAT_2) Ctl-Opt ActGrp(*Caller);

Dcl-Pr pause ExtProc('sleep');
  time_to_sleep Uns(10) Value;
End-Pr;

Dcl-Proc CONCAT_2;

  Dcl-S names VarChar(20) Dim(4) Inz(*Blanks);
  Dcl-S nameList VarChar(100);

  names(1) = 'Alice';
  names(2) = 'Bob';
  names(3) = 'Charlie';
  names(4) = 'David';
  nameList = %Concatarr(', ':names);
  SND-MSG *STATUS nameList %TARGET(*EXT); 
  // Output:Alice, Bob, Charlie, David
  pause(3);

End-Proc CONCAT_2;

上の例では、%CONCATARRの1つ目のパラメーターに、コンマと1つのブランク スペースを渡していることに注目してください。これにより、出力ストリングは、形式の整った名前のリストの体裁を保つことができます。しかし、RPGのすべてではないにしても多くのBIFと同様に、そのパラメーターは、式の結果がストリングである場合は、必要に応じてどのような式にすることもできます。

また、この例では、「names」配列の要素が4つのみ(Dim(4))であることにも留意が必要です(例を単純にするためです)。これは、実例として現実的ではありません。たとえば、配列をDim(1000)に変更して、プログラムを再度実行すると、出力は、「Alice, Bob, Charlie, David」の後に、996回の「, 」の繰り返しが続くようになります。配列内のブランクでない要素のみを対象とするように、%CONCATARRステートメントを修正することができます。

  nameList = %ConcatArr(', ':%SubArr(names:1:%Lookup(' ':names:1)-1));

この新たなバージョンは、%SUBARRおよび%LOOKUP BIFを追加することにより、配列の非ブランク値が含まれる部分のみを使用するように%CONCATARR BIFに指示します。結果のストリングの末尾の過剰な「コンマ-スペース」の問題の解決策としてより適切なのは、おそらく配列の定義を変更することでしょう。

**Free
Ctl-Opt Main(CONCAT_3) ActGrp(*Caller);

Dcl-Pr pause ExtProc('sleep');
  time_to_sleep Uns(10) Value;
End-Pr;

Dcl-Proc CONCAT_3;

  Dcl-S names VarChar(20) Dim(*Auto:10);
  Dcl-S nameList VarChar(100);

  names(1) = 'Alice';
  names(2) = 'Bob';
  names(3) = 'Charlie';
  names(4) = 'David';
  nameList = %Concatarr(', ':names);
  SND-MSG *STATUS nameList %TARGET(*EXT); 
  //Output:Alice, Bob, Charlie, David
  pause(3);

End-Proc CONCAT_3;

前の2つの例の出力は同じですが、2つ目の例の方が判読しやすいと思います。

最後になりますが、上の例はすべて、%CONCATおよび%CONCATARRによって、ストリング間にスペーサーの働きをするものを追加してストリングを結合する方法を説明しています。しかし、スペーサーなしでストリングを結合する必要がある場合には、どちらのBIFも、1つ目のパラメーターとして*NONEをサポートしています。

RPGの%CONCATおよび%CONCATARR組み込み関数を使用することで、ストリング操作機能を大幅に強化できます。それらの関数は、コードをすっきりさせて判読しやすくするだけでなく、手作業での連結によってエラーが引き起こされる可能性も低くします。

あわせて読みたい記事

PAGE TOP