1人COBOL再研修〜基礎編〜

現在研修で絶賛COBOL学習中。始まって2週間経過したところで、初めて触る言語っていうのと、自分の覚えが非常に悪いというのを踏まえておさらい。どうか温かい目で見てください。

## 今までCOBOLは？

高校の情報処理検定の問題で見たことだけはあった。ただ学校がマクロ言語（VBA）を選択していたので、勉強はしていない。

## よく見た参考資料

* 会社の研修資料
* [COBOLの構成について](https://qiita.com/masapiko/items/188dd347b7def30d0a74)
* [はじめてのCOBOL](http://www16.plala.or.jp/hiyokogumi/3/300.html)

それでもわからないときはそこら辺を巡回したりした。

## 環境

* Ubuntu18.04 LTS
* OpenCobol 1.1.0

## COBOLって何？

「Common Business Oriented Language（共通事務処理用言語）」。英文に似た記述方法で帳票作成やファイル処理に適している。

## COBOLのお約束

COBOLにはいくつか書き方にルールがある。

* 1行は80文字以内に収めないといけない
* 1行にも領域が決められている
  * 領域は下表の通り
  * 73文字目以降まで命令が続いているともれなく`SyntaxError`が出る。

|場所|名称（領域）|意味（役割）|
|:---:|:---:|:---|
|1〜6文字|__一連番号領域__|プログラムの行番号を6桁で記載<br>→スペースでOK|
|7文字|__標準領域__|・`*`ならコメント<br>・スペースなら命令行<br>・`-`なら前行の続き<br>・`/`ならそこで改行されて後をコメント|
|8〜11文字|__A領域__|・データ定義時のレベル番号<br>・ディビジョン見出し<br>・セクション見出し<br>・パラグラフ名<br>を記載|
|12〜72文字|__B領域__|命令文・データ名を記載|
|73〜80文字|__見出し領域__|翻訳対象外。コメントとして扱う|

* 命令の終了は`;`ではなく`.`（ピリオド）

## COBOLの構成

大きく分けて4つある。

### 見出し部（IDENTIFICATION DIVISION）

* プログラム名や作成者などを定義する。
* `ID DIVISION`とも略せる。

### 環境部(ENVIRONMENT DIVISION)

* コンパイルするコンピュータ名や実行するコンピュータ名、環境変数や入出力するファイルについて定義する。

### データ部(DATA DIVISION)

* プログラム内で利用するデータ項目（変数）をすべて定義する。
* 入出力ファイルがあるときは、そのファイルのレイアウト（何文字目から何文字は何を示しているか）も記述する。

### 処理部(PROCEDURE DIVISION)

* 処理を書く。

## Hello Worldを書く

一通りCOBOLの概要を書いたところで毎度おなじみのHello Worldを書いてみる。

```COBOL
------+--1---------2---------3---------4---------5
       ID                    DIVISION.
       PROGRAM-ID.           SAMPLE.
      *
       ENVIRONMENT           DIVISION.
      *
       DATA                  DIVISION.
      *
       PROCEDURE             DIVISION.
       MAIN                  SECTION.
       MAIN-S.
         DISPLAY           'HELLO WORLD'.
       MAIN-E.
         STOP RUN.
```

実行結果

```
HELLO WORLD
```

ちなみに、画面出力は`DISPLAY <出力したいもの>.`とする。

## データを取得する　`ACCEPT`

`ACCEPT`を使用することで、キーボードからの入力を受け付けたり、システム日付を取得することができる。書き方は

```COBOL
ACCEPT <格納先のデータ項目>.
```

### その前にデータ項目を作るには

データ項目の定義は`DATA DIVISION.`内の`WORKING-STORAGE SECTION.`で行う。書き方は以下の通り。

```COBOL
------+--1---------2---------3---------4---------5
      * ｾﾞﾝﾘｬｸ
       DATA                  DIVISION.
       WORKING-STORAGE       SECTION.
       01  IN-STR            PIC X(16).
      * ｺｳﾘｬｸ
```

|コード|意味|
|:---:|:---|
|`01`|レベル番号。01だとデータが独立していることになる|
|`IN-STR`|項目名。予約後でない限り任意の名前がつけれる|
|`PIC`|PICTURE句といい、必ずつける|
|`X(16)`|データの型と格納量を定義する。<br>・`X`は半角英数字ｶﾅ<br>・`(16)`は格納可能文字数で16文字|

データ項目を定義できるようになったところで、キーボード入力をしてみる。

```COBOL
------+--1---------2---------3---------4---------5---------6
       ID                    DIVISION.
       PROGRAM-ID.           SAMPLE.
      *
       ENVIRONMENT           DIVISION.
      *
       DATA                  DIVISION.
       WORKING-STORAGE       SECTION.
       01  IN-STR            PIC X(16).
       01  IN-DATE           PIC 9(06).
      *
       PROCEDURE             DIVISION.
       MAIN                  SECTION.
       MAIN-S.
         ACCEPT                IN-STR.
         ACCEPT                IN-DATE       FROM  DATE.
         DISPLAY               "DATE   : "   IN-DATE.
         DISPLAY               "IN-DATA: "   IN-STR.
       MAIN-E.
         STOP RUN.
```

実行結果

```Cobol
HOGE　←キーボードから入力
DATE   : 190602
IN-DATA: HOGE
```

キーボード入力のデータを出力できた。また、`FROM  DATE.`を後ろにつけることで、システム日付も取得できた。データ項目`IN-DATE`は`9(06)`となっているが、`9`だと数字0〜9のみ格納できる。

## 計算処理をする `COMPUTE`

書き方は以下の通り。

```COBOL
COMPUTE  <データ格納先> = <算術式（1 + 1 とか）>
```

これは他の言語にも近いから飲み込みやすい。

## データを代入する `MOVE`

`ACCEPT`と違って直接リテラルやデータ項目を別のデータ項目に格納したいときに使う。

```COBOL
MOVE  <元データ>  TO  <格納先>
```

## `COMPUTE`や`MOVE`を使ったサンプル

```COBOL
------+--1---------2---------3---------4---------5---------6
       ID                    DIVISION.
       PROGRAM-ID.           SAMPLE.
       *
       ENVIRONMENT           DIVISION.
       *
       DATA                  DIVISION.
       WORKING-STORAGE       SECTION.
       01  TODAY             PIC 9(06).
       01  TOMORROW          PIC 9(06).
       *
       PROCEDURE             DIVISION.
       MAIN                  SECTION.
       MAIN-S.
         ACCEPT              TODAY  FROM  DATE.
         DISPLAY             "TODAY:    " TODAY.
         MOVE                TODAY  TO  TOMORROW.
         COMPUTE             TOMORROW = TOMORROW + 1.
         DISPLAY             "TOMORROW: " TOMORROW.
       MAIN-E.
         STOP RUN.
```

実行結果

```
TODAY:    190602
TOMORROW: 190603
```

### ここらで気になったこと：文字列連結ってできるの？

```COBOL
------+--1---------2---------3---------4---------5---------6
       ID                    DIVISION.
       PROGRAM-ID.           SAMPLE.
      *
       ENVIRONMENT           DIVISION.
      *
       DATA                  DIVISION.
       WORKING-STORAGE       SECTION.
       01  STR               PIC X(16).
      *
       PROCEDURE             DIVISION.
       MAIN                  SECTION.
       MAIN-S.
         COMPUTE             STR = 'HELLO ' + 'WORLD'.
         DISPLAY             STR.
       MAIN-E.
         STOP RUN.
```

コンパイル結果

```
SAMPLE.cbl: In paragraph 'MAIN-S':
SAMPLE.cbl:13: Error: '"HELLO "' is not a numeric value
SAMPLE.cbl:13: Error: '"WORLD"' is not a numeric value
SAMPLE.cbl:13: Error: 'STR' is not numeric or numeric-edited name
```

だめだった。`〜 is not a numeric value`って書いてるから、計算は数字しかできないのね。覚えておこう。

## 今回はここまで

Markdownでまとめながら勉強すると、ここまで来るのにも結構時間がかかった。ただ、研修中に試したかったことができたりおさらいできたりでいい機会だった。

次回はもうちょっと奥行った内容を勉強して、またこんな感じで投稿できたらと思う。→[続き](https://qiita.com/zama_8722/items/90febb1e27c73aa20809)(2019/06/15作成)