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
の部分で、
- `WS-COUNTER`が1からスタート (`FROM 1`)。
- `UNTIL WS-COUNTER > 5` (1 > 5 は偽) なのでループ実行 → `DISPLAY`で「1」が表示される。
- ループ1周終わり。`BY 1` なので `WS-COUNTER` が 2 になる。
- `UNTIL WS-COUNTER > 5` (2 > 5 は偽) なのでループ実行 → `DISPLAY`で「2」が表示される。
- ... これを繰り返す ...
- `WS-COUNTER` が 5 になる。
- `UNTIL WS-COUNTER > 5` (5 > 5 は偽) なのでループ実行 → `DISPLAY`で「5」が表示される。
- ループ5周終わり。`BY 1` なので `WS-COUNTER` が 6 になる。
- `UNTIL WS-COUNTER > 5` (6 > 5 は真!) なので、条件達成!ループを抜ける。
- `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プログラミングがもっと楽しく、もっとパワフルになりますよ!
自信を持って、どんどん活用していきましょう!
【関連記事】
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。