COBOLの書き方は初期からある「固定書式」と、後の言語仕様の改定で導入された「自由書式」がある。
自由書式は最近のプログラミング言語と同様、桁数の制約はなく、コードはインデントで整形する(インデントしてなくても、コンパイル自体はできる)。
ただ、自分がCOBOLに関わるのは既に稼働しているシステムの保守開発の時が多く、開発現場で自由書式のCOBOLソースコードを見たことはない。
よって、以降は固定書式を前提に記載する。
固定書式のルール
1行は80桁以内で、桁数によって領域が分かれている(コンパイラによっては1行あたり80桁の制限がないものもある)。
それぞれの領域には、何を記述するのかが定められている。
・1~6桁目は一連番号領域
ここには行番号を書く。
行番号は10や100単位で付番することが多い。
ただし、最近のコンパイラは一連番号領域を無視するので、行番号が正しくなくても問題にはならない。
そのため、全行を「000000」としたり、空白で埋めるケースもある。
・7桁目は標識領域
8桁目以降に何が書かれているのかを記号で示す。
以下のようなものがある。
空白なら、通常行(プログラムコード)。
*(アスタリスク)なら、コメント行。
・8~11桁目はA領域
各部(DIVISION)の開始宣言、節や段落の宣言などをこの領域から書き始める。
・12~72桁目はB領域
命令文などを記述する。
・73~80桁目は見出し領域
自由に記述できる(プログラムとして認識されない)。
コメントも書けるが、文字数に制限があるので、使わないことが多い。
4つの部(DIVISION)と節(SECTION)
COBOLのプログラムは、下記の4つの部(DIVISION)に分けて記述する。
部からさらに節、段落と、要素が分かれていく。
なお、使わない部は省略ができる。
■見出し部(IDENTIFICATION DIVISION)
プログラム名や作成者等を記述する。
■環境部(ENVIRONMENT DIVISION)
入出力ファイルや環境変数の情報等を記述する。
以下のような節(SECTION)がある。
・構成節(CONFIGURATION SECTION)
利用するコンピューター名や環境変数などを定義する。
・入出力節(INPUT-OUTPUT SECTION、FILE-CONTROL)
入力/出力するファイルに対する、プログラム内での名前や、格納先(パス)などを定義する。
■データ部(DATA DIVISION)
プログラム内で使用するデータ(ファイル内の項目・変数・定数など)の定義を記述する。
以下のような節(SECTION)がある。
・ファイル節(FILE SECTION)
入力/出力ファイルのデータ項目について定義する。
・作業場所節(WORKNG-STORAGE SECTION)
プログラム内で使用する変数や定数などを定義する。
・連絡節(LINKAGE SECTION)
外部プログラムとのデータのやりとりに関する情報を定義する。
■手続き部(PROCEDURE DIVISION)
実際の処理内容(ロジック)を記述する。
データ項目の定義方法
COBOLでデータ項目(変数・定数)を定義するときは、レベル番号を用いて集団項目・基本項目を定義する。
レベル番号とはデータ項目の階層や従属関係を定義するための番号。
「01」が最上位の階層で、数字が増えるほど下位の階層となる。
ロジック内で上位レベルの項目(集団項目)を参照すると、下位項目が連結された1つのデータ項目として扱われる。
具体的には、以下のように定義する。
なお、ここでは便宜上、変数名に日本語を使っている。
変数名に日本語を使うことはできるのだが、英語かローマ字を使うことが多い。
ただし、プロジェクトによってはコーディング規約で変数名に日本語を使うルールになっている事もあるので、プロジェクトのルールに従う。
000000 01 社員. 000000 03 社員コード PIC X(06). 000000 03 社員氏名 PIC X(30). 000000 03 入社日付. 000000 05 入社年 PIC 9(04). 000000 05 FILLER PIC X(01) VALUE '/'. 000000 05 入社月 PIC 9(02). 000000 05 FILLER PIC X(01) VALUE '/'. 000000 05 入社日 PIC 9(02). 000000 03 退社日付. 000000 05 退社年 PIC 9(04). 000000 05 FILLER PIC X(01) VALUE '/'. 000000 05 退社月 PIC 9(02). 000000 05 FILLER PIC X(01) VALUE '/'. 000000 05 退社日 PIC 9(02).
データ項目には文字列、数字(符号あり/なし、ゼロサプレス)、小数点などの型とサイズ(桁数)を指定する。
なお、「FILLER」は特別な項目名であり、何度でも定義できるが、ロジック内で参照はできない。
サンプルプログラム
プログラムソース
000000 IDENTIFICATION DIVISION. 000000 PROGRAM-ID. TEST_COB. 000000* 000000 ENVIRONMENT DIVISION. 000000 INPUT-OUTPUT SECTION. 000000 FILE-CONTROL. 000000* 入力ファイル指定(改行区切り) 000000 SELECT IN-FL ASSIGN TO 'infile.dat' 000000 ORGANIZATION IS LINE SEQUENTIAL. 000000* 000000* 出力ファイル指定(改行区切り) 000000 SELECT OUT-FL ASSIGN TO 'outfile.dat' 000000 ORGANIZATION IS LINE SEQUENTIAL. 000000* 000000 DATA DIVISION. 000000*ファイルのレイアウト定義 000000 FILE SECTION. 000000*入力ファイル 000000 FD IN-FL. 000000 01 IN-REC. 000000 03 IN-CODE PIC X(04). 000000 03 FILLER PIC X(01). 000000 03 IN-UNIT-PRICE PIC 9(05). 000000 03 FILLER PIC X(01). 000000 03 IN-QUANTITY PIC 9(02). 000000* 000000*出力ファイル 000000 FD OUT-FL. 000000 01 OUT-REC. 000000 03 OUT-NO PIC 9(03). 000000 03 FILLER PIC X(01). 000000 03 OUT-CODE PIC X(04). 000000 03 FILLER PIC X(01). 000000 03 OUT-UNIT-PRICE PIC Z(05). 000000 03 FILLER PIC X(01). 000000 03 OUT-QUANTITY PIC Z(02). 000000 03 FILLER PIC X(01). 000000 03 OUT-TOTAL-PRICE PIC Z(07). 000000 03 FILLER PIC X(01). 000000 03 OUT-PRICE-JUDGMENT PIC X(01). 000000* 000000*変数・定数の定義 000000 WORKING-STORAGE SECTION. 000000 01 FLG-EOF PIC X(01). 000000 01 WK-TOTAL-PRICE PIC 9(07). 000000 01 CONST-PRICE PIC 9(07) VALUE 500000. 000000* 000000 PROCEDURE DIVISION. 000000* 000000 PERFORM INIT-PROC. 000000 PERFORM MAIN-PROC. 000000 PERFORM END-PROC. 000000 STOP RUN. 000000* 000000*前処理 000000 INIT-PROC SECTION. 000000* 000000* 入力/出力ファイルを開く 000000 OPEN INPUT IN-FL. 000000 OPEN OUTPUT OUT-FL. 000000* 000000* フラグに初期値を設定 000000 MOVE SPACE TO FLG-EOF. 000000* 000000* 全桁カンマを設定してから、出力レコードを属性初期化 000000* FILLER項目は初期化されないため、カンマが残る 000000 MOVE ALL ',' TO OUT-REC. 000000 INITIALIZE OUT-REC. 000000* 000000* 1件目のレコードを読む 000000 PERFORM READ-FILE. 000000* 000000 INIT-PROC-EXIT. 000000 EXIT. 000000* 000000*主処理 000000 MAIN-PROC SECTION. 000000* 000000* フラグが設定されるまでループ 000000 PERFORM UNTIL FLG-EOF = '1' 000000* 000000* 変数のカウントアップ 000000 ADD 1 TO OUT-NO 000000* 000000* 入力ファイルの内容を転記 000000 MOVE IN-CODE TO OUT-CODE 000000 MOVE IN-UNIT-PRICE TO OUT-UNIT-PRICE 000000 MOVE IN-QUANTITY TO OUT-QUANTITY 000000* 000000* 数字の計算(合計金額=単価×数量) 000000 COMPUTE WK-TOTAL-PRICE = IN-UNIT-PRICE * IN-QUANTITY 000000 MOVE WK-TOTAL-PRICE TO OUT-TOTAL-PRICE 000000* 000000* 合計金額が一定額を超えているか判定 000000 IF WK-TOTAL-PRICE > CONST-PRICE 000000 MOVE '*' TO OUT-PRICE-JUDGMENT 000000 ELSE 000000 MOVE SPACE TO OUT-PRICE-JUDGMENT 000000 END-IF 000000* 000000* レコード書き出し 000000 WRITE OUT-REC 000000* 000000* 次のレコードを読む 000000 PERFORM READ-FILE 000000* 000000 END-PERFORM. 000000* 000000 MAIN-PROC-EXIT. 000000 EXIT. 000000* 000000*後処理 000000 END-PROC SECTION. 000000* 000000* 入力/出力ファイルを閉じる 000000 CLOSE IN-FL 000000 OUT-FL. 000000* 000000 END-PROC-EXIT. 000000 EXIT. 000000* 000000*ファイル入力処理 000000 READ-FILE SECTION. 000000* 000000* ファイルを読む 000000* レコードが無ければフラグを設定 000000 READ IN-FL 000000 AT END 000000 MOVE '1' TO FLG-EOF 000000 END-READ. 000000* 000000 READ-FILE-EXIT. 000000 EXIT.
実行結果
# 入力ファイル(infile.dat) A001,01000,60 B010,30000,20 A002,02000,40 B020,40000,30 C100,15000,30 # 出力ファイル(outfile.dat) 001,A001, 1000,60, 60000, 002,B010,30000,20, 600000,* 003,A002, 2000,40, 80000, 004,B020,40000,30,1200000,* 005,C100,15000,30, 450000,
