【COBOL学習|初心者向け】COBOLでも再帰処理を!RECURSIVE属性でプログラムを賢く呼び出す方法

1. 導入:再帰処理で複雑な問題をシンプルに

皆さんは、プログラムの中で「自分自身を呼び出す」という処理を書いたことはありますか?通常、COBOLはプログラム間で値を引き渡して処理を進めるのが基本ですが、階層構造のデータ処理や複雑な計算などでは、自分自身を呼び出す「再帰(Recursive)」という手法が非常に役立ちます。これを実現するのが今回解説する「RECURSIVE属性」です。この属性を使えば、同じロジックを何度も書く必要がなくなり、コードが驚くほどスッキリします。

2. 基礎知識:再帰処理とLOCAL-STORAGE SECTION

再帰とは、あるプログラムの中で、自分自身のプログラムを呼び出すことを指します。ここで重要なのが「データの管理場所」です。
通常のCOBOLプログラムで使われるWORKING-STORAGE SECTIONは、プログラムが一度読み込まれるとメモリ上の場所が固定されます。そのため、再帰呼び出しをすると、前の呼び出し時のデータが新しい呼び出しによって上書きされて壊れてしまいます。
そこで登場するのが LOCAL-STORAGE SECTION です。この領域は、呼び出されるたびに新しいメモリが確保され、終了すると解放されます。RECURSIVE属性を指定すると、この領域が自動的にスタック(一時的な作業場所)で管理されるようになるため、再帰が可能になるのです。

3. 実装・解決策:RECURSIVEの指定方法

実装は非常に簡単です。プログラムの識別子を定義するPROGRAM-ID行に「IS RECURSIVE」というキーワードを追加するだけです。これだけで、コンパイラに対して「このプログラムは自分自身を呼び出す設計ですよ」と伝えることができます。

4. サンプルプログラム:階乗計算で再帰を体験

以下のコードは、数値を再帰的に掛け合わせて階乗(例:5! = 5×4×3×2×1)を求める例です。

IDENTIFICATION DIVISION.
PROGRAM-ID. FACTORIAL-PROG IS RECURSIVE.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 IN-NUM PIC 9(02) VALUE 5.
01 RESULT PIC 9(10).

LOCAL-STORAGE SECTION.

  • 再帰呼び出しごとに生成される作業用変数

01 WS-WORK PIC 9(02).
01 WS-SUB-RES PIC 9(10).

PROCEDURE DIVISION.
CALL “FACTORIAL-PROG” USING IN-NUM RESULT.
DISPLAY “結果は: ” RESULT.
STOP RUN.

  • 再帰用エントリーポイント

ENTRY “FACTORIAL-PROG” USING BY REFERENCE WS-WORK WS-SUB-RES.
IF WS-WORK <= 1 THEN MOVE 1 TO WS-SUB-RES ELSE

  • 自分自身を呼び出す(引数を減らして再帰)

SUBTRACT 1 FROM WS-WORK
CALL “FACTORIAL-PROG” USING WS-WORK WS-SUB-RES

  • 戻ってきた値に現在の値を掛ける

ADD 1 TO WS-WORK GIVING WS-WORK
COMPUTE WS-SUB-RES = WS-SUB-RES WS-WORK
END-IF.
EXIT PROGRAM.

5. 応用・注意点:現場で気をつけるべきこと

RECURSIVE属性を使う際に最も注意すべき点は、「無限ループの防止」「メモリ消費」です。
再帰呼び出しには必ず「終了条件」が必要です。先ほどの例では、WS-WORKが1になったら再帰を止めるという条件がありました。これがないと自分自身を無限に呼び出し続け、メモリ不足(スタックオーバーフロー)でプログラムが異常終了します。
また、深い階層まで再帰しすぎるとメモリを大量に消費するため、業務プログラムでは「深さが最大何回までなら許容できるか」を事前に考慮して設計するようにしてください。再帰は強力な武器ですが、使いすぎには注意が必要ですよ!

コメント

タイトルとURLをコピーしました