もう迷わない!COBOL配列の宣言(OCCURS句)とアクセス方法
COBOLを学び始めたばかりだと、「配列」ってなんだか難しそう…と感じるかもしれませんね。
他のプログラミング言語にも似たような仕組みはありますが、COBOL特有の「OCCURS句」という書き方が出てきて、ちょっと戸惑うポイントかもしれません。
でも大丈夫!この記事を読めば、COBOLの配列がスッキリ理解できるようになりますよ。配列の基本的な考え方から、実際のプログラムでのデータの入れ方、取り出し方まで、ステップバイステップで丁寧に解説していきます。
この記事で学べること
- COBOLの配列って何? 基本のキホン
- 配列の作り方 OCCURS句のルール
- 配列の中身にアクセスする方法 添え字の使い方
- 簡単な配列プログラムの例
- 配列を使うときの注意点
COBOLの配列とは?~基本概念をやさしく理解しよう~
まず、「配列」って一体何者なんでしょう?
難しく考えなくてOKです。配列は、同じ種類のデータ(例えば、数字だけ、とか、文字だけ)を、まとめて整理しておくための「箱の集まり」みたいなものだとイメージしてください。
例えば、クラスの生徒30人分のテストの点数とか、1年間の各月の売上データとか、社員名簿みたいに、同じ種類の情報がたくさんある場合、一つ一つ別々の名前を付けて管理するのは大変ですよね?
そんな時に配列を使うと、データをひとまとめにして、番号(これを「添え字」といいます、後で詳しく説明しますね!)で「何番目のデータ」という風に区別できるので、管理がとっても楽になるんです。
COBOLプログラムでは、たくさんのデータを効率よく扱うために、配列がよく使われていますよ。
COBOL配列の定義方法:OCCURS句の書き方
では、COBOLで配列を作るにはどうすればいいのでしょうか?
ここで登場するのが「OCCURS句」です。文字通り「出現する」という意味で、データ項目が何回繰り返すか(=配列の要素がいくつあるか)を指定するのに使います。
基本的な書き方はこんな感じです。
01 配列を含む集団項目. 05 配列にしたいデータ項目 PIC X(10) OCCURS 5 TIMES.
上の例だと、「PIC X(10)」つまり10桁の文字列を入れる箱が、「OCCURS 5 TIMES」で5個用意される、という意味になります。これで、5つのデータ(例えば5人分の名前とか)をまとめて管理できる配列が作れました!簡単でしょう?
ポイントは、OCCURS句は単独では使えず、必ず「PIC句」などでデータ型や桁数を指定したデータ項目の後に付けて書く、という点です。
データ項目とOCCURS句の関係
OCCURS句は、どのデータ項目を配列にするのかをハッキリさせる必要があります。
COBOLのデータ定義(DATA DIVISION)では、データを階層構造で書くのが一般的です。こんな感じですね。
DATA DIVISION. WORKING-STORAGE SECTION. 01 STUDENT-RECORD. 05 STUDENT-NAME PIC X(20). 05 TEST-SCORES. 10 SUBJECT-SCORE PIC 9(3) OCCURS 3 TIMES. *> 国語、数学、英語の点数用
この例では、「STUDENT-RECORD」という大きなまとまりの中に、「STUDENT-NAME」(名前)と「TEST-SCORES」(テストの点数)があります。
さらに「TEST-SCORES」の中に、「SUBJECT-SCORE」(各教科の点数)があって、この「SUBJECT-SCORE」に対して「OCCURS 3 TIMES」を指定しています。
このように、OCCURS句は通常、ある集団項目(上の例だと TEST-SCORES)の下位にあるデータ項目(SUBJECT-SCORE)に付けて、そのデータ項目を複数個用意する、という形で使われます。レベル番号(01, 05, 10...)で構造を表すのがCOBOL流ですね。
配列の要素数を指定する
OCCURS句で一番分かりやすいのが、配列の大きさ、つまり「箱の数(要素数)」を決める部分です。
さっきの例 `OCCURS 5 TIMES` の `5` の部分ですね。ここに数字を入れることで、「このデータ項目をいくつ用意するか」を指定します。
例えば、
- `OCCURS 10 TIMES.` なら、10個の要素を持つ配列。
- `OCCURS 100 TIMES.` なら、100個の要素を持つ配列。
という具合です。COBOLの基本的な配列は、プログラムを書く時点で「要素数がいくつなのか」をあらかじめ決めておく「固定長」が一般的です。
プログラムの実行中に要素数を変える、といったことは少し複雑なテクニックが必要になります(今回は触れません)。
必要なデータの数に合わせて、適切な要素数を指定してあげましょう。
COBOL配列へのアクセス方法:添え字の使い方
さて、配列という「箱の集まり」を作ったら、次はそれぞれの箱にデータを入れたり、入っているデータを取り出したりする方法を知る必要があります。
ここで活躍するのが「添え字(そえじ)」または「インデックス」と呼ばれるものです。
配列は複数の箱が連なっていますが、それぞれの箱には「1番目」「2番目」「3番目」…というように、場所を示す番号が付いています。この番号が添え字です。COBOLでは、多くのプログラミング言語と違って、添え字は「1」から始まります。(0から始まる言語もあるので注意!)
配列の特定の要素にアクセスするには、配列名の後ろにカッコ `()` を付けて、その中に添え字を指定します。
配列名 (添え字)
例えば、さっき定義した `SUBJECT-SCORE PIC 9(3) OCCURS 3 TIMES.` という配列の、2番目の要素(数学の点数とか)にアクセスしたい場合は、
SUBJECT-SCORE (2)
と書きます。
この「添え字」には、直接数字を書くこともできますが、プログラムの中では数値を入れるための別のデータ項目(変数)を用意して、その変数名を指定するのが一般的です。
ループ処理などで添え字の値を変化させながら、配列の要素に順番にアクセスしていく、という使い方をよくします。
WORKING-STORAGE SECTION. 01 WS-INDEX PIC 9(1). *> 添え字用の変数 PROCEDURE DIVISION. MOVE 1 TO WS-INDEX. *> 添え字に1を設定 MOVE 85 TO SUBJECT-SCORE (WS-INDEX). *> 配列の1番目に85を格納 ADD 1 TO WS-INDEX. *> 添え字を2にする MOVE 92 TO SUBJECT-SCORE (WS-INDEX). *> 配列の2番目に92を格納
こんな風に、添え字用の変数(ここでは `WS-INDEX`)を使うことで、プログラムで柔軟に配列を操作できるようになります。
【実践】COBOL配列の使い方
理屈だけじゃなく、実際に動くプログラムを見てみましょう!
ここでは、5人分のテストの点数を配列に格納して、その合計点と平均点を計算して表示する、という簡単なサンプルプログラムを紹介します。
IDENTIFICATION DIVISION. PROGRAM-ID. ARRAY-SAMPLE. DATA DIVISION. WORKING-STORAGE SECTION. 01 SCORE-TABLE. 05 SCORE PIC 9(3) OCCURS 5 TIMES. *> 5人分の点数用配列 01 WS-IDX PIC 9(1). *> 添え字用変数 01 WS-TOTAL PIC 9(4) VALUE ZERO. *> 合計点用変数 (初期値ゼロ) 01 WS-AVERAGE PIC 9(3)V9(1). *> 平均点用変数 (小数点以下1桁) 01 WS-WORK-AVE PIC 9(4)V9(1). *> 平均計算用ワーク変数 PROCEDURE DIVISION. *> データ格納処理 (仮の点数を入れます) MOVE 75 TO SCORE(1). MOVE 88 TO SCORE(2). MOVE 62 TO SCORE(3). MOVE 95 TO SCORE(4). MOVE 80 TO SCORE(5). *> 合計点計算処理 (PERFORM VARYING でループ) PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 5 ADD SCORE(WS-IDX) TO WS-TOTAL END-PERFORM. *> 平均点計算処理 COMPUTE WS-WORK-AVE = WS-TOTAL / 5. MOVE WS-WORK-AVE TO WS-AVERAGE. *> 表示用に転記 *> 結果表示処理 DISPLAY "--- テスト結果 ---". PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 5 DISPLAY " " WS-IDX "番目の点数: " SCORE(WS-IDX) END-PERFORM. DISPLAY "------------------". DISPLAY " 合 計 点: " WS-TOTAL. DISPLAY " 平 均 点: " WS-AVERAGE. DISPLAY "------------------". STOP RUN.
実行結果
上のサンプルプログラムを実行すると、コンソール(実行画面)にはこのように表示されるはずです。
--- テスト結果 --- 1番目の点数: 075 2番目の点数: 088 3番目の点数: 062 4番目の点数: 095 5番目の点数: 080 ------------------ 合 計 点: 0400 平 均 点: 080.0 ------------------
ちゃんとデータが格納され、計算結果が表示されていますね!
サンプルプログラム解説
このプログラムの動きを順番に見ていきましょう。
- DATA DIVISION
- `SCORE PIC 9(3) OCCURS 5 TIMES.` で、3桁の数値を5個格納できる配列 `SCORE` を定義しています。これが点数を入れる箱ですね。
- `WS-IDX` は、配列の何番目にアクセスするかを指定するための添え字用変数です。
- `WS-TOTAL` は合計点を計算して入れておく変数。計算に使う変数は `VALUE ZERO.` で最初に0にしておくのがお約束です。
- `WS-AVERAGE` と `WS-WORK-AVE` は平均点を計算・表示するための変数です。小数点も扱えるように `V9(1)` を付けています。
- PROCEDURE DIVISION - データ格納
- `MOVE 75 TO SCORE(1).` のように、添え字(1~5)を直接指定して、配列 `SCORE` の各要素に仮の点数を格納しています。
- PROCEDURE DIVISION - 合計点計算
- `PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 5` これはループ処理の決まり文句です。「変数 `WS-IDX` の値を1から1ずつ増やしながら、5を超えるまで繰り返す」という意味。
- ループの中で `ADD SCORE(WS-IDX) TO WS-TOTAL` を実行しています。`WS-IDX` の値が 1, 2, 3, 4, 5 と変わっていくので、`SCORE(1)` から `SCORE(5)` までの値が順番に `WS-TOTAL` に足されていきます。ループと添え字を組み合わせることで、配列の全要素を効率よく処理できるのがポイントです。
- PROCEDURE DIVISION - 平均点計算
- `COMPUTE WS-WORK-AVE = WS-TOTAL / 5.` で、合計点 `WS-TOTAL` を人数 `5` で割って平均を計算し、`WS-WORK-AVE` に入れています。
- `MOVE WS-WORK-AVE TO WS-AVERAGE.` で、計算結果を表示用の変数に移しています(データ型を合わせるため)。
- PROCEDURE DIVISION - 結果表示
- ここでも `PERFORM VARYING` を使ってループし、`DISPLAY` 命令で配列 `SCORE` の中身(各点数)を順番に表示しています。
- 最後に合計点 `WS-TOTAL` と平均点 `WS-AVERAGE` を表示しています。
どうでしょう?配列と添え字、そしてループ処理を組み合わせるイメージが掴めましたか?
多次元配列の考え方(応用編)
ここまでは、データが一列に並んだ「一次元配列」を見てきました。でも、プログラムで扱いたいデータは、もっと複雑な場合もありますよね。
例えば、クラスの生徒ごと、かつ教科ごとの点数みたいに、縦と横がある「表」のような形式でデータを管理したい場合です。
そんな時に使うのが「多次元配列」です。COBOLでは、OCCURS句をネスト(入れ子に)することで、多次元配列を作ることができます。
例を見てみましょう。3人分の、国語・数学・英語の3教科の点数を管理する配列は、こんな風に定義できます。
01 STUDENT-SCORES. 05 STUDENT OCCURS 3 TIMES. *> 3人分 10 SUBJECT-SCORE PIC 9(3) OCCURS 3 TIMES. *> 各人の3教科分
この場合、`STUDENT` が3回繰り返され、そのそれぞれの中で `SUBJECT-SCORE` が3回繰り返される、という構造になります。イメージとしては、3行3列の表ですね。
アクセスする時は、添え字も2つ使います。例えば、2番目の生徒の、1番目の教科(国語)の点数にアクセスするには、
SUBJECT-SCORE (2, 1)
のように書きます。(書き方は処理系の仕様によって若干異なる場合もあります)
今回は「こんな考え方もあるんだな」くらいでOKです。まずは一次元配列をしっかりマスターしましょう!
COBOL配列を使う上での注意点
配列はとても便利ですが、いくつか気をつけたいポイントがあります。うっかりミスを防ぐために、しっかり確認しておきましょう。
添え字の範囲に注意
これが一番やりがちなミスかもしれません。
例えば、`OCCURS 5 TIMES.` と定義した配列があるとします。この配列にアクセスできる添え字の範囲は、1から5までです。
もし、プログラムの誤りで添え字が 0 になったり、6以上になったりした状態で、その配列要素にアクセスしようとするとどうなるでしょう?
COBOL(というか、実行環境によりますが)は、必ずしも「範囲外ですよ!」とエラーを出してくれるとは限りません。
場合によっては、プログラムが確保しているメモリの、配列とは関係ない部分を書き換えてしまったり、読み込んでしまったりして、予期せぬ誤動作や、最悪の場合プログラムの異常終了(ABEND アベンド)を引き起こす可能性があります。
ループ処理の終了条件の設定ミスなどで発生しやすいので、添え字が想定した範囲内に収まっているか、十分に注意してプログラムを書く必要があります。
配列の初期化を忘れずに
特に、配列を合計値の計算など、数値を累積していくような使い方をする場合、使う前に中身をきれいにしておく(初期化する)ことがとても大切です。
変数を定義しただけだと、そのメモリ領域には以前使われていたゴミデータが残っている可能性があります。これを初期化しないまま計算に使うと、とんでもない結果になってしまいます。
初期化の方法はいくつかあります。
- 定義時に初期化する (VALUE句):
配列の要素すべてを同じ値(例えばゼロ)で初期化したい場合は、`VALUE句` が使えます。01 COUNTER-TABLE. 05 COUNTER PIC 9(5) OCCURS 10 TIMES VALUE ZERO. *> 全要素を0で初期化
- プログラムの処理で初期化する (PERFORM):
プログラムの最初の方で、ループ処理(`PERFORM VARYING` など)を使って、配列の全要素に明示的にゼロやスペースなどを設定する方法もあります。PROCEDURE DIVISION. PERFORM VARYING WS-IDX FROM 1 BY 1 UNTIL WS-IDX > 10 MOVE ZERO TO COUNTER(WS-IDX) END-PERFORM. *> この後に配列を使った処理を書く...
どちらの方法を使うにしても、計算等で利用する配列は、必ず使用前に適切な値で初期化する、ということを忘れないでくださいね。
【まとめ】COBOL配列を使いこなそう!
お疲れ様でした!今回はCOBOLの配列について、基本的なところから見てきました。
ポイントを振り返ってみましょう。
- 配列は、同じ種類のデータをまとめて管理するための箱の集まり。
- COBOLでは OCCURS句 を使って配列を定義する。
- 配列の各要素には 添え字 (1から始まる番号) を使ってアクセスする。
- 添え字の範囲チェックと、使う前の初期化を忘れずに!
配列は、COBOLでたくさんのデータを扱うプログラムを作る上で、なくてはならない仕組みです。
最初はちょっと難しく感じるかもしれませんが、この記事で紹介したサンプルプログラムなどを参考に、ぜひ実際に手を動かして試してみてください。
【関連記事】
0 件のコメント:
コメントを投稿
注: コメントを投稿できるのは、このブログのメンバーだけです。