| ||||||||
| ||||||||
|
********** ( 定数を持つテーブル ) ********** 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命令を利用しない方法を解説します。
WORKING-STORAGE SECTION で、駅名の入ったテーブルの下に、見慣れない文字列「REDEFINES」が出てきます。これはREDEFINES句(レディファインズ句)というもので、一度定義した項目(集団項目や単一項目)を再定義しますよ、という宣言になります。詳しい説明はQ&Aのページ内にある、「REDEFINESって何?」で解説していますので、ここでの説明は割愛します。
さて、ここで問題です。次のサンプルには重大なバグがあります。さあアナタには解けますか?
********** 表検索 ********** *********************************************************************** * 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).こう記述していなければダメ、というわけです。わかりますか?