COBOL入門 Mission4-4

処 理 内 容 PROGRAM-ID 難易度 言語
表検索 (Table-Search) TBL030 1 COBOL
1:処理図
2:処理概要

キーボードから入力された駅コード(4桁)で駅名テーブルを検索し、該当する駅名を画面に表示する
駅コードは繰返し指定できるようにする
プログラムの終了条件は 999 入力とする

駅名テーブルには
1001 新宿駅 1002 大久保駅 1003 東中野駅・・・
 の様に 1022 高尾駅まで登録してある

 文字列定数のテーブルについては《再定義》で設定する
 該当するコードがある時は駅名を表示
  無い時は どうしよう???

 新しい駅が出来たらどうしよう ???

4:外部フォーマット定義(画面・書式等)
繰返し駅コードを入力する場合
プログラムの終了条件として特殊な値を指定する必要がある
5:その他
駅名はどのように定義しておくのか?
 $  § いよいよ出てきました 《再定義》 少々小骨ありです!!!

**********  ( 定数を持つテーブル )  **********

 IDENTIFICATION             DIVISION.
 PROGRAM-ID.                TBL030.
 DATA                       DIVISION.
 WORKING-STORAGE            SECTION.
*駅コード取得領域 *****
 01  ACPT                   PIC X(04).

*添え字領域 *****
 01  I                      PIC 9(02).
*表示用編集領域 *****
 01  D1R.
     03  D1CD               PIC X(04)B(02).
     03  D1NM               PIC X(12).
***** ( 文字定数領域 ) *****
 01  TBL-CNST.
     03  PIC X(16)  VALUE "1001新  宿  駅  ".
     03  PIC X(16)  VALUE "1002大 久 保 駅 ".
     03  PIC X(16)  VALUE "1003東 中 野 駅 ".
     03  PIC X(16)  VALUE "1004中  野  駅  ".
     03  PIC X(16)  VALUE "1005高 円 寺 駅 ".
     03  PIC X(16)  VALUE "1006阿佐ヶ谷駅  ".
     03  PIC X(16)  VALUE "1007荻  窪  駅  ".
     03  PIC X(16)  VALUE "1008西 荻 窪 駅 ".
     03  PIC X(16)  VALUE "1009吉 祥 寺 駅 ".
     03  PIC X(16)  VALUE "1010三  鷹  駅  ".
     03  PIC X(16)  VALUE "1011武 蔵 境 駅 ".
     03  PIC X(16)  VALUE "1012東小金井駅  ".
     03  PIC X(16)  VALUE "1013武蔵小金井駅".
     03  PIC X(16)  VALUE "1014国 分 寺 駅 ".
     03  PIC X(16)  VALUE "1015西国分寺駅  ".
     03  PIC X(16)  VALUE "1016国  立  駅  ".
     03  PIC X(16)  VALUE "1017立  川  駅  ".
     03  PIC X(16)  VALUE "1018日  野  駅  ".
     03  PIC X(16)  VALUE "1019豊  田  駅  ".
     03  PIC X(16)  VALUE "1020八 王 子 駅 ".
     03  PIC X(16)  VALUE "1021西八王子駅  ".
     03  PIC X(16)  VALUE "1022高  尾  駅  ".
***** ( 文字定数領域をテーブルとして再定義する ) *****

 01  TBL  REDEFINES  TBL-CNST.
     03  TB  OCCURS  22.
*        *** 駅コード ***
         05  TBCD  PIC X(04).
*        ***   駅名   ***
         05  TBNM  PIC X(12).
 PROCEDURE                  DIVISION.
     PERFORM  UNTIL  ACPT  =  "9999"
         DISPLAY  "駅コード"  X(04)  TYPE-IN  END・・・9999"
*        *** (駅コード取得) ***
         ACCEPT  ACPT
         IF  ACPT  =  "9999"
             THEN  CONTINUE
*            *** (テーブル検索) ***
             ELSE  PERFORM VARYING I FROM 1 BY 1
                           UNTIL I > 22 OR ACPT = TBCD(I)
                       CONTINUE
                   END-PERFORM
*                  *** (検索結果の判定) ***
                   IF  I  >  22
                       THEN  DISPLAY  "<<< CODE - ERR >>>"
*                      *** (結果の表示) ***
                       ELSE  MOVE  TBCD(I)  TO  D1CD
                             MOVE  TBNM(I)  TO  D1NM
                             DISPLAY  D1R   DISPLAY " "
                   END-IF
         END-IF
     END-PERFORM
     STOP  RUN.

テーブルの検索といえば通常、「SEARCH」という命令語を利用するのが一般的です。ここではテーブルの理解を深めるため、あえてSEARCH命令を利用しない方法を解説します。

REDEFINES(再定義)句について

WORKING-STORAGE SECTION で、駅名の入ったテーブルの下に、見慣れない文字列「REDEFINES」が出てきます。これはREDEFINES句(レディファインズ句)というもので、一度定義した項目(集団項目や単一項目)を再定義しますよ、という宣言になります。詳しい説明はQ&Aのページ内にある、「REDEFINESって何?」で解説していますので、ここでの説明は割愛します。

2006/05/22 追記

さて、ここで問題です。次のサンプルには重大なバグがあります。さあアナタには解けますか?

**********  表検索  **********

***********************************************************************
*  4桁の学校コードを TYPE-IN して学校名を表示するプログラムです
*     実はこのプログラムには重大な欠陥がありますが分かりますか?
***********************************************************************

 IDENTIFICATION             DIVISION.
 PROGRAM-ID.                TBL03X.

 DATA                       DIVISION.
 WORKING-STORAGE            SECTION.
***** ( コード取得領域 ) *****
 01  ACPT                   PIC X(04).
***** ( 添え字領域 ) *****
 01  I                      PIC 9(01).
***** ( 表示用編集領域 ) *****
 01  D1R.
     03  D1CD               PIC X(04)B(02).
     03  D1NM               PIC X(16).

***** ( 文字定数領域 ) *****
 01  TBL-CNST.
     03  PIC X(20)  VALUE "0021東京大学        ".
     03  PIC X(20)  VALUE "0025東京農工大学    ".
     03  PIC X(20)  VALUE "0042静岡大学        ".
     03  PIC X(20)  VALUE "0050京都工芸繊維大学".
     03  PIC X(20)  VALUE "0051大阪大学        ".
     03  PIC X(20)  VALUE "0071九州工業大学    ".
     03  PIC X(20)  VALUE "0085豊橋技術科学大学".
     03  PIC X(20)  VALUE "2011酪農学園大学   ".
     03  PIC X(20)  VALUE "2329明治鍼灸大学    ".

***** ( テーブルとして再定義する ) *****
 01  TBL  REDEFINES  TBL-CNST.
     03  TB  OCCURS  9.
*        ***** 学校コード *****
         05  TBCD  PIC X(04).
*        *****   学校名   *****
         05  TBNM  PIC X(16).
*
 PROCEDURE                  DIVISION.
     PERFORM  UNTIL  ACPT  =  "9999"
         DISPLAY "!!! TBL03X-STARTED !!!"
         PERFORM  UNTIL  ACPT  =  "9999"
             DISPLAY  "CODE  X(04)  TYPE-IN  END...9999"
             ACCEPT  ACPT
             IF  ACPT  =  "9999"
                 THEN  CONTINUE
                 ELSE  PERFORM VARYING I FROM 1 BY 1
                                  UNTIL  I > 9 OR ACPT = TBCD(I)
                          CONTINUE
                       END-PERFORM
                       IF  I  >  9
                           THEN  DISPLAY  "CODE NOT-FOUND  RETYPE-IN"
                           ELSE  MOVE  TBCD(I)  TO  D1CD
                                 MOVE  TBNM(I)  TO  D1NM
                                 DISPLAY  D1R
                       END-IF
             END-IF
     END-PERFORM
     DISPLAY  "!!! TBL03X - ENDED !!!"
     STOP  RUN.

回答

さて、上のプログラムで一体何がダメなんでしょう?まず処理をみてみると、最初に数字を入力(タイプイン)する指示がきて、「9999」なら処理終了、それ以外は入力された4桁の数字でREDEFINESで定義された大学コードを検索し、同じ4桁のコードが存在すれば大学名を表示、無ければ「CODE NOT-FOUND RETYPE-IN」とのメッセージを返し、次の入力へ移る、ということになりますね。ここまでは別に問題ないです。

 処理には何も問題がないのですが、実はインデックスに問題があるのです。この検索をおこなう際に利用している「I」(アイ)というインデックス。これがマズい。WORKING-STORAGE SECTIONで定義された「I」をみてみるとこう記述されています。

***** ( 添え字領域 ) *****
 01  I                      PIC 9(01).
確かにテーブルの要素は9つしかないため、添え字(インデックス)も同じ大きさで構わない、そう考えられます。ですが、実際にこのプログラムを動作してみるとループ(永久に処理が終わらない)します。それは、桁数に問題があるためです。桁数をみてみると、「9(01)」となっています。つまり0〜9までしか使えないため、条件式で「I > 9」という条件を満たすことができないのです。9までカウントアップされたインデックスに+1をすると、インデックスの値はまた0に戻ってしまうのです!

ですから、正解は・・・

***** ( 添え字領域 ) *****
 01  I                      PIC 9(02).
こう記述していなければダメ、というわけです。わかりますか?

2007/01/30 追記


<< Back    Index    Next >>   < Top >