COBOL

概要

非理系の事務員や官吏でもプログラミングできる言語として設計されたため、自然言語である英語に近い記述をめざしたコマンド語彙や構文（シンタックス）が採用されている。特に金額計算など事務処理用に広く使われている。COBOLは自然言語（英語）に近い構文を持つため、そのソースコードは記述が冗長にはなるが、可読性が高い。本のように、部、節、段落、文という階層で記述される。人によっては関数や数式だらけの言語よりもハードルが低い。リフレクションができないなど、モダンなプログラミング言語に比べて論理制御機能は貧弱である。一方、文字列解析や文字列編集、帳票、画面編集などの事務処理機能は豊富である。
COBOLは仕様の古い言語である。ただ、言語規格は拡張が続けられていて、2002年版以降ではオブジェクト指向にも対応して部品性を向上した。現実のプロジェクトで制約となるのは、COBOLの言語機能の不足よりは、稼働プラットフォーム、業務運用あるいは保守体制である場合も多い。
COBOLは、科学技術計算向けのFORTRANに次いで国際的な標準化が行われた、初期のプログラミング言語である。過去のバージョンとの互換性を重視した国際標準規格にしたがって多くのプラットフォームでコンパイラが開発されてきたので、COBOL to COBOLのマイグレーション（プラットフォームの更新）は比較的容易である。
膨大なCOBOLプログラムおよびそれらの処理するデータが、企業や政府機関に長年開発し続けられ稼働している。ガートナー発という情報によれば、メインフレームが世界1万サイト以上あって3万8千のレガシーシステムがあり、COBOLは全プログラム約3,100億行のうちの約65%の約2,000億行あって、毎年約50億行が増えているという。これはFORTRANとアセンブラを合わせた資産の数十億行に比べて圧倒的に多い。また、世界の商用データの約75%、商用トランザクションの80%以上（Google検索の200倍以上）である。COBOL開発者は85万人以上いるが、COBOL開発者の増加より減少がずっと速いという。
日本国内では、2004-2009年のプロジェクトデータ2,417件をまとめたIPAのレポートによると、1位のJava（25.4%）に次いでCOBOLは16.8%で2位である。
このように、誕生から半世紀たってもなお主流言語のひとつの座を占めている点で、他の初期の言語を引き離している。

誕生経緯

1950年代、事務処理言語は開発メーカーごとに異なっていた。その統一の必要性を認識していたアメリカ国防総省によって、事務処理用の共通言語の開発が提案され、CODASYL（Conference on Data Systems Languages、データシステムズ言語協議会）が設立された。そうした背景の下、1959年にCODASYLによって開発された共通事務処理用言語がCOBOLである。
その後、1960年1月にCODASYL執行委員会によって最初の仕様書が承認され、合衆国政府印刷局に送られた。この最初の仕様書は1960年4月に発行され、通称COBOL-60と呼ばれている。
COBOLの開発により、アメリカ政府の事務処理システムは全てCOBOLのみで納品されることとなった。これに伴い、COBOLは事務処理用言語として世界中に普及することになる。

現状

C言語やJavaなどの登場後も、COBOLは主に商用計算記述用として、主に金融業界や行政サービスなどで広く使用されている。
COBOL言語規格は、ローカル変数が作りにくく論理制御機能面が弱かった古典的言語からの脱皮を図っている。オブジェクト指向を採用し、入れ子プログラムを可能としたうえ、COBOLからCOBOLクラスライブラリのみならずJavaのクラスライブラリも呼べるようにするなど、相互運用性や共同開発容易性、安全性を改善してきている。
2019年現在、COBOL Cowboys社の調査では2000億行のCOBOLプログラムが現役で、フォーチュン500企業の90%がCOBOLプログラムを使い続けている。またマイクロフォーカス社のDerek Britton氏は「COBOLシステムを運用している組織が万単位で存在」「この言語が世界のトランザクション処理システムのうちの70％で用いられている」と述べた。

COBOLの文法の概要

主にANSI COBOL 1985の文法について述べる。

IDENTIFICATION DIVISION

「PROGRAM-ID」（プログラム識別名）を記述する。
「AUTHOR」（作成者名）、「DATE-WRITTEN」（作成日）等の文法もあったが廃要素となった。

ENVIRONMENT DIVISION

プログラムが実行されるコンピュータの環境を記述する。「ENVIRONMENT DIVISION」は、「CONFIGURATION SECTION」（環境節）と「INPUT-OUTPUT SECTION」（I-O節）に大別される。

DATA DIVISION

プログラムで使用する変数及びデータ並びにその型について記述する。プログラムで使用する変数及びデータのすべては、DATA DIVISIONで定義しなければならない。
「DATA DIVISION」は、「FILE SECTION」と「WORKING-STORAGE SECTION」に大別される。データの型の宣言は、PICTURE(PIC)句によって行う。
呼ばれたプログラムが呼んだプログラムから引数でデータを受け取る場合は、それらの包含構造や基本項目の型を呼ばれたプログラムの「LINKAGE SECTION」で宣言する。

PROCEDURE DIVISION

実行されるプログラムの内、実際の処理部分のコードを記述する。
引数を受け取る場合は、「PROCEDURE DIVISION USING 引数名 [, 引数名……]」という書き方をする。
上記3つのDIVISIONを記述したあとやっと「PROCEDURE DIVISION」で実行手順のコードを記述する文法であるため、COBOLは「前置きが長い」言語ともいえる。
COBOLの予約語の数は膨大で、文字数の長いものが多い。

実例1 (Hello world)

000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. HELLO.000300 PROCEDURE DIVISION.000400     DISPLAY 'HELLO, WORLD!'.000500     STOP RUN.
出力
HELLO, WORLD!
この例では DISPLAY命令を使って文字列をコンソールまたは標準出力に出力している。
COBOLはレコードレイアウトの決まったファイルの処理に使われることが多い。その場合はふつう、ファイル節（FILE SECTION）にレコードとそれを構成するデータ群の定義を書く。そして、実行部（PROCEDURE DIVISION）のREAD文、WRITE文などでそのレコードを読み書きする。

実例2 (Hello world)

作業領域節（WORKING-STORAGE SECTION）にデータを定義した例。
000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. HELLO.000300 DATA DIVISION.000400 WORKING-STORAGE SECTION.000500 01 HELLO1      PIC X(15).000600 01 HELLO2.000700     03 FILLER  PIC X(06) VALUE 'HELLO,'.000800     03 FILLER  PIC X(01) VALUE SPACE.000900     03 FILLER  PIC X(06) VALUE 'WORLD!'.001000     03 FILLER  PIC X(01) VALUE SPACE.001100     03 FILLER  PIC 9(01) VALUE 2.001200 PROCEDURE DIVISION.001300     MOVE 'HELLO, WORLD! 1' TO HELLO1.001400     DISPLAY HELLO1.001500     DISPLAY HELLO2.001600     STOP RUN.
出力
HELLO, WORLD! 1
HELLO, WORLD! 2

実例3 (Fizz Buzz)

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 > 100000800       EVALUATE FUNCTION MOD(I 3) = ZERO000900           ALSO FUNCTION MOD(I 5) = ZERO001000       WHEN TRUE  ALSO TRUE001100         DISPLAY 'FIZZBUZZ'001200       WHEN TRUE  ALSO FALSE001300         DISPLAY 'FIZZ'001400       WHEN FALSE ALSO TRUE001500         DISPLAY 'BUZZ'001600       WHEN OTHER001700         DISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)001800       END-EVALUATE001900     END-PERFORM.002000     STOP RUN.
出力
1
2
FIZZ
4
BUZZ
FIZZ
7
8
FIZZ
BUZZ
11
　（中略）
FIZZBUZZ
91
92
FIZZ
94
BUZZ
FIZZ
97
98
FIZZ
BUZZ
COBOLでは剰余を求める際に、商・剰余それぞれを格納する変数を定義した上でDIVIDE文を用いることが多いが、商は不要で剰余のみが知りたい場合や、それを変数に格納しておく必要が無い場合は、組み込み関数のMODを用いても良い。
また、COBOLの数字項目は定義された桁数よりも少ない桁数の値が格納された場合、ゼロパディングした状態で扱うため、このまま表示させると001、002、…、098と先頭に0が補われて表示されてしまう。桁で定義された数字項目に、正の整数が格納された場合、その最上位桁の位置は左からカラム目であるから、上記のようにDISPLAY I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)と記述することで、パディングされた0を除いた部分だけを表示させることが出来る。
なお、0、負の数、小数を扱う場合は、下記のように数字編集項目によるゼロサプレスとUNSTRING文を組み合わせることでパディングされた0を除いて表示させることが出来る。
000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. FIZZBUZZ.000300 DATA DIVISION.000400 WORKING-STORAGE SECTION.000500 01 I                                PIC S9(3).000600 01 HENSHU-IKI                       PIC X(4).000700 01 HENSHU-NUM REDEFINES HENSHU-IKI  PIC ---9.000800 01 DUMMY-IKI                        PIC X(1).000900 PROCEDURE DIVISION.001000     PERFORM VARYING I FROM -100 BY 1 UNTIL I > 100001100       EVALUATE FUNCTION MOD(I 3) = ZERO001200           ALSO FUNCTION MOD(I 5) = ZERO001300       WHEN TRUE  ALSO TRUE001400         DISPLAY 'FIZZBUZZ'001500       WHEN TRUE  ALSO FALSE001600         DISPLAY 'FIZZ'001700       WHEN FALSE ALSO TRUE001800         DISPLAY 'BUZZ'001900       WHEN OTHER002000         COMPUTE HENSHU-NUM = I002100         UNSTRING002200           HENSHU-IKI DELIMITED BY ALL SPACE002300           INTO DUMMY-IKI HENSHU-IKI002400         END-UNSTRING002500         DISPLAY HENSHU-IKI002600       END-EVALUATE002700     END-PERFORM.002800     STOP RUN.
COBOLの数字編集項目によるゼロサプレスは、単純に0を空白に置き換えるだけであるから、先頭に空白が生じる（＝整数部分が右寄せになる）。ゼロサプレスを行い更に先頭の空白も除去したい（＝左寄せにしたい）場合は、空白を区切り文字に指定してUNSTRING文を用いれば良い。上記の例では、UNSTRING文実行後の変数DUMMY-IKIには常に空白が入り（対象の文字列がいきなり空白＝区切り文字から始まり、その前には何も無いため、何も入らない＝空白が入る）、変数HENSHU-IKIには数字の部分だけが入る。

実例4 (Fizz Buzz)

000100 IDENTIFICATION DIVISION.000200 PROGRAM-ID. FIZZBUZZ.000300 DATA DIVISION.000400 WORKING-STORAGE SECTION.000500 01 I           PIC 9(3).000600 01 HENSHU-IKI  PIC X(8).000700 PROCEDURE DIVISION.000800     PERFORM VARYING I FROM 1 BY 1 UNTIL I > 100000900       MOVE SPACE TO HENSHU-IKI001000       IF FUNCTION MOD(I 3) = ZERO001100         MOVE 'FIZZ' TO HENSHU-IKI001200       END-IF001300       IF FUNCTION MOD(I 5) = ZERO001400         STRING001500           HENSHU-IKI DELIMITED BY SPACE001600           'BUZZ' DELIMITED BY SIZE001700           INTO HENSHU-IKI001800         END-STRING001900       END-IF002000       IF HENSHU-IKI = SPACE002100         MOVE I(3 - FUNCTION INTEGER(FUNCTION LOG10(I)):)002200           TO HENSHU-IKI002300       END-IF002400       DISPLAY HENSHU-IKI002500     END-PERFORM.002600     STOP RUN.
出力結果は実例3と同じであるが、STRING文による文字列の連結を利用することで、3の倍数かつ5の倍数（すなわち15の倍数）か否かの判定を無くしている。なお、上記の例におけるSTRING文は、Java等におけるhenshu_iki = henshu_iki + "Buzz";（あるいはこれを略記したhenshu_iki += "Buzz";）と同様の動作をする。