| ||||||||
| ||||||||
|
ええと、まず今回の問題ではタイプイン命令(ACCEPT)が出題されてます。COBOLでは処理中に手動で値を入力するには、このACCEPT命令で行なうか、JCL(後に説明します)で受け渡す方法が一般的です。表示は100ずつということなので注意して組んでみましょう。
IDENTIFICATION DIVISION. PROGRAM-ID. CNT004. DATA DIVISION. WORKING-STORAGE SECTION. 01 WCNT PIC 9(04) VALUE 0. * ↑この項目をタイプインで受け取り比較する 01 CNT PIC 9(04) VALUE 0. 01 CNT1 PIC 9(03) VALUE 0. 01 WTIME. 03 HH PIC 9(02). 03 MM PIC 9(02). 03 SS PIC 9(02). 01 STIME PIC 9(06) VALUE 0. 01 ETIME PIC 9(06) VALUE 0. 01 XTIME PIC 9(06) VALUE 0. PROCEDURE DIVISION. DISPLAY "!!! CNT 9(04) TYPE-IN !!!" * ↑DISPLAY命令を直前に行なえば、タイプイン時に * 指定した文字列を画面に表示できます ACCEPT WCNT ACCEPT WTIME FROM TIME COMPUTE STIME = (HH * 3600) + (MM * 60) + SS PERFORM UNTIL CNT = WCNT * ↑先ほど指定したWCNTを超えるまで繰り返す ADD 1 TO CNT CNT1 IF CNT1 = 100 THEN DISPLAY CNT MOVE ZERO TO CNT1 ELSE CONTINUE END-IF END-PERFORM ACCEPT WTIME FROM TIME COMPUTE ETIME = ((HH * 3600) + (MM * 60) + SS) COMPUTE XTIME = ETIME - STIME COMPUTE HH = XTIME / 3600 COMPUTE XTIME = XTIME - (HH * 3600) COMPUTE MM = XTIME / 60 COMPUTE SS = XTIME - (MM * 60) DISPLAY "TIME = " HH ":" MM ":" SS DISPLAY "<<< CNT004 ENDED >>>" STOP RUN.
ACCEPT命令だけでもちゃんと動作はします。ただそうなると、画面には入力を受け入れる状態にはなりますが、特に何も表示されないため何の入力をするのかよくわかりません。そこでACCEPT命令の直前にDISPLAY命令を入れてあげるようにしましょう。こうすれば画面には「!!! CNT 9(04) TYPE-IN !!!」の文字に続いて「?」が表示されるようになります。
後はそれほど難しい箇所はありませんね。ACCEPT命令で入力したWCNTに達するまでCNT+1を繰り返せばOK。
カウント値を繰返し指定出来るようにする。ただし9999が入力されたらプログラムを終了する。
先ほどのプログラムは、1回ACCEPTでタイプイン(入力)したらお終いでした。これじゃあ面白くない。だったら自分で改造してみましょう。
[ヒント] 繰返し処理する場合はその都度カウンタをゼロに戻すことが必要!
以下の説明文内に模範解答を掲載しています。
プログラムを書いていると、ある一連の作業を何度も繰り返す場面があります。その都度同じ処理を書いても勿論間違いではありませんが、処理をひとつの塊(ブロック)として定義することで、解かり易くバグの少ないスマートなコードを書くことができます。
*タイプインを繰り返し指定できるように改造(9999は終了) IDENTIFICATION DIVISION. PROGRAM-ID. CNT041. ENVIRONMENT DIVISION. CONFIGURATION SECTION. DATA DIVISION. WORKING-STORAGE SECTION. 01 WCNT PIC 9(04) VALUE 0. 01 CNT PIC 9(04) VALUE 0. 01 CNT1 PIC 9(03) VALUE 0. 01 WTIME. 03 HH PIC 9(02). 03 MM PIC 9(02). 03 SS PIC 9(02). 01 STIME PIC 9(06) VALUE 0. 01 ETIME PIC 9(06) VALUE 0. PROCEDURE DIVISION. A. *>8カラム目から始まり、ピリオドで終わるものを「段落」と呼びます DISPLAY "!!! CNT 9(04) TYPE-IN END・・・9999!!!" ACCEPT WCNT IF WCNT = 9999 THEN DISPLAY "<<< CNT041 - ENDED >>>" STOP RUN ELSE MOVE ZERO TO CNT CNT1 ACCEPT WTIME FROM TIME COMPUTE STIME = (HH * 3600) + (MM * 60) + SS PERFORM UNTIL CNT = WCNT ADD 1 TO CNT CNT1 IF CNT1 = 100 THEN DISPLAY CNT MOVE ZERO TO CNT1 ELSE CONTINUE END-IF END-PERFORM ACCEPT WTIME FROM TIME COMPUTE ETIME = ((HH * 3600) + (MM * 60) + SS) - STIME COMPUTE HH = ETIME / 3600 COMPUTE ETIME = ETIME - (HH * 3600) COMPUTE MM = ETIME / 60 COMPUTE SS = ETIME - (MM * 60) DISPLAY "TIME = " HH ":" MM ":" SS END-IF GO TO A. *>「A」段落に戻り、繰返し処理を可能にしている
赤色で表示されている部分「A.」ここが今回のプログラムのキモになります。COBOLプログラムでは、必ず処理は行の上から下へ、命令語が1行内に複数あれば左から右へ処理をおこないます。つまり一旦下まで処理されたプログラムを再度上位に戻すためには、何かしら目印を立ててあげる必要があるのです。この目印を手続き名(段落)と呼びます。こう断言して書いてしまうと語弊がありますが、通常は何かしら一連の処理単位で繰り返す場合に利用されています。
先ほどのプログラムでも問題なく動作はします。しますけど、GOTO命令というのは、行きっぱなしになる命令です。簡単なプログラムであれば問題ないのですが、複雑な処理になればなるほどGOTO命令でプログラムが余計複雑になる場合があります。そこで、同じ処理をよりスマートに組んでみましょう。
* 整構造化sample IDENTIFICATION DIVISION. PROGRAM-ID. CNT0042. DATA DIVISION. WORKING-STORAGE SECTION. 01 WCNT PIC 9(04) VALUE 0. 01 CNT PIC 9(04) VALUE 0. 01 CNT1 PIC 9(03) VALUE 0. 01 WTIME. 03 HH PIC 9(02). 03 MM PIC 9(02). 03 SS PIC 9(02). 01 STIME PIC 9(06) VALUE 0. 01 ETIME PIC 9(06) VALUE 0. PROCEDURE DIVISION. * ***** WCNT = 9999 まで繰返し ***** PERFORM UNTIL WCNT = 9999 DISPLAY "!!! CNT 9(04) TYPE-IN END・・・9999" * ***** WCNT の取得 ***** ACCEPT WCNT IF WCNT = 9999 THEN CONTINUE ELSE * ***** スタートタイム の取得 ***** MOVE ZERO TO CNT CNT1 ACCEPT WTIME FROM TIME COMPUTE STIME = (HH * 3600) + (MM * 60) + SS * ***** カウント の取得 ***** PERFORM UNTIL CNT = WCNT ADD 1 TO CNT CNT1 IF CNT1 = 100 THEN DISPLAY CNT MOVE ZERO TO CNT1 ELSE CONTINUE END-IF END-PERFORM * ***** エンドタイム の取得 ***** ACCEPT WTIME FROM TIME * ***** 所要時分の算出・表示 ***** COMPUTE ETIME = ((HH * 3600) + (MM * 60) + SS) - STIME COMPUTE HH = ETIME / 3600 COMPUTE ETIME = ETIME - (HH * 3600) COMPUTE MM = ETIME / 60 COMPUTE SS = ETIME - (MM * 60) DISPLAY "TIME = " HH ":" MM ":" SS END-IF END-PERFORM STOP RUN.
これが整構造と言われる手法で書かれたサンプルです。手続き名を利用しないで、「PERFORM UNTIL」にて処理の繰り返しをおこなっているのがわかりますか?
総てのプログラムは1つの入り口・1つの出口を持つSequence,Do-Until,Do-While,If-Then-Else,Caseの5つの機能の組合せで実現可能である(ダイクストラの構造化定理より)
ここら辺のことは、私よりも大先輩のVOKさんのサイト、 何で今更構造化プログラム の中で詳しく述べられているので、まずはそちらを読んでみて下さい。要約してしまえば、シンプルでより独立性の高いプログラムを1つずつ組み上げたプログラムは、絶対バグが出るはずはありません。つまりテストすらしなくていいということになります。そんなバカな…そう思う人もいるでしょうが、完全なる整構造が成されたプログラムではバグは理論上ゼロになります。興味を持たれた方は、ぜひ遊びに行ってみて下さい。