COBOL繰り返し処理の要!PERFORM VARYINGをマスターしよう

2025年4月9日水曜日

COBOL


COBOLプログラミングの学習、楽しんでいますか?

多くの人が「むむむ…」となりがちなのが、「同じ処理を何度も繰り返す」方法です。
特に、COBOLならではの『PERFORM VARYING』という命令文は、他のプログラミング言語とちょっと勝手が違うので、最初は戸惑うかもしれません。

でも、大丈夫!この記事を読めば、そんなPERFORM VARYINGの謎がスッキリ解けますよ。

基本のキから、実際のプログラムでの使い方、そして「あちゃー!」となりがちな落とし穴まで、まるっと解説します。

これを読めば、面倒な繰り返し処理もドンと来い!って思えるはず。さあ、一緒にCOBOLの世界をもっと深く探検してみませんか?

この記事で学べることリストです!

  • PERFORM VARYING文が何をするものか
  • PERFORM VARYING文の基本的な書き方のルール
  • カウンター変数、開始値、増減値、終了条件の設定方法
  • 実際のプログラム例(サンプルコード付き)
  • 使うときに気をつけるべきポイント(無限ループとか!)

読み終わるころには、自信を持ってPERFORM VARYINGを使えるようになっているはずです!

COBOL PERFORM VARYINGの繰り返しとは?

さて、COBOLでプログラムを作っていると、「この処理、10回繰り返したいなぁ」とか「このデータの数だけ同じことしたい!」なんて場面が絶対に出てきます。

そんなときに登場するのが繰り返し処理の命令です。

その中でも、特に「回数を決めて繰り返したい」「ある条件になるまで繰り返したい」ときに便利なのが、今回主役の`PERFORM VARYING`文なんですね。

これは、指定した変数(カウンター変数と呼びます)の値を少しずつ変えながら、決まった条件になるまで処理をぐるぐる繰り返してくれる、働き者の命令文です。

これを使いこなせると、プログラムがぐっと効率的になりますし、書くコードの量も減らせるんですよ。COBOLプログラマーを目指すなら、避けては通れない道、それがPERFORM VARYINGなのです!

PERFORM VARYINGの書き方

では、早速`PERFORM VARYING`文の書き方を見ていきましょう。
基本の形はこんな感じです。

PERFORM 段落名 VARYING カウンター変数 FROM 初期値 BY 増減値 UNTIL 終了条件.

もしくは、繰り返したい処理を`PERFORM`と`END-PERFORM`で挟む書き方もあります。

PERFORM VARYING カウンター変数 FROM 初期値 BY 増減値 UNTIL 終了条件
    繰り返したい処理...
    繰り返したい処理...
END-PERFORM.

なんだか呪文みたいですよね!でも大丈夫、一つ一つのパーツの意味を知れば簡単です。
これから、`VARYING`、`FROM`、`BY`、`UNTIL`の各部分(これらを「句」と呼びます)が何をしているのか、順番に解き明かしていきますね。

VARYING句:カウンター変数を指定

`VARYING`句は、「今回の繰り返しの主役、カウンター変数はこれだよ!」と宣言する部分です。
カウンター変数は、ループが何回目かを数えるための数字を入れる箱(変数)のこと。
事前に`DATA DIVISION`の`WORKING-STORAGE SECTION`で、数字が入る変数として定義しておく必要があります。</例えばこんな感じ。

WORKING-STORAGE SECTION.
01 WS-COUNTER PIC 9(3).  *> これがカウンター変数

上の例だと、`WS-COUNTER`という名前の変数(箱)を用意しています。`PIC 9(3)`は「999までの数字が入る箱だよ」という意味です。
ループの中で「今、何周目かな?」を知りたいときに使うのが、このVARYING句で指定した変数、と覚えてください。

FROM句:カウンター変数の初期値を設定

`FROM`句は、その名の通り「~から」という意味。
カウンター変数が、ループ開始時にいくつからスタートするかを決める部分です。

PERFORM VARYING WS-COUNTER FROM 1 ...

このように書けば、`WS-COUNTER`は「1」からスタートします。
たいていは1から始めることが多いですが、プログラムによっては0から始めたり、他の数字から始めることもできますよ。ループのスタートダッシュを決めるのが`FROM`句です!

BY句:カウンター変数の増減値を設定

`BY`句は、「ループが1周するごとに、カウンター変数をいくつずつ変えるか」を決める部分です。
いわば、ループの歩幅ですね。

PERFORM VARYING WS-COUNTER FROM 1 BY 1 ...

このように`BY 1`と書けば、ループが1回終わるごとに`WS-COUNTER`の値が1ずつ増えていきます(1, 2, 3...)。
もし`BY 2`と書けば2ずつ(1, 3, 5...)、`BY -1`と書けば1ずつ減っていく(例えば10から始めて10, 9, 8...)ようにもできます。普通は`BY 1`を使うことが多いでしょう。

UNTIL句:繰り返しを終了する条件を指定

さあ、一番のポイント、`UNTIL`句です!これは「~になるまで」という意味で、ループをいつ終えるか、そのゴール条件を決める、超重要な部分です。

PERFORM VARYING WS-COUNTER FROM 1 BY 1 UNTIL WS-COUNTER > 10.

この例だと、「`WS-COUNTER`の値が10より大きくなるまで繰り返してね」という意味になります。
つまり、`WS-COUNTER`が1, 2, ..., 10の間はループ内の処理を実行し、11になった瞬間に「条件達成!」となり、ループから抜け出します。
ここで使う条件式(`WS-COUNTER > 10`の部分)には、`=`(等しい)、`>`(より大きい)、`<`(より小さい)、`>=`(以上)、`<=`(以下)などの比較演算子が使えます。UNTIL句の条件は、ループ処理を実行する「前」に毎回チェックされる、という点をしっかり覚えておきましょう。これが無限ループを防ぐ鍵になります。

PERFORM VARYINGの使い方【サンプルコード】

理屈がわかったところで、実際に`PERFORM VARYING`を使ったプログラムを見てみましょう!
百聞は一見にしかず、動くコードを見るのが一番分かりやすいですからね。ここでは、シンプルな例と、もう少し実用的なテーブル(配列)処理の例を紹介します。

基本的なループ処理(1から5まで表示)

まずは超基本!カウンター変数を使って、1から5までの数字を順番に画面に表示するプログラムです。

▼ サンプルプログラム(SAMPLE01)

IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE01.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-COUNTER PIC 9(1). *> カウンター変数(1桁の数字)

PROCEDURE DIVISION.
MAIN-PROC.
    DISPLAY "ループを開始します!".

    PERFORM VARYING WS-COUNTER FROM 1 BY 1 UNTIL WS-COUNTER > 5
        DISPLAY "現在のカウンター: " WS-COUNTER
    END-PERFORM.

    DISPLAY "ループが終了しました!".
    STOP RUN.

▼ 実行結果

ループを開始します!
現在のカウンター: 1
現在のカウンター: 2
現在のカウンター: 3
現在のカウンター: 4
現在のカウンター: 5
ループが終了しました!

▼ 解説

どうでしょう?イメージ通りでしたか? PERFORM VARYING WS-COUNTER FROM 1 BY 1 UNTIL WS-COUNTER > 5の部分で、

  1. `WS-COUNTER`が1からスタート (`FROM 1`)。
  2. `UNTIL WS-COUNTER > 5` (1 > 5 は偽) なのでループ実行 → `DISPLAY`で「1」が表示される。
  3. ループ1周終わり。`BY 1` なので `WS-COUNTER` が 2 になる。
  4. `UNTIL WS-COUNTER > 5` (2 > 5 は偽) なのでループ実行 → `DISPLAY`で「2」が表示される。
  5. ... これを繰り返す ...
  6. `WS-COUNTER` が 5 になる。
  7. `UNTIL WS-COUNTER > 5` (5 > 5 は偽) なのでループ実行 → `DISPLAY`で「5」が表示される。
  8. ループ5周終わり。`BY 1` なので `WS-COUNTER` が 6 になる。
  9. `UNTIL WS-COUNTER > 5` (6 > 5 は真!) なので、条件達成!ループを抜ける。
  10. `END-PERFORM`の次の行(`DISPLAY "ループが終了しました!"`)に進む。

という流れで動いています。カウンター変数の値が条件を満たすまで、処理が繰り返される様子が分かりますね。

テーブル(配列)処理での活用例

COBOLでは、同じ種類のデータをまとめて扱う「テーブル(他の言語でいう配列)」をよく使います。
`PERFORM VARYING`は、このテーブルの各要素を順番に処理するのにピッタリなんです。
ここでは、テーブルに入っている3つの点数を合計する例を見てみましょう。

▼ サンプルプログラム(SAMPLE02)

IDENTIFICATION DIVISION.
PROGRAM-ID. SAMPLE02.

DATA DIVISION.
WORKING-STORAGE SECTION.
*> テーブル(配列)の定義
01 SCORE-TABLE.
   05 SCORE PIC 9(3) VALUE 070 OCCURS 3 TIMES. *> 点数(3桁)を3つ格納
*> ループと計算用変数
01 WS-IDX    PIC 9(1). *> テーブルの添え字(インデックス)用
01 WS-TOTAL  PIC 9(4) VALUE ZERO. *> 合計点用(4桁、初期値0)

PROCEDURE DIVISION.
MAIN-PROC.
    DISPLAY "点数テーブルの内容:".
    MOVE 85 TO SCORE(2). *> テーブルの2番目に85をセット
    MOVE 92 TO SCORE(3). *> テーブルの3番目に92をセット

    DISPLAY "1番目の点数: " SCORE(1).
    DISPLAY "2番目の点数: " SCORE(2).
    DISPLAY "3番目の点数: " SCORE(3).

    DISPLAY "--------------------".
    DISPLAY "合計点を計算します...".

    *> テーブルの要素数だけループ (1から3まで)
    PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 3
        *> WS-TOTALにSCORE(WS-IDX番目)を加算
        ADD SCORE(WS-IDX) TO WS-TOTAL
        DISPLAY WS-IDX "番目の点数(" SCORE(WS-IDX) ") を加算しました。"
    END-PERFORM.

    DISPLAY "--------------------".
    DISPLAY "合計点: " WS-TOTAL.
    STOP RUN.

▼ 実行結果

点数テーブルの内容:
1番目の点数: 070
2番目の点数: 085
3番目の点数: 092
--------------------
合計点を計算します...
1番目の点数(070) を加算しました。
2番目の点数(085) を加算しました。
3番目の点数(092) を加算しました。
--------------------
合計点: 0247

▼ 解説

このプログラムでは、`SCORE`という名前のテーブル(配列)に3つの点数を入れています。
注目は`PERFORM VARYING`文のループの中にある`ADD SCORE(WS-IDX) TO WS-TOTAL`の部分です。
ループのカウンター変数`WS-IDX`が1, 2, 3と変化するのに合わせて、`SCORE(1)`, `SCORE(2)`, `SCORE(3)`と、テーブルの要素を順番に参照して、合計点`WS-TOTAL`に足し込んでいます。このように、`VARYING`句のカウンター変数をテーブルの添え字(インデックス)として使うのは、COBOLプログラミングの定番テクニックです。便利でしょ?

PERFORM VARYINGの注意点

`PERFORM VARYING`は超便利ですが、使い方を間違えるとちょっと困ったことになる場合もあります。
ここでは、初心者が特に気をつけたいポイントを2つ、お伝えしますね。

無限ループに注意

一番怖いのが「無限ループ」です。これは、ループが終わる条件(UNTIL句)がいつまで経っても満たされず、プログラムが永遠に同じ処理を繰り返してしまう状態のこと。
例えば、

*> これは無限ループになる悪い例!
PERFORM VARYING WS-COUNTER FROM 1 BY 1 UNTIL WS-COUNTER < 0.
   DISPLAY "無限ループ中..."
END-PERFORM.

この例だと、`WS-COUNTER`は1から始まり、1ずつ増えていきます。でも、終了条件は「`WS-COUNTER`が0より小さくなるまで」です。1から増えていく数字が0より小さくなることは永遠にないので、このループは止まりません!
こうなると、プログラムが応答しなくなったり、システムに負荷をかけたりして大変なことになります。
`UNTIL`句の条件式が、カウンター変数の変化によっていつか必ず真(True)になるように、よーく考えて設定することが本当に肝心です。

カウンター変数のスコープとループ内での変更

`VARYING`句で指定したカウンター変数(例:`WS-COUNTER`)は、実はループの外でも使えます。ループが終わった直後にその変数の値を調べると、ループを抜けたときの値(`UNTIL`の条件が満たされたときの値)が入っています。
ただし!ループの中で、そのカウンター変数の値を勝手に変えるような処理を書くのは、基本的には避けた方が良いです。

*> あまり良くない例
PERFORM VARYING WS-COUNTER FROM 1 BY 1 UNTIL WS-COUNTER > 5
    DISPLAY WS-COUNTER
    IF WS-COUNTER = 3 THEN
        MOVE 1 TO WS-COUNTER *> ループ内でカウンターを変更!
    END-IF
END-PERFORM.

上の例のようにループ内でカウンターの値を直接いじると、ループの回数が思った通りにならなかったり、予期せぬ動きをしたりする原因になります。
カウンター変数は`PERFORM VARYING`文自身に任せて、ループの中では参照するだけにとどめておくのが安全策です。

【まとめ】PERFORM VARYINGを使いこなそう

お疲れ様でした!今回はCOBOLの繰り返し処理の要、`PERFORM VARYING`文について、基本から使い方、注意点までを解説しました。

ポイントをまとめると…

  • `PERFORM VARYING`は回数や条件を決めて処理を繰り返す命令文!
  • `VARYING`(変数), `FROM`(開始値), `BY`(増減値), `UNTIL`(終了条件)が基本セット!
  • カウンター変数をテーブルの添え字に使うと便利!
  • `UNTIL`句の条件設定は慎重に!無限ループに注意!
  • ループ内でカウンター変数をむやみに変えない!

最初はちょっと難しく感じるかもしれませんが、実際に自分でコードを書いて動かしてみるのが一番の近道です。

この記事のサンプルコードを参考に、ぜひ色々なパターンを試してみてください。
PERFORM VARYINGをマスターすれば、COBOLプログラミングがもっと楽しく、もっとパワフルになりますよ!

自信を持って、どんどん活用していきましょう!

【関連記事】

>> 今さら聞けない「COBOLとは?」

このブログを検索

  • ()

自己紹介

自分の写真
リモートワークでエンジニア兼Webディレクターとして活動しています。プログラミングやAIなど、日々の業務や学びの中で得た知識や気づきをわかりやすく発信し、これからITスキルを身につけたい人にも役立つ情報をお届けします。 note → https://note.com/yurufuri X → https://x.com/mnao111

QooQ