よくあるCOBOLでの質問

このサイトを開設してから寄せられたCOBOLに関する質問と、私の回答を掲載しておきます。少しでも参考になれば嬉しいです。徐々に増やしていきます。

  1. これでファイルの初期化?
  2. PERFORM THRUって何?
  3. COMPって何?
  4. PACKED-DECIMALって何?
  5. REDEFINESって何?
  6. データの長さを得る関数ってある?
  7. 試験問題を解くコツは?
  8. COBOL85でプリンターへ印刷するには?
  9. ビットとバイトの意味すらわかりません
  10. プログラム内で項目群の並び替えをしたい
  11. PIC 9(5)V9 の V9 って何ですか? 4/19up!
※他にも何か気づいた点がございましたらメールでお知らせ下さると助かります。

▼メニューへ

Q01. これでファイルの初期化?

設計書に「4月10月にファイル初期化する」と書いてありまして、そこのソースを確認してみると

IF MM = 4 OR 10
   OPEN OUTPUT F0001
   CLOSE F0001.
と、これだけです。これだけではファイルの初期が出来るとは思えないです。開いて閉じるだけで初期化できるのは意図しない事で消えてしまう危険が潜んでいそうで納得できな いんです。やはり削除するのはDELETE命令だと思うんですが…。これはこの機種だけの仕様なんでしょうか?

A01

COBOLならではのプログラミングですね。マニュアル等には掲載されないCOBOLテクニックです。COBOLではOUTPUTでOPENした時点で、一旦ファイルを使用済みファイルに変換してくれます。つまりゼロ件のアウトファイルができあがる、即ちファイルのクリアが行なわれるのです。普通はJCL側(shell)で判定してファイルクリアのコマンドを投入するのが一般的ではありますが、こういう手法もありますよと。

DELETE命令はレコード単位の削除命令であり、ファイルのクリアには適しません。何故なら1000万件のレコードがあるファイルのクリアをするために、わざわざ1レコード毎に削除していたら丸一日掛けても処理が終わりません。

▲トップへ  ▼メニューへ

Q02. PERFORM THRUって何?

PERFORM命令の説明で、THRUという文言が出てきますがこのTHRUの意味がわからないです。

A02

PERFORM THRU もよく見かけますね。「THRU」を直訳すれば、"通り過ぎる" になります。PERFORM AAA THRU BBB であれば、AAAからBBBまでを実行しなさいよ、という意味です。SECTION を使用しない場合に、よく利用されていますね。ちょっとサンプルでも記載してみましょうか。

PROCEDURE  DIVISION.
	PERFORM  INIT-R  THRU  INIT-E
	PERFORM  READ-R  THRU  READ-E
	PERFORM  LOOP-R  THRU  LOOP-E
	STOP RUN.
INIT-R.
	OPEN IN-FILE
	MOVE ALL ZERO TO COUNT-AREA.
INIT-E.
READ-R.
	READ IN-FILE AT END
	    MOVE  HIGH-VALUE  TO  IN-REC
	END-READ.
READ-E.
LOOP-R.
	PERFORM  UNTIL   IN-REC = HIGH-VALUE
	    ADD  1  TO  IN-CNT
	    PERFORM READ-R  THRU  READ-E
	END-PERFORM
	CLOSE  IN-FILE
	DISPLAY "INPUT COUNT = " IN-CNT.
LOOP-E.

どうでしょうか、わかるかな?。SECTIONで処理を分ける場合、THRUは不用になりますね。

▲トップへ  ▼メニューへ

Q03. COMPって何?

Cobolコードを見ていると、WORKING-STORAGE内で
03 KINGAKU  PIC  9(4)  COMP.
と書かれている項目がありました。この最後についてる「COMP」の意味がわかりません。

A03

これは「COMPUTATIONAL」という意味の予約語で実は2進数で表現されます。これをつけると数字項目はどうなるか?たとえば

working-storage	section.
	03  kingaku-1   pic 9(4).
	03  kingaku-2   pic 9(4) comp.
procedure	division.
	move  1234   TO   kingaku-1  kingku-2

とした場合を考えてみましょう。それぞれの中身を16進数で表示させてみるとはっきり違いがわかります。

kingaku-1[hex] ==>  F1F2F3F4
kingaku-2[hex] ==>  04D2

ご覧のように「kingaku-1」は4バイトの項目なのですが、COMP指定があるkingaku-2の場合、使用する領域が半分の2バイトで済むわけですね。ただし中身は2進数のため人間が直接データをみてもややわかりづらいという欠点があります。補足ですが、符号つきの場合はこうなります。

working-storage	section.
	03  kingaku-1   pic s9(4).
	03  kingaku-2   pic s9(4) comp.
procedure	division.
	move  -1234   TO   kingaku-1  kingku-2

kingaku-1[hex] ==> F1F2F3D4 kingaku-2[hex] ==> FB2E

2進数でマイナス表現する場合、2の補数で表現されるため中身は「FB2E」になります。どうです、もう何がなんだかわからないでしょ?だから計算領域をあまり使わないための手段、ぐらいに覚えておけばいいです。

▲トップへ  ▼メニューへ

Q04. PACKED-DECIMALって何?

Cobolコードを見ていると、WORKING-STORAGE内で
03 KINGAKU  PIC  9(4)  PACKED-DECIMAL.
と書かれている項目がありました。この最後についてる「PACKED-DECIMAL」の意味がわかりません。

A04

質問3と同じような内容ですが、これは数字項目を内部10進で表現させる予約語です。これをつけると数字項目はどうなるか?早速やってみましょう。

working-storage	section.
	03  kingaku-1   pic s9(4).
	03  kingaku-2   pic s9(4) packed-decimal.
procedure	division.
	move  -1234   TO   kingaku-1  kingku-2

kingaku-1[hex] ==> F1F2F3D4 kingaku-2[hex] ==> 01234D

PACKED-DECIMAL指定がある場合、中身は内部10進数になり16進数表示では、「01234D」となります。最後の「D」が符号になります。プラスは「C」マイナスは「D」で表現されます。COMPは使用する領域が半分の2バイトでしたが、PACKED-DECIMALの場合、

内部10進数の実バイト数 = [ 項目バイト数 / 2 + 0.5 ]

という計算式でバイト数を求めます。「kingaku-2 pic s9(4) packed-decimal.」の場合は…

[ 4 / 2 + 0.5 ] = 2.5  ※小数点は切り上げるため実バイト数は3バイトになる

こんな感じになり、s9(4)packed-decimailは4バイトでも2バイトでもなく実は3バイトが正解になります。この内部10進は人間が見てもすぐ数値がわかるため、実務でも頻繁に利用されます。

▲トップへ  ▼メニューへ

Q05. REDEFINESって何?

03 WORK-KJDT-N REDEFINES  WORK-KJDT.

というのがあるんですが、このREDEFINESってなんでしょうか?

A05

"REDEFINES"はこの文の上記にある「WORK-KJDT」という項目を再利用しますよ、という予約語です。例を挙げた方が早いかな。

01 X-REC.
   03 X1  PIC X(7).
   03 AAA PIC x(10).
   03 BBB REDEFINES AAA.
      05  CCC  PIC 9(5).
      05  DDD  PIC X(5).

こんな感じで使用します。「AAA」という項目を「BBB」という項目(群)で再利用する手法です。「AAA」の文字列10バイトの項目を、「CCC」の数字5バイトと「DDD」の文字列5バイトという二つの項目に分解しているのがわかるでしょうか。そして…

	MOVE ZERO    TO   CCC
	MOVE "ABCDE" TO   DDD
	DISPLAY  "AAA = "  AAA

結果 AAA = 00000ABCDE

わかりますか?こんな感じで項目を別の項目として編集する手法です。ちなみにREDEFINESは「01レベル」での利用はできないという点に注意しましょう。

▲トップへ  ▼メニューへ

Q06. データの長さを得る関数ってある?

コボルでデータの長さを得る関数は存在するのでしょうか?(C言語だとSTRLENみたいな)

A06

結論を言えばありません。COBOLは全て固定長なので、データ長=項目長になります。ここら辺がCやJava言語に比べCOBOLが発展しない理由の一因ですね。ただし、固定長項目の中身が空白以外で何バイト利用されているのか?という調査であればINSPECT命令を利用すれば得ることができます。詳しい使用例は命令語ページを参照して下さい。

▲トップへ  ▼メニューへ

Q07. 試験問題を解くコツは?

情報処理試験の過去問題をといているのですがどうしても時間がかかってしまいます。早く解けるようになるには慣れるしかないのでしょうか?特に作業場所節の行数が多いと混乱します。何か良いアドバイスはありますか?

A07

そのお気持ちはよくわかります。私も問題によっては解答するまでに時間がかかります。コツと言えるかわかりませんが、WORKING-STORAGE SECTIONは最初は見ないで無視しましょう。あくまで私の場合ですが、設問の付近しか見ません。出題者が問題を出す場所というのはある程度予測できます。

  1. 変数を代入させる文
  2. プログラムの仕様(構造)を理解しているか試す箇所
  3. SORT命令の構文
  4. 分岐命令(IF文など)

まずはざっと手続き部をみて、利用されている変数を洗い出します。問題には必要最低限の変数しかありません。多くて5,6個でしょうか。ココで初めてWORKINGをみます。洗い出した変数の桁数とサイン付き(符号付き)かどうかだけの確認です。各変数がどういう用途で使われているのかを考えれば、自ずと問題も解けるはずです。簡単に言ってますけど、やはり慣れは必要でしょうね。頑張って下さい。

▲トップへ  ▼メニューへ

Q08. COBOL85でプリンターへ印刷するには?

DownloadしたCOBOL85で自分のマシンのプリンターに出力したい場合、どのように記述すればよいのでしょうか?

A08

	SELECT  出力ファイル名 ASSIGN TO PRINTER.

と記述して下さい。これでパソコンに接続されている標準プリンタへ印字されるはずです。

▲トップへ  ▼メニューへ

Q09. ビットとバイトの意味すらわかりません

学校で習っているビットとバイトの違いすらわかりません。こんな私でも大丈夫なんでしょうか?

A09

不安になる気持ちはわかります。これは単位の違いです。長さの単位で喩えれば、センチとメートルの違いです。ビットは一番小さいデータの単位で、バイトは時給で働く人のことです。うん、嘘。バイトはビットの上の単位です。1メートルが100センチなら、1バイトは8ビットになります。じゃあ具体例を出しましょうか。

01 w-byte1  pic 9(1) value 3.

数字1桁の項目に「3」が入っています。これを16進数で表示した場合、中身はこうなります。

w-byte1[hex] ==>  F3

じゃあこれをビット(2進数)で表示した場合、中身はこうなります。

w-byte1[bin] ==>  1111 0011

つまり、プログラム上での最小単位はバイトなんですが、実際その1バイトの中身は8ビットで構成されてますよ、ということです。全然関係ないですが、昔ネオジオというゲームメーカーが「100メガショック!」というCMをやってました。実はアレ、100メガバイトじゃなくて100メガビットだったらしいですよ、という補足トリビアでした。

▲トップへ  ▼メニューへ

Q10. プログラム内で項目群の並び替えをしたいのですが

SORT命令はファイルソート用だと思うのですが、プログラムの内部テーブルをソートする方法はあるのでしょうか?もしサンプルがあれば教えて下さい。

A10

内部ソートですが、COBOLの場合は手動による並び替えが一般的かと思われます。これはテクニック的なものなので、人によって方法は色々あります。じゃあ具体的にどうやるか。

 WORKING-STORAGE SECTION.
 01 WORK-TABLE.
    02 ITEM      PIC X(02)  OCCURS 10.
 01 WK-ITEMS     PIC X(20)  VALUE  "02010304050604030201".
 01 A            PIC 9(02).
 01 B            PIC 9(02).
 01 C            PIC 9(02).
 01 ITEMW        PIC X(02).
 PROCEDURE       DIVISION.
*
* 事前準備としてテーブルにデータを格納しておきます
*
     MOVE WK-ITEMS TO WORK-TABLE
*
* 内部ソート(テーブルの並び替え)
*
     PERFORM VARYING A FROM 1 BY 1 UNTIL A > 10
         COMPUTE C = A + 1
         PERFORM VARYING B FROM C BY 1 UNTIL B > 10
             IF  ITEM(A) <  ITEM(B)
                 CONTINUE
             ELSE
                 MOVE   ITEM(A)  TO  ITEMW
                 MOVE   ITEM(B)  TO  ITEM(A)
                 MOVE   ITEMW    TO  ITEM(B)
             END-IF
         END-PERFORM
     END-PERFORM

〜(以下略)〜

こんな感じでしょうか。結局やってることは本当にトロクサイです。なーんだと思われるかもしれませんね。命令文を突き詰めて考えると、他に劇的な手法があれば別ですが、命令文自体の中身って案外こんな構造なんじゃないかと思いますよ。こういう単純なロジックをひとつの命令語として定義しているだけじゃないかと。

▲トップへ  ▼メニューへ

Q11. PIC 9(05)V9 の V9って何?

WORKING-STORAGE内で
03 KINGAKU  PIC  9(05)V9.
と書かれている項目がありました。この「V9」の意味がわかりません。

A11

PICTURE句の中に記述できる「V」、これは想定小数点の位置を示しています。想定小数点とは、データとしては単なるひとつの数字項目ですが、プログラム内では小数点以下として取り扱われる領域の指定です。また最後の「9」は単純に「9(01)」の省略系です。文章で説明するより例題を出したほうが一目瞭然ですね。

DATA            DIVISION.
FILE            SECTION.
FD O-FILE.
01 O-REC.
   02 O-KIN-2   PIC 9(5)V9(2).
WORKING-STORAGE SECTION.
01 KIN-0        PIC 9(5).    *> 数字5桁、小数なし
01 KIN-1        PIC 9(5)V9.  *> 数字5桁、小数1位
01 KIN-2        PIC 9(5)V99. *> 数字5桁、小数2位
01 KIN-1-1      PIC 9(5)V9(1).  *> KIN-1 と同じ意味
01 KIN-2-1      PIC 9(5)V9(2).  *> KIN-2 と同じ意味
PROCEDURE       DIVISION.
    MOVE   12345.12   TO   KIN-0  KIN-1  KIN-2
    DISPLAY "KIN-0=" KIN-0 " | KIN-1=" KIN-1 " | KIN-2=" KIN-2
    OPEN   O-FILE
    WRITE  O-REC  FROM  KIN-2
    CLOSE  O-FILE
    STOP   RUN
結果は以下の通り
KIN-0=12345 | KIN-1=12345.1 | KIN-2=12345.12

このようにプログラム内で小数点以下の数字を利用するためには、必ず「V」をつけて小数点以下の桁数を指定しなければなりませんよ、ということです。 また実際に小数点をつけた状態でデータを出力すると結果はどうなったでしょうか?

O-RECの中身
1234512

上記の結果からもわかるように、データ上では小数点の有無は無視され、ただの数字7バイトとして扱われます。小数点以下を扱うときには注意してください。

▲トップへ  ▼メニューへ

<< Back   Index   Next >>  < Top >