COBOLとは、事務処理用のプログラミング言語である。Common Business Oriented Language(汎商業目的言語)の略。高級言語。
概要
アメリカ国防総省によって統一事務処理言語の開発が提案され、1959年にアメリカのデータシステムズ言語協議会(CODASYL)が開発された。もともとは、世界最初に“バグ”を発見した、最初期のプログラマでもありコンピュータ開発者でもあった“アメイジング・グレース”こと、グレース・ホッパー女史が開発したコンパイラ言語である「FLOW-MATIC」がベース。このため、グレース・ホッパーは「COBOLの母」とも呼ばれている(ちなみに女性にして初の海軍将官(提督)でもある)。日本のごく一部のおっさんからは「COBOLのおばちゃま」とか呼ばれることもある。
アメリカ政府が主導で開発を行ったこともあり、COBOL誕生以降、アメリカ政府の事務システムは全てCOBOLによって製作された。現在でも事務処理用ホストコンピュータではCOBOLプログラムが主流として活躍している。
日本では銀行系のシステムで昔から使われている事が多い。2025年頃からCOBOLを扱うエンジニアが定年退職などでいなくなる為、開発やメンテナンスにかかる人員が確保できなくなる問題に直面しており、銀行系のシステムはCOBOLを使わないシステムへの改修を順次進めている。銀行間で共同のシステムを開発する事例もあるが、いずれにしてもCOBOLはシステム要件から除外している事が多い。
特徴
他のプログラミング言語と異なり、英語に近い構文になっているのが最大の特徴である。これは開発者であるグレース・ホッパーの理念によるもの、らしい。当時は機械語主体だったので、プログラミングする言語は標準化された英語をベースに作りやすい、可読性の高い(高水準)言語であるべきだという考えのもと作られている。無論、その反面、プログラム言語としては冗長になり過ぎるきらいもあり、その点についての批判もある。
文法
4つのDIVISION
COBOLは、「IDENTIFICATION DIVISION.」(見出し部)、「ENVIRONMENT DIVISION.」(環境部)、「DATA DIVISION.」(データ部)、「PROCEDURE DIVISION.」(手続き部)の4つのDIVISIONから成り立ち、これらを順番に記述しなければならない。
IDENTIFICATION DIVISION.
プログラムの見出しとなる部。
「PROGRAM-ID.」(プログラム番号)、「AUTHOR.」(プログラム作成者名)、「DATE-WRITTEN.」(作成日)などのプログラムの実行に関係しない文を記述する。更新履歴などを記述することもある。なお、「AUTHOR.」「DATE-WRITTEN.」は廃要素のため、最新規格のCOBOLでは使わないようにしよう。
ENVIRONMENT DIVISION.
「CONFIGURATION SECTION.」(環境節)と「INPUT-OUTPUT SECTION.」(I/O節)があり、環境節ではホストコンピューター名など、I/O節では入出力ファイルの情報を記述する。なお、環境節の「SOURCE-COMPUTER.」「OBJECT-COMPUTER.」等の記載は、コンパイル時に影響を与えることは無く、実質覚書のようなものである。そのため、省略されることも多い。
DATA DIVISION.
「FILE SECTION.」(ファイル節)と「WORKING-STORAGE SECTION.」(作業領域節)、「LINKAGE SECTION.」(引数節)がある。変数、定数の宣言は、PICTURE(PIC)句によって行う。
PROCEDURE DIVISION.
書式
COBOLでは、1行に80桁(カラム)まで記述できるが、実際にソースコードを記述できる領域が指定されている。一部例外もあるが、行の終端には必ずピリオド(.)を付けなければならない。
また、英字は大文字・小文字のどちらで記述しても良い(区別されない)が、かつて小文字に対応していないパンチカードや文字コードが存在していた頃の名残もあってか、大文字で記述することが一般的になっている。
1~6カラム
一連番号領域。
プログラムの行を識別するための領域。コンパイル時にこの領域は無視されるため、必ずしもコーディング上記述する必要はない。
7カラム
識別領域。
「*」を付けることで、その行をコメント行として認識される。通常は空白。
8~11カラム
A領域。
DIVISIONやSECTION等の見出しや作業領域節の「01」などを記述する。
12~72カラム
B領域。
命令文や各DIVISION、SECTIONを構成する文を記述する。ピリオドも含めて、全てこの領域に記述する必要がある。
73~80カラム
プログラム識別領域。
コメントとして扱われる領域。コンパイル時にこの領域は無視されるため、必ずしもコーディング上記述する必要はない。
ソースコードの例
プログラムを終了させる際には「STOP RUN」と記述しなければならない。
例1:Hello World
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. HELLOWORLD.
000300 PROCEDURE DIVISION.
000400 DISPLAY 'HELLO, WORLD!'.
000500 STOP RUN.
例2:FizzBuzz
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. FIZZBUZZ.
000300 DATA DIVISION.
000400 WORKING-STORAGE SECTION.
000500 01 I PIC 9(3).
000600 PROCEDURE DIVISION.
000700 PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100
000800 EVALUATE FUNCTION MOD(I 3) = ZERO
000900 ALSO FUNCTION MOD(I 5) = ZERO
001000 WHEN TRUE ALSO TRUE
001100 DISPLAY 'FIZZBUZZ'
001200 WHEN TRUE ALSO FALSE
001300 DISPLAY 'FIZZ'
001400 WHEN FALSE ALSO TRUE
001500 DISPLAY 'BUZZ'
001600 WHEN OTHER
001700 DISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)
001800 END-EVALUATE
001900 END-PERFORM.
002000 STOP RUN.
COBOLの数字項目は定義された桁数よりも少ない桁数の値が格納された場合、ゼロパディングした状態で扱うため、このまま表示させると001、002、…、098と先頭に0が補われて表示されてしまう。N 桁で定義された数字項目に、正の整数 n が格納された場合、その最上位桁の位置は左から N - [log10n] カラム目である[1]から、上記のように「DISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)」と記述することで、パディングされた0を除いた部分だけを表示させることが出来る。
例3:ユークリッドの互除法
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. EUCLID.
000300 ENVIRONMENT DIVISION.
000400 INPUT-OUTPUT SECTION.
000500 FILE-CONTROL.
000600 SELECT INDATA ASSIGN TO 'INDATA.TXT'
000700 ORGANIZATION IS LINE SEQUENTIAL FILE STATUS IS INDATA-STS.
000800 SELECT OTDATA ASSIGN TO 'OTDATA.TXT'
000900 ORGANIZATION IS LINE SEQUENTIAL.
001000 DATA DIVISION.
001100 FILE SECTION.
001200 FD INDATA.
001300 01 INDATA-REC.
001400 03 M PIC 9(18).
001500 03 FILLER PIC X(01).
001600 03 N PIC 9(18).
001700 FD OTDATA.
001800 01 OTDATA-REC.
001900 03 FILLER PIC X(38).
002000 03 GCD PIC 9(18).
002100 03 FILLER PIC X(01).
002200 03 ERR-FLG PIC X(01).
002300 WORKING-STORAGE SECTION.
002400 01 INDATA-STS PIC X(02).
002500 01 R PIC 9(18).
002600 PROCEDURE DIVISION.
002700 OPEN INPUT INDATA OUTPUT OTDATA.
002800 PERFORM UNTIL INDATA-STS NOT = ZERO
002900 READ INDATA
003000 NOT AT END
003100 MOVE INDATA-REC TO OTDATA-REC
003200 EVALUATE TRUE
003300 WHEN M IS NOT NUMERIC
003400 WHEN N IS NOT NUMERIC
003500 WHEN M = N AND ZERO
003600 MOVE '1' TO ERR-FLG
003700 WHEN OTHER
003800 MOVE ZERO TO ERR-FLG
003900 PERFORM UNTIL N = ZERO
004000 COMPUTE R = FUNCTION MOD(M N)
004100 COMPUTE M = N
004200 COMPUTE N = R
004300 END-PERFORM
004400 COMPUTE GCD = M
004500 END-EVALUATE
004600 WRITE OTDATA-REC
004700 END-READ
004800 END-PERFORM.
004900 CLOSE INDATA OTDATA.
005000 STOP RUN.
テキストファイルを入出力データとしている関係上、入力データとして不適切なものが渡された場合(具体的には、入力値M、Nの少なくとも一方に数字以外の文字が含まれている場合や、M、Nが両方とも0である場合[2])も考慮している。
例4-1:17歳ジェネレーター(実在日判定を副プログラムで実施)
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. SEVENTEEN.
000300*
000400 DATA DIVISION.
000500 WORKING-STORAGE SECTION.
000600* 生年月日
000700 01 BIRTH-YMD.
000800 03 BIRTH-Y PIC 9(4).
000900 03 BIRTH-MD PIC X(4).
001000* 計算基準日
001100 01 KIJUN-YMD.
001200 03 KIJUN-Y PIC 9(4).
001300 03 KIJUN-MD PIC X(4).
001400 01 KIJUN-YMD-9 REDEFINES KIJUN-YMD PIC 9(8).
001500* 直近の誕生日
001600 01 CHOKN-YMD.
001700 03 CHOKN-Y PIC 9(4).
001800 03 CHOKN-MD PIC X(4).
001900 01 CHOKN-YMD-9 REDEFINES CHOKN-YMD PIC 9(8).
002000* 年齢
002100 01 AGE.
002200 03 YEARS PIC 9(2).
002300 03 FILLER PIC N(1) VALUE N'歳'.
002400 03 DAYS PIC 9(5).
002500 03 FILLER PIC N(1) VALUE N'日'.
002600* エラーフラグ
002700 01 ERR-FLG PIC X(1).
002800*
002900 PROCEDURE DIVISION.
003000 DISPLAY N'生年月日を入力して下さい。'.
003100 ACCEPT BIRTH-YMD.
003200*
003300* 副プログラムで生年月日が実在日か判定する
003400 CALL 'ISDATE' USING BY CONTENT BIRTH-YMD
003500 BY REFERENCE ERR-FLG.
003600 IF ERR-FLG = '1'
003700* 生年月日が非実在日の時、エラー
003800 DISPLAY N'エラー:生年月日が非実在日'
003900 GO TO OWARI
004000 END-IF.
004100*
004200 DISPLAY N'計算基準日を入力して下さい。'.
004300 DISPLAY N'※今日の日付で計算する時:' '99999999'.
004400 ACCEPT KIJUN-YMD.
004500*
004600 IF KIJUN-YMD = ALL '9'
004700* 計算基準日がALL‘9’の時、今日の日付を設定
004800 MOVE FUNCTION CURRENT-DATE(1:8) TO KIJUN-YMD
004900 ELSE
005000* 副プログラムで計算基準日が実在日か判定する
005100 CALL 'ISDATE' USING BY CONTENT KIJUN-YMD
005200 BY REFERENCE ERR-FLG
005300 IF ERR-FLG = '1'
005400* 計算基準日が非実在日の時、エラー
005500 DISPLAY N'エラー:計算基準日が非実在日'
005600 GO TO OWARI
005700 END-IF
005800 END-IF.
005900*
006000* 直近の誕生日(年)、年齢(年数)を求める
006100 EVALUATE TRUE
006200 WHEN BIRTH-YMD > KIJUN-YMD
006300* 生年月日が計算基準日から見て未来の時、エラー
006400 DISPLAY N'エラー:まだ生まれていない'
006500 GO TO OWARI
006600 WHEN KIJUN-Y - BIRTH-Y <= 17
006700* 16歳以下 or 今年17歳になった
006800 COMPUTE CHOKN-Y = KIJUN-Y
006900 COMPUTE YEARS = KIJUN-Y - BIRTH-Y
007000 IF BIRTH-MD > KIJUN-MD
007100* 今年はまだ誕生日を迎えていない
007200 COMPUTE CHOKN-Y = CHOKN-Y - 1
007300 COMPUTE YEARS = YEARS - 1
007400 END-IF
007500 WHEN OTHER
007600* 昨年以前に17歳になった
007700 COMPUTE CHOKN-Y = BIRTH-Y + 17
007800 COMPUTE YEARS = 17
007900 END-EVALUATE.
008000*
008100* 直近の誕生日(月・日)を求める
008200 EVALUATE TRUE
008300 WHEN BIRTH-MD NOT = '0229'
008400 WHEN FUNCTION MOD(CHOKN-Y 004) = ZERO AND
008500 FUNCTION MOD(CHOKN-Y 100) > ZERO
008600 WHEN FUNCTION MOD(CHOKN-Y 400) = ZERO
008700* 2月29日生まれでない人 or 閏年の場合は誕生日に年を取る
008800 MOVE BIRTH-MD TO CHOKN-MD
008900 WHEN OTHER
009000* 2月29日生まれの人は、閏年以外は3月1日に年を取る
009100 MOVE '0301' TO CHOKN-MD
009200 END-EVALUATE.
009300*
009400* 年齢(日数)を求める
009500 COMPUTE DAYS = FUNCTION INTEGER-OF-DATE(KIJUN-YMD-9)
009600 - FUNCTION INTEGER-OF-DATE(CHOKN-YMD-9).
009700*
009800* 年齢を表示
009900 DISPLAY AGE.
010000 OWARI.
010100 STOP RUN.
COBOLの「INTEGER-OF-DATE」関数は、YYYYMMDD形式の8桁の数字を引数とし、1601年1月1日を第1日として通算日数を返すものである。ただし、引数に非実在日[3]や1601年1月1日より過去の日付を指定した場合は、処理系によってはアベンド[4]してしまうものもある。そのため、この例では「INTEGER-OF-DATE」関数の引数に指定する値が実在日か否かをCALL先のプログラムで判定している。CALL文のUSING指定は、CALL先のプログラムの「LINKAGE SECTION.」(引数節)の内容と、引数の数及びそれらの大きさ、並び順を必ず一致させなければならない。また、引数の前に「BY CONTENT」と記述した場合は、CALL先のプログラムで対応する引数の値を変更してもその内容はCALL元に引き継がれないが、「BY REFERENCE」と記述した場合は、CALL先のプログラムで対応する引数の値を変更するとその内容がCALL元に引き継がれる[5]。
例4-2:実在日判定(副プログラム)
000100 IDENTIFICATION DIVISION.
000200 PROGRAM-ID. ISDATE.
000300*
000400 DATA DIVISION.
000500 WORKING-STORAGE SECTION.
000600* 月末日テーブル
000700 01 LST-DAY-TBL VALUE '312931303130313130313031'.
000800 03 LST-DAY PIC 9(2) OCCURS 12.
000900*
001000 LINKAGE SECTION.
001100* 入力日付
001200 01 INPUT-YMD.
001300 03 INPUT-Y PIC 9(4).
001400 03 INPUT-MD.
001500 05 INPUT-M PIC 9(2).
001600 05 INPUT-D PIC 9(2).
001700* エラーフラグ
001800 01 ERR-FLG PIC X(1).
001900*
002000 PROCEDURE DIVISION USING INPUT-YMD ERR-FLG.
002100 EVALUATE TRUE
002200 WHEN INPUT-YMD IS NOT NUMERIC
002300 WHEN INPUT-YMD < '16010101'
002400 WHEN INPUT-M < 01
002500 WHEN INPUT-M > 12
002600 WHEN INPUT-D < 01
002700 WHEN INPUT-D > LST-DAY(INPUT-M)
002800* 入力日付に数字以外の文字が含まれている時、
002900* 入力日付が1601年1月1日より過去の時、
003000* 月が1~12の範囲に無い時、
003100* 日が1~月末日の範囲に無い時、エラー
003200 MOVE '1' TO ERR-FLG
003300 WHEN INPUT-MD NOT = '0229'
003400 WHEN FUNCTION MOD(INPUT-Y 004) = ZERO AND
003500 FUNCTION MOD(INPUT-Y 100) > ZERO
003600 WHEN FUNCTION MOD(INPUT-Y 400) = ZERO
003700* 入力日付が1601年1月1日以降の実在日
003800 MOVE ZERO TO ERR-FLG
003900 WHEN OTHER
004000* 入力日付が2月29日だが閏年でない時、エラー
004100 MOVE '1' TO ERR-FLG
004200 END-EVALUATE.
004300 EXIT PROGRAM.
主プログラム(CALL元のプログラム)からパラメータとして渡される変数は、「LINKAGE SECTION.」(引数節)に定義する。副プログラムを終了させ、主プログラムに戻るためには「EXIT PROGRAM」と記述する。「STOP RUN」だと主プログラムを含め全てのプログラムを終了させてしまうので注意。逆に、主プログラム上で「EXIT PROGRAM」と記述してもこの命令は無視される[6]。
関連商品
関連項目
脚注
- *[ ] はガウス記号であり、[x] は x 以下の最大の整数を表す。いわゆる「小数点以下切り捨て」である。
- *数値を格納する変数を「PIC 9(n)」で定義しているため、負の数の場合を考慮する必要は無い。もし「PIC S9(n)」で定義した場合は、負の数の場合も考慮する必要がある。
- *数字以外の文字を含んでいるのはもちろんのこと、8月32日、閏年以外の2月29日等ももってのほかである。
- *Abnormal End(異常終了)の略。
- *「BY CONTENT」、「BY REFERENCE」のいずれも記述しなかった場合は、「BY REFERENCE」を記述したものと見なされる。
- *「STOP RUN」や「EXIT PROGRAM」の代わりに「GOBACK」と記述した場合、記述したプログラムが主プログラムであれば「STOP RUN」と同様の動作をし、副プログラムであれば「EXIT PROGRAM」と同様の動作をする。使い分けが面倒であれば常に「GOBACK」と記述するようにしても良いかも知れない。
- 4
- 0pt