COBOL入門(TinyCOBOLでの学習)

姉妹編)WindowsでのOpenCOBOLインストール 目次

COBOLとは

COBOLはCOmonBusinessOrientedLanguageの略であり,事務処理をプログラミングすることを指向している。 具体的には表形式(2次元データ)の帳票を編集,作成する機能を言語自体がそなえており,その枠組みに沿って作れば比較的初心者でもビジネスに耐えるプログラムを作成できる。実際,プログラマの半数はCOBOLプログラマであるとさえ言われているし,現在良く話題に上るJavaやC++(C#)などへの書き換えもほとんど進んでいない。他の言語を習う前に,COBOLの類型的なデータ操作に慣れておいて損はない。

とはいうものの,COBOLは汎用機でしか動かない言語であって, なかなかPCやWSにコンパイラを移植することができなかったので, プロジェクトの現場に出ないと学習できない言語であった。 しかし,幸運にも TinyCOBOLというフリーのUnix用コンパイラがリリースされ, 安価なPC LinuxでもCOBOLを学習できるようになったので, 感謝の上利用させていただくことにする。 本レポートはLinuxでTinyCOBOLを学習するためのガイドである。 Linux用といっても,gcc+asがあれば動作するので, Windows+Cygwinでもできる。Windowsでの動作に興味のある方は、姉妹編の Windows(Cygwin)でのOpenCOBOLインストールを 参照されたい。OpenCOBOLは基本的にTiny-COBOLを日本語化したものであるので、本ページの 内容をwindowsで実践してみることができる。

COBOLの勉強の仕方

参考URLの上から5つを参考にして欲しい。 COBOL の講習、チュートリアル、サン プル(英語) が最もまとまっている。

書籍では,400冊以上のCOBOLの本が出版されている。
TinyCOBOLに付属しているサンプルコードは30セット以上あり,参考になるが,初学者にいきなりはきついので,COBOLの代表的命令をマスターした後に読むと良い。 実行する場合は,インストールディレクトリ/test.code/t00 に移動した後,makeを行って,testeを実行する。

Tiny-COBOLのインストール,コンパイル,実行

フリーのCOBOLコンパイラとしてTinyCOBOLの他にも,open-cobol, COBOL2Cなどの選択肢もあるが,インストールの容易性と,いくつかの テストの結果,著者のVine2.0環境ではtiny-cobol0.53が最も安定してコンパイル& リンクできたので選択した。Vine Linux2.5とMiracleLinux2.0ではtiny-cobol0.58でも安定していた。

TinyCOBOLは基本的に大文字,小文字を区別しない(文字データは区別する)。大文字しか許さない処理系もあるので移植の際は注意する。 また,0.57以前においてはファイルのREADにおいて,AT ENDは有効であるが, NOT AT ENDは文法エラーになる。これは, AT ENDブロックの中で, ファイルの終わりに到達したかのフラグを立てて,PERFORMのUNTIL条件で使うことで 回避する。0.58では使えるようになっている。

インストール(管理者のみ)

http://prdownloads.sf.net/tiny-cobol/
から,tinycobol-0.62.tar.gz をダウンロードし,/usr/localに保存を想定。
$./configure
(注:これに失敗した場合,$./configure --with-libdb=3 を行う。)
$make
#make install

コンパイルは以下のように,ファイル名の.cob以前の部分を指定する。
hello.cobを例にする。

$htcobol -v hello.cob
して
$ls
とすると,
hello
というファイルが出現する。これが実行プログラムである。
unixの場合,実行プログラム名=実行命令なので,
$hello
と入力すると,結果が出る。

サンプルコードのコンパイル(test.code/t00の場合)
$cd test.code/t00
Makefile(バッチファイル。JCLみたいなもの)の指示通りコンパイル。
$make
実行
$teste

最初の一歩

言語の最初のプログラムはいつでも,"HELLO WORLD!!" 。
一行表示だけのプログラムから,5千行のプログラムまでも
ほんの数歩。
何事もはじめるまでが大変で,クセになってしまえば後は何とかなるものでは?

まずエディタ(viやemacs。ここではvi)でhello.cobを作成する。

$vi hello.cob 
a(で挿入モード)
* hello.cob : The First and Shortest COBOL Program.
IDENTIFICATION  DIVISION.
PROGRAM-ID.     HELLO.
ENVIRONMENT     DIVISION.
DATA            DIVISION.
PROCEDURE       DIVISION.
DISPLAY 'HELLO WORLD!!'.
   STOP RUN.
(エディタから抜けるための操作:viでは、Esc ZZ)
$
解説)
正式には,全行の1番目から6番目のカラムは一連番号領域といって,行番号
を記入するが,TinyCOBOLではこの領域を省略できる。OpenCOBOLでは省略できないので注意。

先頭(本来なら7カラム目)に"*"があると,その行はコメントとみなされて,
プログラムの実行と無関係になる。

COBOLプログラムは4つのDIVISIONを必ず含む。
      IDENTIFICATION  DIVISION. はProgram-idを書くところと思ってよい。
      ENVIRONMENT     DIVISION. はマシン環境,入出力ファイル割り当てを書く。
ファイル名と入出力装置名の割り当てが最も重要であるが,今回はファイルを
使わないので空でよい。
      DATA            DIVISION. は利用する変数を宣言する。
hello.cobは変数を利用しないので,DATA DIVISIONは空で良い。

      PROCEDURE       DIVISION. は変数を利用した処理を書く。
      DISPLAY 'HELLO WORLD!!'.
で,'HELLO WORLD!!' を画面に表示する。
DISPLAYは定数や変数を画面に表示する命令である。
      STOP RUN.
プログラムの停止命令である。

hello.cobで有効な命令と言えるのは,DISPLAY文だけである。
VBやPerlであればPrint文1行ですむところを,各DIVISIONの中身がなくとも
宣言して使わなければいけないところが,COBOLの冗長なところであるが,
構造が明確でエラーを見つけやすいという面もある。

$htcobol -x hello
$hello
とすると,以下の結果が出る。
HELLO WORLD!!

COBOLでループ(繰り返し処理)は PERFORM を主に用いるので,例をあげる。
一番目と2番目,3番目と4番目は全く同じ結果になる。

*1から10までを表示する)
IDENTIFICATION DIVISION.
PROGRAM-ID.  ten1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Num1           PIC 99  VALUE ZEROS.
PROCEDURE DIVISION.
begin.
    PERFORM 10 TIMES
       Compute Num1 = Num1+1
       DISPLAY Num1
    END-PERFORM.
    STOP RUN.
*1から10までを表示する)
IDENTIFICATION DIVISION.
PROGRAM-ID.  ten2.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Num1           PIC 99  VALUE ZEROS.
PROCEDURE DIVISION.
begin.
    PERFORM Varying Num1 From 1 By 1 Until Num1 >10
       DISPLAY Num1
    END-PERFORM.
    STOP RUN.
*1から10までの和を求める)
IDENTIFICATION DIVISION.
PROGRAM-ID.  sum1.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Num1           PIC 99  VALUE ZEROS.
01  Sum1           PIC 99  VALUE ZEROS.
PROCEDURE DIVISION.
begin.
    PERFORM 10 TIMES
       Compute Num1 = Num1+1
       Compute Sum1 = Sum1 + Num1
    END-PERFORM.
    DISPLAY Sum1
    STOP RUN.
*1から10までの和を求める)
IDENTIFICATION DIVISION.
PROGRAM-ID.  sum2.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01  Num1           PIC 99  VALUE ZEROS.
01  Sum1           PIC 99  VALUE ZEROS.
PROCEDURE DIVISION.
begin.
    PERFORM Varying Num1 From 1 By 1 Until Num1 >10
       Compute Sum1 = Sum1 + Num1
    END-PERFORM.
    DISPLAY Sum1
    STOP RUN.

COBOL文法

日本語の部分がプログラムによって変わるところである。
{...}は...の1回以上の繰り返し, [...]は...の0か1回の出現(省略可)を表す。
(XXX | YYY | ..) は XXXかYYY..のどれか一つであることを表す。
  1. DIVISION
    COBOLプログラムは以下の4つのDIVISION(部、軍事用語で師団の意味)の組である。
    
    見出し部
    IDENTIFICATION DIVISION.
    PROGRAM-ID. プログラム名. 
    
    環境部
    ENVIRONMENT DIVISION.
    [CONFIGURATION SECTION.
    [SOURCE-COMPUTER. 開発マシン]
    [OBJECT-COMPUTER. 実行マシン]
    [SPECIAL-NAMES. 特別名称文]
    ]
    [INPUT-OUTPUT SECTION.
    {FILE-CONTROL. 
     SELECT ファイル名 ASSIGN TO デバイス名.
     I-O-CONTROL.
        入出力制御文
    }
    ]
    
    データ部
    DATA DIVISION.
    [FILE SECTION.
    {FD ファイル名.
    01 レコード定義文.
        フィールド定義文
    }
    ]
    
    [WORKING-STORAGE SECTION.
    { 01 レコード定義文.
        フィールド定義文
    }
    ]
    
     
    手続き部
    PROCEDURE DIVISION.
    [DECLARATIVES.
    {節名 SECTION.
       USE文.
    段落名. [文]]}]
    END DECLARATIVES.
    ]
                
    { 節名 SECTION.
     {段落名.
       {文}
     }
    }
    
  2. データ名
    データ名,手続き名のルールは以下のとおりである。
    30字以内。英字,数字,"-"で構成。"-"は先頭におけない。
    英字を1字以上含める。ただし手続き名は数字だけであってもよい。
    予約語は使用できない。
    
  3. 予約語

    ACCEPT, ACCESS, ADD, ADVANCING, AFTER, ALL, ALPHABET, ALPHABETIC, ALPHABETIC-LOWER, ALPHABETIC-UPPER, ALPHANUMERIC, ALPHANUMERIC-EDITED , ALSO, ALTER, ALTERNATES, AND, ANY, ARE, AREA, AREAS, ASCENDING, ASSIGN, AT, AUTHOR

    BEFORE, BIMARY, BLANK, BLOCK, BOTTOM, BY

    CALL, CANCEL, CD, CF, CH, CHARACTER, CHARACTERS, CLASS, CLOCK-UNITS , CLOSE, COBOL, CODE, CODE-SET, COLLATING, COLUMN, COMMA, COMMON, COMMUNICATION , COMP, COMPUTATIONAL, COMPUTE, CONFIGURATION, CONTAINS, CONTENT, CONTINUE, CONTROL, CONTROLS, CONVERTING, COPY, CORR, CORRESPONDING, COUNT, CURRENCY

    DATA, DATE, DATE-COMPILED, DATE-WRITTEN, DAY, DAY-OF-WEEK, DE, DEBUG-CONTENTS , DEBUG-ITEM, DEBUG-LINE, DEBUG-NAME, DEBUGGING, DECIMAL-POINT, DECLARATIVES, DELETE, DELIMITED, DELIMITER, DEPENDING, DESCENDING, DESTINATION, DETAIL, DISABLE, DISPLAY, DIVIDE, DIVISION, DOWN, DUPLICATES, DYNAMIC

    EGI, ELSE, EMI, ENABLE, END, END-ADD, END-CALL, END-COMPUTE, END-DELETE, END-DEVIDE, END-EVALUATE , END-IF, END-MULTIPLY, END-OF-PAGE, END-PERFORM, END-READ, END-RECIEVE, END-RETURN, END-REWRITE, END-SERCH, END-START, END-STRING, END-SUBTRACT, END-UNSTRING, END-WRITE, ENTER, ENVIRONMENT , EOP, EQUAL, ERROR, ESI, EVALUATE, EVERY, EXCEPTION, EXIT, EXTEND, EXTERNAL

    FALSE, FD, FILE, FILE-CONTROL, FILLER, FINAL, FIRST, FOOTING, FOR, FROM, FUNCTION

    GENERATE, GIVING, GLOBAL, GO, GREATER, GROUP

    HEADING, HIGH-VALUE, HIGH-VALUES

    I-O, I-O-CONTROL, IDENTIFICATION, IF, IN, INDEX, INDEXED, INDICATE, INITIAL, INITIALIZEINTO, INITIATE, INPUT, INPUT-OUTPUT, INSPECT, INSTALLATION, INTO, INVALID, IS

    (JAPANESE), JUST, JUSTIFIED

    (KANJI), KEY

    LABEL, LAST, LEADING, LEFT, LENGTH, LESS, LIMIT, LIMITS, LINAGE, LINAGE-COUNTER , LINE, LINE-COUNTER, LINES, LINKAGE, LOCK, LOW-VALUE, LOW-VALUES

    MEMORY, MERGE, MESSAGE, MODE, MODULES, MOVE, MULTIPLE, MULTIPLY

    NATIVE, NEGATIVE, NEXT, NO, NOT, NUMBER, NUMERIC, NUMERIC-EDITED

    OBJECT-COMPTER, OCCURS, OF, OFF, OMITTED, ON, OPEN, OPTIONAL, OR, ORDER, ORGANIZATION, OTHER, OUTPUT, OVERFLOW, PACKED-DECIMAL , PADDING, PAGE, PAGE-COUNTER, PERFORM, PF, PH, PIC, PICTURE, PLUS, POINTER, POSITION, POSITIVE, PRINTING, PROCEDURE, PROCEDURES, PROCEED, PROGRAM, PROGRAM-ID, PURGE

    QUEUE, QUOTE, QUOTES

    RANDAM, RD, READ, RECIEVE, RECORD, RECORDS, REDEFINES, REEL, REFERENCE, REFERENCES, RELATIVE, RELEASE, REMAINDER, REMOVAL, RENAMES, REPLACE, REPLACING, REPORT, REPORTING, REPORTS, RERUN, RESERVE, RESET, RETURN, REVERSED, REWIND, REWRITE, RF, RH, RIGHT, ROUNDED, RUN

    SAME, SD, SEARCH, SECTION, SECURITY, SEGMENT, SEGMENT-LIMIT , SELECT, SEND, SENTENCE, SEPARATE, SEQUENCE, SEQUENTIAL, SET, SIGN, SIZE, SORT, SORT-MERGE, SOURCE, SOURCE-COMPUTER , SPACE, SPACES, SPECIAL-NAMES, STANDARD, STANDARD-1, STANDARD-2, START, STATUS, STOP, STRING, SUB-QUEUE-1, SUB-QUEUE-2, SUBQUEUE-3, SUBTRACT, SUM, SUPPRESS, SYMBOLIC, SYNC, SYNCRONIZED

    TABLE, TALLYING, TAPE, TERMINAL, TERMINATE, TEST, TEXT, THAN, THEN, THROUGH, THRU, TIME, TIMES, TO, TOP, TRAILING, TRUE, TYPE

    UNIT, UNSTRING, UNTIL, UP, UPON, USAGE, USING

    VALUE, VALUES, VARYING

    WHEN, WITH, WORKING-STORAGE, WRITE

    ZERO, ZEROES, ZEROS

  4. PIC(PICTURE) - データの宣言
    DATA DIVISIONで行う。
    
    X: 数字以外の文字1字
    9: 数字1字
    Z: 9と同じだが,Zero Supress(0なら空白の置き換わる)される。
    S: "+" または "-" の演算符号。記憶場所はとらない。
    V: 想定小数点。記憶場所はとらない。
    ,: ","を挿入する位置。有効数字の左にあった場合は空白に置き換わる。
    B,0,/: これらを書いた位置に,空白,"0","/" が入る。
    .: "."の位置に小数点が挿入される。
    CR,DB: Credit(貸方)とDebit(借方)。データが負の場合にこれらが挿入される。
    \: 有効数字の直前にひとつ"\"を挿入。
    *: 有効数字の左側を"*"に置換。
    -: 数値が正の時は空白。負の時は数字の直前に"-"を挿入。
    +: 数値が負の時は空白。正の時は数字の直前に"+"を挿入。
    
    5桁の数字 COUNTを宣言する場合:
    02 COUNT PIC 99999.
     または 
    DATA DIVISION.
    02 COUNT PIC 9(5).
    
    10文字の文字列 NAME を宣言する場合。
    02 NAME PIC XXXXXXXXXX.
     または,
    02 NAME PIC X(10).
    
    注)日本メーカー製品で日本語全角文字を表すNが使えることがある。
    Nが使えない場合でも,X 2文字でN相当とすれば問題ない。
    ただし,Unixでは通常EUCでないとコンパイルできない。
    
  5. ACCEPT - データの入力
     accept データ名 [from 呼び名] フォーマット
    
    from がないと標準入力(キーボード入力)とみなされる。
    
    *キーボード入力の例
    IDENTIFICATION     DIVISION.
     program-id.        accept2.
     ENVIRONMENT        DIVISION.
     DATA               DIVISION.
    *作業領域の定義  ・・・  プログラムで使用する作業用領域の定義
     WORKING-STORAGE SECTION.
    *「入出力用作業領域を英数字タイプ3桁分でAAAという名前で定義する。」
     01  AAA      PIC  XXX.
    *** [手続き部] ・・・ プログラム処理を記述する部
     PROCEDURE    DIVISION.
    *    [ACCEPT]:キーボードからのデータの入力
         DISPLAY "INPUT 3 ALPHANUM>" WITH NO ADVANCING.
         ACCEPT   AAA.
    *    [DISPLAY]:画面上に表示させる
         DISPLAY  AAA.
         STOP RUN.
    
    * コマンドライン入力の例
     IDENTIFICATION DIVISION.
     PROGRAM-ID.    accept-from-cmdline.
    
     ENVIRONMENT     DIVISION.
     CONFIGURATION   SECTION.
     DATA DIVISION.
     WORKING-STORAGE SECTION.
    * コマンド全体を格納するTEMP変数
     01 TEMP PIC  X(256).
    * 手続き部:データを操作して、ロジックを実行する。
     PROCEDURE DIVISION.
    * コマンドライン全体をTEMPに格納
      ACCEPT  TEMP FROM COMMAND-LINE.
    * 表示
      DISPLAY TEMP.
      STOP RUN.
    
    日付,時間取得の例
    * currentTime.cob
    * $Date: 2002/04/08 04:37:54 $
    * $Author: shirokaz $
    * $Revision: 1.9 $
    *** <処理概要>
    *    現在時刻をディスプレイに表示する。
    *********************************************************************
    *** [見出し部] ・・・  プログラムの見出しを記述する部
    IDENTIFICATION DIVISION.
    * プログラムIDを記述
    PROGRAM-ID.  currentTime.
    * 作成者を記述
    AUTHOR.  shirokaz.
    *
    *********************************************************************
    *** [環境部]  ・・・  使用するコンピュータの環境を定義する部
    ENVIRONMENT DIVISION.
    *
    *********************************************************************
    *** [データ部] ・・・  プログラムで使用するデータの構造・属性を
    *                        定義する部
    DATA DIVISION.
    *    作業領域の定義  ・・・  プログラムで使用する作業用領域の定義
    WORKING-STORAGE SECTION.
    *「現在日付取得用作業領域を定義する。」
    * YYMMDD
    01 CurrentDate.
       02  CurrentYear     PIC 9(2).
       02  CurrentMonth    PIC 9(2).
       02  CurrentDay      PIC 9(2).
    *「日数取得用作業領域を定義する。」
    * YYDDD
    01 DayOfYear.
       02  FILLER          PIC 9(2).
       02  YearDay         PIC 9(3).
    *「現在時刻取得用作業領域を定義する。」
    * HHMMSSss   s = S/100
    01 CurrentTime.
       02  CurrentHour     PIC 9(2).
       02  CurrentMinute   PIC 9(2).
       02  FILLER          PIC 9(4).
    *********************************************************************
    *** [手続き部] ・・・  プログラム処理を記述する部
    PROCEDURE DIVISION.
    Begin.
    *  [ACCEPT 〜 FROM DATE]:現在日付の取得
       ACCEPT  CurrentDate FROM DATE YYMMDD.
    *        ;現在日付をCurrtntDateにYYMMDD形式で取得する
    *  [ACCEPT 〜 FROM DAY]:現在までの日数を取得
       ACCEPT  DayOfYear FROM DAY YYDDD.
    *        ;現在までの日数をDayOfYearにYYYYDDD形式で取得する
    *  [ACCEPT 〜 FROM TIME]:現在時刻を取得
       ACCEPT  CurrentTime FROM TIME.
    *        ;現在時刻をCurrtntTimeに取得する
    *
    *  [DISPLAY]:画面上に表示させる
       DISPLAY CurrentDay "/" CurrentMonth "/20" CurrentYear.
       DISPLAY "Today is day " YearDay " of the year".
       DISPLAY "The time is " CurrentHour ":"CurrentMinute.
    *        ;取得した現在日付・日数・現在時刻を画面に表示させる。
    *  [STOP RUN]:プログラムの終了
       STOP RUN.
    
  6. DISPLAY - データの表示
    DISPLAY データ名 [UPON 呼び名] [WITH NO ADVANCING]
    
    UPONがないと標準出力(ディスプレイ)とみなされる。
    WITH NO ADVANCINGがないと表示後に改行される。
    
  7. MOVE - データの転送
    MOVE { データ名  } TO { データ名 } 
    最初のデータ名は定数を含む。
    
    (1)基本項目、集団項目、レコードなどの転記を行う
    
    (2)転記の方法には次の2種類がある
     (a)数字転記
       送り出し側が基本項目で、受け取り側が数字項目の場合に行われる転記方法であり、
       右づめで転記される
       想定小数点の指定があるときには、受け取り側項目の小数点位置に桁合わせして転記される
       ・受け取り側の桁数が大きいときは、余った桁にゼロが埋められる
       ・受け取り側の桁数が小さいときは、けた落ちする
    
     (b)英数字転記
       受け取り側が英数字基本項目、あるいは受け取り側が集団項目である場合に行われる転記方法であり、
       左づめで転記される
    
       ・受け取り側の桁数が大きいときは、余った桁に空白が埋められる
       ・受け取り側の桁数が小さいときは、桁落ちする
    
    (3)英数字項目を数字項目へ転記してはならない
    
    (4)ある記憶領域を特殊な文字で埋める場合、表意定数を指定する
    
    (5)受け取り側が英数字編集項目または数字編集項目の場合は、転記の際に編集が行われる
      受け取り側が英数字編集項目の場合の転記規則は、受け取り側が英数字項目の規則に準じ、
      数字編集項目の場合は、数字項目の場合の規則に準じる
    
    (6)JUSTIFIED RIGHT(右桁よせ)
      英数字同士のMOVEで,データのPIC宣言の最後にJUSTIFIED RIGHTを指定すると,
    右側から転記される。
    
    例)
                   MOVE        "ABCDE" TO AAA.
    
  8. STRING, UNSTRING - 文字列の結合と分解
    STRING {データ名 DELIMITED BY データ名}
       INTO データ名 [WITH POINTER データ名]
       [ON OVERFLOW 文] [NOT ON OVERFLOW 文]
       [END-STRING] 
    
    UNSTRING データ名
       [DELIMITED BY [ALL] データ名 [OR [ALL] データ名]]
        INTO {データ名 [DELIMITER IN データ名] [COUNT IN データ名]}
       [WITH POINTER データ名] [TALLING データ名]
    
       [ON OVERFLOW 文] [NOT ON OVERFLOW 文]
       [END-UNSTRING] 
    
    例)
    *〔データ部〕
      77  AN-1  PIC X(6)   VALUE "STRING".
      77  AN-2  PIC X(5)   VALUE "STATE".
      77  AN-4  PIC X(6)   VALUE "MENT#0".
      77  AN-5  PIC X(4)   VALUE "#123".
      77  AN-7  PIC X(20)  VALUE "********************".
      77  ED-8  PIC 99     VALUE 3.
    *〔手続き部〕
         STRING AN-1 SPACE AN-2 DELIMITED BY SIZE
                AN-4 AN-5 DELIMITED BY "#"
                     INTO AN-7 WITH POINTER ED-8.
    
    *〔データ部〕
    01 NAMES.
     02 NAME PIC  X(20) OCCURS 10 TIMES.
    *〔手続き部〕
      UNSTRING TEMP DELIMITED BY ' ' INTO
        NAME(1) NAME(2) NAME(3) NAME(4) NAME(5)
        NAME(6) NAME(7) NAME(8) NAME(9) NAME(10).
    
       UNSTRINGは不定長形式のデータファイル(CSVなど)を扱うのに便利である。
    注)
     処理系によって日本語と英語の混在が許されないことがあるので注意。
    
  9. COMPUTE - 数値計算
    COMPUTE {一意名 [ROUNDED]} データ名 = 算術式 [ON SIZE ERROR 無条件文]
    
    算術演算子は,
    +, -, *, /, **(べき乗)の5つである。
    ADD,SUBTRACT, MULTIPLY, DIVIDEなどの命令と同等である。
    
    ROUNDEDは四捨五入の指示,ON SIZE ERRORは桁あふれ処理の指示である。
    
    例)
    
     IDENTIFICATION DIVISION.
    * プログラムIDを記述
     PROGRAM-ID.    ex-compute.
    *** [環境部]  ・・・ 使用するコンピュータの環境を定義する部
     ENVIRONMENT DIVISION.
    *** [データ部] ・・・ プログラムで使用するデータの構造・属性を
    *                        定義する部
     DATA DIVISION.
    *   作業領域の定義  ・・・ プログラムで使用する作業用領域の定義
     WORKING-STORAGE SECTION.
    * 「計算・結果表示用作業領域を定義する。」
     01 VA PIC 9(3) VALUE 35.
     01 VB PIC 9(3) VALUE 102.
     01 VC PIC 9(3) VALUE 72.
     01 VD PIC 9(2) VALUE 10.
     01 A1 PIC 9(5).
     01 A2 PIC S9(5).
     01 A3 PIC 99V999.
     01 A4 PIC 99.999.
     01 A5 PIC 999,999.
     01 A6 PIC ZZZZZ9.
     01 A7 PIC 9(20).
    *
    *** [手続き部] ・・・ プログラム処理を記述する部
     PROCEDURE DIVISION.
    *    [COMPUTE]:式で指定した計算を行う
         COMPUTE A1 = VA * VB.
    *            ;A1にVA×VBの計算結果を設定
         COMPUTE A2 = VA - VB.
    *            ;A2にVA−VBの計算結果を設定
         COMPUTE A3 = VB / VC.
    *            ;A3にVB÷VCの計算結果を設定(表示は99V999形式)
         COMPUTE A4 = VB / VC.
    *            ;A4にVB÷VCの計算結果を設定(表示は99.999形式)
         COMPUTE A5 = VB * VC.
    *            ;A5にVB×VCの計算結果を設定(表示は999,999形式)
         COMPUTE A6 = VB * VC.
    *            ;A6にVB×VCの計算結果を設定(表示はZZZZZ9形式)
         COMPUTE A7 = VC ** VD.
    *            ;A7にVCのVD乗の計算結果を設定
    *
    *    [DISPLAY]:画面上に表示させる
         DISPLAY "VA = " VA ", VB = " VB ", VC = " VC ", VD = " VD.
    *            ;各初期値を表示
         DISPLAY "VA * VB = " A1.
         DISPLAY "VA - VB = " A2.
         DISPLAY "VB / VC = " A3.
         DISPLAY "VB / VC = " A4.
         DISPLAY "VB * VC = " A5.
         DISPLAY "VB * VC = " A6.
         DISPLAY "VB ** VC = " A7.
    *            ;各計算結果を表示
    *    [STOP RUN]:プログラムの終了
         STOP RUN.
    
    実行結果)
    VA = 035, VB = 102, VC = 072, VD = 10
    VA * VB = 03570
    VA - VB = -00067
    VB / VC = 01.416
    VB / VC = 01.416
    VB * VC = 007,344
    VB * VC =   7344
    VB ** VC = 03743906242624487424
    
  10. EVALUATE
    EVALUATE (データ名 または TRUE) [ALSO (データ名 または TRUE)] 
      {(WHEN
      (ANY または 条件 または TRUE または [NOT] (データ名 または 定数 または 算術式))
       [ ALSO ( ANY または 条件 または TRUE または [NOT] (データ名 または 定数 または 算術式)] 
      文
      }
     [WHEN OTHER 文]
    [END-EVALUATE]
    
    要するに,こう書く。
    
          evaluate 項目名
              when "a"   perform 手続きA
              when "b"   perform 手続きB
              when "c"   perform 手続きC
              when other perform 手続きD
          end-evaluate.
    
  11. IF - 条件分岐
    IF その1)
     IF 条件 THEN 文
      [ ELSE 文 ]
     END-IF
    
    IF その2)
     IF 条件 THEN  文 または NEXT SENTENCE  
      [{ELSE 文 または ELSE NEXT SENTENCE }]
     END-IF
    
    条件:
     ( データ名 または 定数 または 算術式 ) 
      [ IS [NOT] = または
       IS [NOT] < または
       IS [NOT] > または
       IS [NOT] EQUAL TO または
       IS [NOT] LESS THAN または
       IS [NOT] GREATER THAN または
       IS GREATER THAN OR EQUAL TO または
       IS >= または
       IS LESS THAN OR EQUAL TO または
       IS <= または
     (データ名 または 定数 または 算術式 ) 
    
    例)
               IF  A > 1 THEN GO TO AAA
                         ELSE GO TO BBB
               END-IF.
    
  12. GO TO - 制御のジャンプ
     GO TO 手続き名
    
  13. OCCURS - 配列宣言
           01    AAA.
            02   B OCCURS 2
              03 C OCCURS 5  PIC XXX.
    
    C(1 1) C(1 2) C(1 3) C(1 4) C(1 5) 
    C(2 1) C(2 2) C(2 3) C(2 4) C(2 5) 
    10のデータを宣言したことになる。
    
  14. PERFORM - 実行ブロック(繰り返し)
    注)THRU は THROUGH の省略であり,どちらでも良い。
    データ名は一意名(変数名)または整数(変数または定数)である。
    
    【書き方1】  文の組を1回だけ実行する
    
    PERFORM 手続き名 [THRU 手続き名]
    PERFORM 無条件文 END-PERFORM
    
    【書き方2】  文の組の実行を、特定の回数だけ繰り返す
    
    PERFORM 手続き名 [THROU 手続き名] [データ名 TIMES]
    PERFORM データ名 TIMES 無条件文 END-PERFORM
    
    【書き方3】  文の組の実行を、条件を満足するまで繰り返す
    
    PERFORM  手続き名 [THRU 手続き名 ] 
       [WITH TEST (BEFORE | AFTER)] UNTIL  条件  
       [無条件文-1  END-PERFORM]                                        
    
    【書き方4】  文の組の実行を条件を満足するまで繰り返すと同時に、
    繰り返し回数に応じてデータ項目または指標名の値を変化させる
    
    PERFORM 手続き名 [THRU 手続き名 ]
       [WITH TEST (BEFORE | AFTER)] 
       VARYING  (変数名| 指標名)
       FROM (変数名 | 指標名 | 定数)  BY  (変数名 | 定数名) UNTIL 条件
       [AFTER (変数名 | 指標名 ) FROM (データ名 | 指標名)  BY  データ名  UNTIL 条件]
       [無条件文-1 END-PERFORM]                                        
    
    【書き方5】  文の組の実行を無条件に繰り返す
    
    PERFORM  WITH  NO  LIMIT                                        
       無条件文 END-PERFORM                                          
                      
    例)
    
    PROCEDURE DIVISION.
    * ラベル Begin を定義
    Begin.
    *   Starting to run program  を表示
        DISPLAY "Starting to run program"
    * うちPERFORM の例
    * END-PERFORMまでの処理を3回繰り返す。
        PERFORM 3 TIMES
           DISPLAY ">>>>This is an in line Perform"
        END-PERFORM
    * ここまでを3回繰り返す
    * Finsished in line Perform  を表示する
        DISPLAY "Finished in line Perform"
    * 内PERFORM ここまで
    *
    * 外PERFORMの例
    *  OutOfLineEG を NumOfTimes 回繰り返す。
        PERFORM OutOfLineEG NumOfTimes TIMES
    * Back in Begin. About to Stopを表示
        DISPLAY "Back in Begin. About to Stop".
    *  プログラム終了
        STOP RUN.
    * PERFORM文で呼び出されるところ OutOfLineEG を定義
    OutOfLineEG.
    * >>>> This is an out of line Perform を表示
        DISPLAY ">>>> This is an out of line Perform".
    
  15. OPEN,CLOSE - ファイル操作の準備,後処理
    OPEN {INPUT {ファイル名−1} 
       OUTPUT {ファイル名−2}
       I-O {ファイル名−3}
       EXTEND {ファイル名−4}
    
    CLOSE {ファイル名}  
    
    ファイル名−1には、入力ファイルのファイル名を指定する
    ファイル名−2には、出力ファイルのファイル名を指定する
    ファイル名−3には、入出力ファイルのファイル名を指定する
    ファイル名−4には、拡張出力ファイル(順アクセスの大記憶装置のファイルのみ)
    のファイル名を指定する
    
    例)
           file-control.
               select inp-fl assign "b:\rei.dat"
                      organization line sequential.
               select out-fl assign "b:\rei.out"
                      organization line sequential.
    
               open input  inp-fl.
               open output out-fl.
    
               close inp-fl, out-fl.
    
  16. READ,WRITE - ファイル入出力
     READ ファイル名 [NEXT] RECORD
                          AT END 文
                     [NOT AT END 文] 
     [END-READ]
    
     WRITE レコード名 
     [ AFTER ADVANCING { PAGE 整数 [ LINE or LINES *}
     [ END-WRITE ]
    
    例)
    
    IDENTIFICATION DIVISION.
    PROGRAM-ID.  ReadRelative.
    AUTHOR.  MICHAEL COUGHLAN.
    * Reads a Relative file directly or in sequence
    
    ENVIRONMENT DIVISION.
    INPUT-OUTPUT SECTION.
    FILE-CONTROL.
    SELECT SupplierFile ASSIGN TO "RELSUPP.DAT"
           ORGANIZATION IS RELATIVE
           ACCESS MODE IS DYNAMIC
           RELATIVE KEY IS SupplierKey
           FILE STATUS IS Supplierstatus.
           
    DATA DIVISION.
    FILE SECTION.
    FD SupplierFile.
    01  SupplierRecord.
        88 EndOfFile  VALUE HIGH-VALUES.
        02 SupplierCode            PIC 99.
        02 SupplierName            PIC X(20).
        02 SupplierAddress         PIC X(50).
    
    
    WORKING-STORAGE SECTION.
    01  SupplierStatus             PIC X(2).
        88 RecordFound             VALUE "00".
    
    01  SupplierKey                PIC 99.
    
    01  PrnSupplierRecord.
        02    PrnSupplierCode      PIC BB99.
        02    PrnSupplierName      PIC BBX(20).
        02    PrnSupplierAddress   PIC BBX(50).
    
    01  ReadType                   PIC 9.
        88 DirectRead              VALUE 1.
        88 SequentialRead          VALUE 2.
    
    
    PROCEDURE DIVISION.
    BEGIN.
        OPEN INPUT SupplierFile.
        DISPLAY "Read type : Direct read = 1, Sequential read = 2 --> "
                 WITH NO ADVANCING.
        ACCEPT ReadType.
    
        IF DirectRead
            DISPLAY "Enter supplier code key (2 digits) --> "
                        WITH NO ADVANCING
            ACCEPT SupplierKey
            READ SupplierFile
                INVALID KEY DISPLAY "SUPP STATUS :-", SupplierStatus
            END-READ
            PERFORM DisplayRecord
        END-IF
    
        IF SequentialRead
            READ SupplierFile NEXT RECORD
                AT END SET EndOfFile TO TRUE
            END-READ
            PERFORM UNTIL EndOfFile
                PERFORM DisplayRecord
                READ SupplierFile NEXT RECORD
                    AT END SET EndOfFile TO TRUE
                END-READ
            END-PERFORM
        END-IF
    
        CLOSE SupplierFile.
        STOP RUN.
    
    DisplayRecord.
        IF RecordFound
            MOVE SupplierCode TO PrnSupplierCode
            MOVE SupplierName TO PrnSupplierName
            MOVE SupplierAddress TO PrnSupplierAddress
            DISPLAY PrnSupplierRecord
        END-IF.
    
    
    
  17. SEARCH - データの検索
    SEARCH データ名 [VARYING データ名] [AT END 文]
     {WHEN 条件 (文 または NEXT SENTENCE)}
     [END-SEARCH]
    
    SEARCH ALL データ名 [AT END 文]
     WHEN (データ名 = データ名) または 条件 
     { AND (データ名 = データ名) または 条件) }
     (文 または NEXT SENTENCE)
     [END-SEARCH]
    
    
    identification division.
    program-id. searchSample.
    environment division.
    data                     division.
    working-storage          section.
    01  SEISEKI-TBL.
        05                   PIC X(8) VALUE "MIHO 100".
        05                   PIC X(8) VALUE "AKINA030".
        05                   PIC X(8) VALUE "RIE  050".
        05                   PIC X(8) VALUE "MIKA 060".
        05                   PIC X(8) VALUE "KEIKO090".
    01  TBL REDEFINES SEISEKI-TBL.
        05  DE-TA OCCURS 5 INDEXED BY SIHYOU.
            10  NAMAE        PIC X(5).
            10  TENSUU       PIC 999.
    01  SIRABERU-NAMAE       PIC X(5).
    01  MESAGE.
        10  NAMAE2           PIC X(5).
        10  M1               PIC X(12) VALUE "さんの点数は".
        10  TENSUU2          PIC ZZ9.
        10  M2               PIC X(6) VALUE "点です".
    
    PROCEDURE                DIVISION.
    HAJIME.
        ACCEPT SIRABERU-NAMAE.
        SET SIHYOU TO 1.
        SEARCH DE-TA AT END DISPLAY "該当者なしです"
               WHEN SIRABERU-NAMAE = NAMAE (SIHYOU)
                    MOVE NAMAE (SIHYOU) TO NAMAE2
                    MOVE TENSUU (SIHYOU) TO TENSUU2
                    DISPLAY MESAGE.
        STOP RUN.
    
  18. INSPECT - データのカウント,置換
    置換)
     INSPECT データ名 REPLACING 
     (ALL または LEADING または FIRST) データ名 BY データ名
     CHARACTERS BY データ名
     (BEFORE または AFTER) 
     [INITIAL データ名]
    
    カウント)
     INSPECT データ名 TALLYING データ名 FOR 
     (ALL または LEADING または FIRST) データ名 CHARACTERS)
     (BEFORE または AFTER) [INITIAL データ名]
    
    例)
    
    IDENTIFICATION   DIVISION.
    PROGRAM-ID.      SAMPLE.
    DATA             DIVISION.
    WORKING-STORAGE SECTION.
    01 男性数       PIC 9(4) VALUE ZERO.
    01 女性数       PIC 9(4) VALUE ZERO.
    CONSTANT        SECTION.
    01 参加者名     PIC X(50) VALUE "Mr.Brown Mrs.Brown Mr.Jones Mrs.Margaret Mr.Smith".
    PROCEDURE        DIVISION.
      DISPLAY "旅行参加者名: " 参加者名.
      DISPLAY " ".
      INSPECT 参加者名 TALLYING 男性数 FOR ALL "Mr.".
      DISPLAY "男性は、" 男性数 "名です。".
      INSPECT 参加者名 TALLYING 女性数 FOR ALL "Mrs.".
      DISPLAY "女性は、" 女性数 "名です。".
    END PROGRAM SAMPLE.
    

分割コンパイル&リンク

大規模なプログラムになると,メインテナンスのためにファイルを分割して作成,コンパイルし,後でリンクして実行モジュールを作る。以下は2つに分けた例である。

--- メインプログラム ---
* caller.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. caller.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 HELLO PIC X(12) VALUE "Hello World!".

PROCEDURE DIVISION.
CALL "callee" USING HELLO.
STOP RUN.
--- 副プログラム ---
* callee.cob
IDENTIFICATION DIVISION.
PROGRAM-ID. callee.
ENVIRONMENT DIVISION.
DATA DIVISION.
LINKAGE SECTION.
01 HELLO PIC X(12).

PROCEDURE DIVISION USING HELLO.
DISPLAY HELLO.
STOP RUN.
USING HELLOのHELLO が普通の言語の関数の引数ということになる。

まずそれぞれをオブジェクトプログラムにコンパイルする。
$ htcobol -c caller.cob
$ htcobol -c callee.cob
cコンパイラでcobolライブラリ,数学ライブラリとリンクする。
$ gcc -o caller caller.o callee.o -lhtcobol -lm
実行する。
$ caller
 Hello World!
注)このような手順を書いたシェルファイルを作って実行しても良い。
ただし大きなシステムになるとMakefileを作って,無駄な再コンパイルを
防いだほうが良い。

CGI化

  1. ファイル構成
    肥満度判定システム
    ~/public_html/cgi-bin/fatness/ index.html フレームHTML fatness.html フォーム入力HTML fatness.cgi パラメータ解釈,cobol起動perlスクリプト cgi-lib.pl CGIライブラリ fatness fatness.cobをコンパイルしたモジュール アクセス権限はディレクトリごと 755 にしておけば,大抵の場合安全である。
  2. index.html
    <HTML>
    <HEAD><TITLE>肥満度判定</TITLE></HEAD>
    <FRAMESET ROWS="50%,50%">
    <FRAME SRC="fatness.html" NAME="inputform" SCROLLING="auto">
    <FRAME NAME="outputarea" SCROLLING="auto">
    </FRAMESET>
    </HTML>
    
  3. fatness.html
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
    <html lang="ja-jp">
    <head>
     <meta http-equiv="content-type" content="text/html; charset=euc-jp">
     <TITLE>肥満度判定</TITLE>
     </HEAD>
     <BODY>
     <h1>肥満度判定</h1>
       <FORM method="GET" action="./fatness.cgi" target="outputarea">
       <h2>身長 <input type="text" name="height"></h2>
       <h2>体重 <input type="text" name="weight"></h2>
       <h2><input type="submit" value="判定"></h2>
       </FORM>
    <HR>
    <a href="/index.html">sakura</a>
     </BODY>
    </HTML>
    
  4. fatness.cgi
    #!/usr/bin/perl
    require 'cgi-lib.pl';
    
    &ReadParse(*in);
    
    $height = $in{'height'};
    $weight = $in{'weight'};
    
    system "./fatness $height $weight";
    exit;
    
  5. fatness.cob
     IDENTIFICATION DIVISION.
     PROGRAM-ID.    fatness.
     ENVIRONMENT     DIVISION.
     CONFIGURATION   SECTION.
     DATA DIVISION.
     WORKING-STORAGE SECTION.
    * コマンド全体を格納するTEMP変数
    77 i                   pic  999  value 0.
    77 j                   pic  999  value 0.
    01 inum                pic  999  value 0.
    01 height              pic  999  value 0.
    01 weight              pic  999  value 0.
    01 fatness             pic  999  value 0.
    01 WORKSTR PIC  X(20).
      02 C OCCURS 20 PIC X.
    01 TEMP PIC  X(60).
    01 strs.
     02 str pic x(20) occurs 3.
    * 手続き部:データを操作して、ロジックを実行する。
     PROCEDURE DIVISION.
    * コマンドライン全体をTEMPに格納
      ACCEPT TEMP FROM COMMAND-LINE.
      unstring TEMP DELIMITED BY ' ' INTO
        STR(1) STR(2) STR(3).
    
      PERFORM atoi varying j from 2 by 1 until j = 4
    *    display height  weight
        compute fatness = (height - 100)*0.9 -weight
       DISPLAY "Content-type: text/html".
       DISPLAY.
        display "<H2>あなたは肥満度 " fatness "です</h2>".
        display "<H3>-5 から 5が適正です</h3>".
      STOP RUN.
    
    * PIC X() データを PIC 9()データに変換
    atoi.
      move str(j) to workstr.
      compute inum = 0.
      PERFORM test before varying i from 1 by 1 until i = 20
        if c(i) is = "0" then
          compute inum = inum*10 + 0
        end-if
        if c(i) is = "1" then
          compute inum = inum*10 + 1
        end-if
        if c(i) is = "2" then
          compute inum = inum*10 + 2
        end-if
        if c(i) is = "3" then
          compute inum = inum*10 + 3
        end-if
        if c(i) is = "4" then
          compute inum = inum*10 + 4
        end-if
        if c(i) is = "5" then
          compute inum = inum*10 + 5
        end-if
        if c(i) is = "6" then
          compute inum = inum*10 + 6
        end-if
        if c(i) is = "7" then
          compute inum = inum*10 + 7
        end-if
        if c(i) is = "8" then
          compute inum = inum*10 + 8
        end-if
        if c(i) is = "9" then
          compute inum = inum*10 + 9
        end-if
    *   display i " " c(i) " " inum
      end-perform.
      if j  = 2 then compute height = inum.
      if j  = 3 then compute weight = inum.
    

サンプル

  1. 宅配便送料計算プログラム
    $cd 
    $cd cobol
    $cd sample1020
    $ls
    で構成ファイル一覧を見ることができる。
    

参考URL)

th since 2008/5/12.
著者:城風敏彦
メールいただければ幸いです。まあ、あまりないと思いますが(^^;
mailto:shirokaze@ymail.plala.or.jp