最初のページに戻ります。

総合の目次があるページに戻ります。

よく使うマニュアルです

Wiki

updated on 2004.06.23

17.16.RPGの基本 RPGサイクル2

[ Previous ] [ HOME ] [ Upper ] [ Next ]


前回のロジックをフローチャートにまとめました。情報処理試験の参考書を参考に作成しました。前と違うのは、ファイルのオープンやクローズが入っているくらいで、後は、同じです。このフローを頭にたたき込んでください。フローチャートなんて簡単です。相性占いや、性格判断の、「YES」「NO」のチャートと同じです。でも、記号にいろいろ意味を持たせていますので、よく覚えてください。情報処理試験の参考書に出ています。

keybreak1.gif (16296 バイト)

フローチャートの説明

@フローチャートは、必ず「開始 : START」で始まり、フローの最後は「終了 : END」で終わります。Aに進みます。

Aここでは、プログラムのフローを意識するので、ボールがファイルからやってくるのだ、と考えています。そこで、そのファイルをオープンします。Bに進みます。

B数を数えるための変数フィールドを「COUNT」と名付け、そこを0にしています。AAAA ← 0 は、変数AAAAに0を代入する事です。Cに進みます。

Cファイルを読み込みます。もし、EOF(End of File)なら、Jへ進み、そうでなければDに進みます。

D第1サイクルか、を判定して、もし、第1サイクルならば、Eへ進み、そうでなければ、Fへ進みます。

E比較用変数、OldBallに、今受け取ったNewBallを代入します。Fへ進みます。

FOldball = NewBallを比較します。もし、両者が同じならば、Hへ進みます。そうでなければ、Gへ進みます。

Gカウントアップ用変数Countに+1をして、その値を再び、Countに代入します。この後Cへ進みます。

ここを通る度、Countの内容は、1,2,3,4,5,....とカウントアップしていきます。右のCountは古い値のCountで、左のCountが式の結果のCountです。(※同じフィールドですよ。)カウンターの仕組みは、単純ですね。(古いCount+1)を(新しいCount)に入れているだけです。「新しい」とか「古い」とかは、式の実行順序が、最初か、最後か、と同じです。

Hカウントを印刷します。別に印刷しないでも良いのですが、なにもしなければ、なにも成果物を生まないので、こうしました。Iに進みます。

Iカウントを出力して、Countを0にしています(「ゼロクリア」とよく言います。)Gに進みます。

JCountを印刷します。本当なら、Countが0ではないなら、という条件をつけた方がいいかもしれません。ファイルが空っぽということも有るので。Kに進みます。

Kファイルを閉じます。開いたら、閉じます。開きっぱなし、というのは、かなり特殊な場合だけです。Lに進みます。

L終了

この部分は、とても重要です。分かるまで良く読み、出来れば、空で言えるくらい、暗記して下さい。本当に大事です。英語で言えば、中学初期に習う、基本的挨拶くらい重要で、誰でも知っているものです。知っていて、偉いわけではなく、「当たり前」と思われる部分です。

参考までに、RPGサイクルの詳細フロー図を掲げます。ちょっと細かすぎるので、後で簡略図を掲げます。

RPGサイクルのサンプルプログラム

では、いよいよ、サイクルのプログラムを作ってみましょう!まず、下記のようなファイルを準備をします。また、ロジックは今のボールのカウントを例に挙げます。

物理ファイルDDS:BALLP
     A*------------------------------------*
     A          R BALLR
     A*------------------------------------*
     A            COLOR          5O         COLHDG('ボールの色')
     A*
     A          K COLOR         

これを、CRTPFで作成します。COLORは5バイトのオープンフィールド(O)です。SBCSとDBCSの混在可能ということです。漢字だけで良かったのですが、順番が緑から始まって欲しかったので、このようにしています。レコード様式名はBALLRです。また、このCOLORフィールドをキーにしています。

データの内容は、以下のように入力しています。フィールドCOLORの中身です。

1緑
1緑
2赤
2赤
2赤
2赤
2赤
2赤
2赤
2赤
2赤
2赤
2赤
3青
3青
3青
3青
3青

全部で18レコードです。

もし漢字だけだと、青が先に来てしまいますが、こうすると、1が先頭に来ます。本来は、1=緑のようにコードだけで、行うところですが、RPGのサンプルがややこしくなるので、こうしました。ご容赦下さい。

さて、RPGのソースサンプルです。

(1)  H            Y/                                    1
(2)  FBALLP   IP  E           K        DISK
(3)  FQPRINT  O   F     132     OF     PRINTER
(4)  IBALLR       01
(5)  I                                              COLOR L1
(6)  C*
(7)  C                     ADD  1         O1CNT   50       
     C*
(8)  C           *INZSR    BEGSR                           
(9)  C                     TIME           O1TIME  60       
(10) C                     ENDSR                           
     O*
(11) OQPRINT  H  101   1P
(12) O       OR        OF
(13) O                                    1 'H'
(14) O                                   26 'NUMBER OF BALLS BALLR1'
(15) O                                   43 '実行日付:'
(16) O                         UDATE Y   52
     O*
(17) O        H  1     1P
(18) O       OR        OF
(19) O                                    1 'H'
(20) O                                   43 '実行時間:'
(21) O                         O1TIME    52 '0 :  :  '
     O*
(22) O        D  1     01
(23) O                                    1 'D'
(24) O                         COLOR     10
     O*
(25) O        T  1     L1
(26) O                                    1 'T'
(27) O                         O1CNT JB  20         

ソースの解説

やりたいことは、BALLPを順次読み込み、COLORフィールドの値が変わったら、そのレコード件数を印刷する、というものです。いきなりRPGソースでびっくりでしょう。分からない単語がたくさん出ているのでしょうが、平気です。どんどん先に進んで下さい。分からなくても、先に進んで下さい。やがて、必ず、分かるようになります。それから、上記のフローとの関連は、後ほど説明します。さあ、1行づつ見てゆきましょう。このソースは、「純粋な」RPGサイクルで出来ています。これが、原点です。

尚、標識という言葉が、解説の中に出てきます。これはRPG特有の概念ですが、後ほど、説明します。今は、この標識は、ONとOFFの、2つの状態を表現して、プログラムの流れを制御出きるもの、くらいに考えておいてください。

(1)  H            Y/                                    1   

これは、H仕様書ですね。Y/はYMD形式で、日付のセパレータは/と宣言していますね。後ろの1は、漢字の透過指定でしたね。覚えていますか?

(2)  FBALLP   IP  E           K        DISK          

ここは、F仕様書です。BALLPを、IPつまり、「入力」「RPGサイクル」でオープンする指定をしていますね。その後の、Eは、「外部記述」であることをRPGコンパイラに指示していますね。その後ろのKはキー付きの処理を行う指定です。もしここをスペースにすると、キー順ではなく「到着順」の指定になります。「DISK」は、データファイルの場合の決まり文句でしたね。

(3)  FQPRINT  O   F     132     OF     PRINTER             

ここも、F仕様書です。成果物である印刷をするための、印刷装置ファイル(プリンターファイル)の指定をしていますね。OはOutputつまり、出力です。Fはプログラム内部記述であることを指定しています。Outputの内部記述なので、o仕様書があることを示唆しています。(入力ファイルの内部記述のレコード定義はi仕様書で行い、出力ファイルの内部記述は、o仕様書で行います。)132の部分は、内部記述の場合、記述しなければならない項目で、132桁のレコード(レコード長)である、ということです。OFは、このプログラムで使われるオーバーフロー標識の宣言です。もし、OAと書いたら、このプログラムで使われるオーバーフロー標識は、OAとなります。ここではOFですよね。「PRINTER」は、印刷装置ファイルの場合の、決まり文句でしたね。

(4)  IBALLR       01                              

ここは、i仕様書です。BALLRは、ファイルBALLPのレコード様式です。ファイル名BALLPを記述しなくても、コンパイルは、BALLRがBALLPのレコード様式と判断できる仕組みになっています。というのは、1つのプログラム内では、同じレコード様式を、2つ以上定義できないのです。もし、同じレコード様式名を持つファイルを2つ以上定義したいならば、F仕様書で、各々のレコード様式をリネームしなくてはなりません。まあ、今は、その程度の知識でとどめて下さい。ここでは、BALLPのレコード様式、BALLRを読み込んだら、レコード標識 01 をオンにして下さい、と指定していますね。

(5)  I                                              COLOR L1         

さて、続くi仕様書で、このBALLRについて、さらに定義を続けています。BALLRの中の、COLORというフィールドが、変わったら、制御レベル標識 L1をオンにしてください、と定義しています。ここは最重要です。これが、RPGサイクルの特徴なのです。プログラムが動き出して、レコード1を一件、一件読み込んでいくときに、このCOLORフィールドの値が、変わったら(キーブレイクが起きたら)、このL1なる標識がONになるのです。この標識で、キーブレイクが起きたときに(L1がonの時に)、このようにしてくれ、と「プログラムの動き」を指定できます。

(6)  C*                              

これは、コメント行です。このほかに、H*やF*やi*やO*などもコメントです。仕様書を表す、H,F,E,i,C,Oのすぐ後に*(アスタリスク)をつければ、その行はコメント行です。コンパイラはその行を解釈しません。見やすくするためにつけたり、他のプログラマーへのメッセージとして、説明をつけたり、そんな目的でつけます。

(7)  C                     ADD  1         O1CNT   50            

ここで、C仕様書が出てきました。ADDとは、数値の足し算を行う命令です。O1CNTは、プログラマーが自由に決めることが出来る、フィールドを定義している部分です。なんでも良いのですが、6文字以内で、英語のアルファベットなどで始まり、後は英数で構成されるフィールド名をあなたが決めます。ここでは、出力目的なので、Oで始まるフィールドにしました。(何でも良いのですよ)。この後ろに続く、50とは、全体の桁数5桁、小数点以下は0桁、つまり、数字整数5桁、を指定しています。もし、外部記述のファイルのフィールドならば、属性(フィールドタイプとか桁数など)を定義する必要はありません。コンパイラが勝手に、ファイル記述から取り込んでくれます。また、定義方法は、このほかに、データ構造や、*LIKE DEFNとかありますが、今は、まだ気にしないで下さい。

C仕様書は。大まかに言うと、「条件標識」「演算項目1」「命令語」「演算項目2」「結果」「結果フィールド属性」「結果の標識」に分かれています。

条件標識 演算項目1 命令語 演算項目2 結果 結果フィールド属性 結果の標識
    ADD 1 O1CNT 50  

この行を別の言語で表現すると、O1CNT [結果] = O1CNT [演算項目1] + 1 [演算項目2]となります。このADD 1   O1CNTは、本来、O1CNT     ADD 1       O1CNTなのです。つまり、O1CNT + 1 = O1CNT(普通の表現とは逆ですね)。※数学の式とは、違いますよ。コンピュータ言語独特の表現です。

条件標識 演算項目1 命令語 演算項目2 結果 結果フィールド属性 結果の標識
  O1CNT ADD 1 O1CNT 50  

と同じ事なのですが、RPGでは、「演算項目1」=「結果」の場合、演算項目1を省略できます。したがって、ソースのように、演算項目1をスペースにしています。この演算により、O1CNTの中身は、1,2,3,4,5,...と1づつカウントアップしていきます。

(8)  C           *INZSR    BEGSR                

ここもC仕様書です。ここからは、サブルーチンとなります。BEGSRがキーワードです。ここと、ENDSRがペアになり、ここで囲まれた、部分が、1つのサブルーチンとなります。サブルーチンとは、何度も使われる部分を、独立させて定義したプログラムの一部の事です。また、定義の書式もある程度決まっています。BEGSRはBeginning   of SubRoutineの事です。

ところで、この*INZSRはとても、特殊です。RPG全体を通じて、*で始まる名前は、特殊な予約語と考えて下さい。もともと、*で始まるフィールドは定義できません。でも、この*INZSRは、特別にRPGが準備している予約サブルーチンです。これは、まさにこのサンプルにぴったりの場合に使われるものです。*INZSRが無いころは、後述する、標識1Pは、一切C仕様書を通らずに、いきなり、o仕様書の1Pを指定された部分を印刷していたのです。しかし、これでは時間の印刷(TIME命令)が不可能な為に、追加されたサブルーチンでした。このサブルーチンは、プログラムを呼び出した直後の初期処理で、実行される特殊なサブルーチンです。

条件標識 演算項目1 命令語 演算項目2 結果 結果フィールド属性 結果の標識
  サブルーチン名 BEGSR        

昔は、CSRと定義したことも有りますが、RPG2での話しで、今は省略しています。もし、CSR      XXXX BEGSRというのを見かけたら、かなり古いプログラムと考えて良いでしょう。

H    
F    
E    
L    
I    
C メインルーチン EXSR A
EXSR B
EXSR C
サブルーチンA BEGSR
ENDSR
サブルーチンB BEGSR
ENDSR
サブルーチンC BEGSR
ENDSR
O    
**    

このように、サブルーチンは、C仕様書の最後の方に定義します。

 

(9)  C                     TIME           O1TIME  60            

ここは、サブルーチン*INZSRの中身です。時間を印刷するために、TIME命令で、時間をとりだしています。

条件標識 演算項目1 命令語 演算項目2 結果 結果フィールド属性 結果の標識
    TIME   時間+日付 60 or 120 or 140  

この結果のフィールドの桁数は重要です。整数6桁か12桁か14桁で、結果のフィールドに入る値が異なります。

  1. 6.0の場合    システム時間6桁のみが結果のフィールドに入ります。例)101531つまり10:15:31

  2. 12.0の場合    システム時間6桁と、システム日付6桁が結果のフィールドに入ります。例)101531981231つまり10:15:31と98/12/31

  3. 14.0の場合    システム時間6桁と、システム日付8桁が結果のフィールドに入ります。 例)10153119981231つまり10:15:31と1998-12-31

注意:システム日付の日付の形式は、ジョブ環境の日付の形式に由来します。H仕様書のY/の効果は及びません。(Y/はUDATEや*DATEだけです)

(10) C                     ENDSR                              

ここで、サブルーチンの定義は終了します。ENDSRとはEnd SubRoutineの事です。

条件標識 演算項目1 命令語 演算項目2 結果 結果フィールド属性 結果の標識
  タグ名 ENDSR エラー復帰      
(11) OQPRINT  H  101   1P                              
 OQPRINT  H  101   1P
見出し1行目
 O       OR        OF
 O                                    1 'H'
 O                                   26 'NUMBER OF BALLS BALLR1'
 O                                   43 '実行日付:'
 O                         UDATE Y   52
 OQPRINT  H  1     1P
見出し2行目
 O       OR        OF
 O                                    1 'H'
 O                                   43 '実行時間:'
 O                         O1TIME    52 '0 :  :  '
 OQPRINT  D  1     01
明細1行目
 O                                    1 'D'
 O                         COLOR     10
 OQPRINT  T  1     L1
合計1行目
 O                                    1 'T'
 O                         O1CNT JB  20

o仕様書の始まりです。印刷の1行目の定義です。このQPRINTはF仕様書で、定義してありましたね。132桁でオーバーフロー標識はOFでしたね。ここに書くことが出来るのは、F仕様書で指定したファイルのみです。Hはヘッダーの事です。帳票の見出しに当たる部分を定義します。101は、最初の「1」は、「印刷後スペース1行(ベタ打ち)」、その次の「01」は「印刷前に絶対行01へスキップ」という指示でしたね。

ここででてくる、1Pは特殊です。サイクルの中で、*INZSRの直後にONになる標識です。以下の項目を印刷する条件を制御しています。プログラムの中で、この1PがONになるのは、一回だけです。2Pや3Pなんて、有りません。

※この標識1PがONになっても、まだファイルのレコードは一件も読み込まれていないことに注意して下さい。レコードのデータはこの部分では、印刷出来ません。

(12) O       OR        OF      

この、部分では、OR(もしくは)の指定が有りますね。以下の項目を印刷する条件に、OR条件が付加されています。それは、OFがonになったらという場合です。オーバーフローになったら、この部分を実行してくれ、と指示しているのです。

(13) O                                    1 'H'  

ここからは、印刷する項目を指定しています。印刷用紙(実際は出力域:出力バッファ。以前に入力域のお話をしましたよね。その逆に、今度は出力する場合の緩衝域のことです。)の1桁めに「H」を印刷しています。本来こんなもの印刷しなくて良いのですが、後で印刷物を見てわかりやすいようにしただけです。実務ではこんなものは印刷しません

(14) O                                   26 'NUMBER OF BALLS BALLR1' 

これは、帳票のタイルのつもりです。26桁をおしりにして、印刷する指示です。BALLR1とはこのRPGの名前です。本当はプログラム名を取りだす最もいい方法が有るのですが、ここではふれません。いづれ、「プログラム状況データ構造」で説明します。

5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

N

U

M

B

E

R

 

O

F

 

B

A

L

L

S

 

B

A

L

L

R

1

(15) O                                   43 '実行日付:'  

ここは、「実行日付:」を、43桁をおしりにして、印刷する指示です。漢字ですので、0e0fが漢字の前後に付くのでしたよね。

33 34 35 36 37 38 39 40 41 42 43
0e 0f :
(16) O                         UDATE Y   52       

ここでは、ジョブ日付を52桁をおしりにして、編集コードYで印刷する指示をしています。後ろの桁の指定をはずすと、「位取り基数法」の0が指定されたのと同じになり、一つ前のフィールドにぴったりとくっつきます。また、52の代わりに、+   1を指定すると、一桁スペースを開けて、前のフィールドにくっつきます。桁数を数得るのが面倒な場合に使います。

45 46 47 48 49 50 51 52
9 8 / 1 0 / 2 5

上記3つをまとめると、

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
H       N U M B E R   O F   B A L L S   B A L L R 1  
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
          0E 0F :   9 8 / 1 0 / 2 5

となります。

(17) OQPRINT  H  101   1P                              

ここから印刷の2行目の定義です。あとは1行目と同じです。Oの次がスペースですよね。ここは、QPRINTと入っていても良いのですが、省略可能です。省略した場合は、一つ上のファイル名が継承されます。

(18) O       OR        OF                              

1行目の定義と同じです。

(19) O                                    1 'H'          

1行目の定義と同じです。

(20) O                                   43 '実行時間:'     

ここでは、43桁をおしりに、「実行時間:」と印刷していますね。

(21) O                         O1TIME    52 '0 :  :  '    

ここでは、*INZSRで取りだした、時間を印刷しています。時間用の編集コードは無いので、編集語を使います。もし、'   :  :  'と0を入れないと、午前0時ちょうどの時、なにも印刷されません。気をつけましょう。

上記3つをまとめると、

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
H                                                    
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
          0E 0F :   1 0 : 1 5 : 3 1
(22) O        D  1     01                              

ここからは、明細行(レコードを読む度に印刷する)部分の定義です。Dが明細Detailを意味しています。1は印刷後1スペース(ベタ打ち)です。01はレコード標識です。これが無いと、o仕様書に来る度に、無意味に印刷するので、H印刷の時に、無駄に1行印刷してしまいます。そこで、ファイルを読んだら、という条件で、BALLRのレコード標識01を条件付けします(i仕様書を参照)。

(23) O                                    1 'D'      

ここでは、1桁目に「D」を印刷します。本来こんなもの印刷しなくて良いのですが、後で印刷物を見てわかりやすいようにしただけです。実務ではこんなものは印刷しません

(24) O                         COLOR     10       

ここでは、レコード様式BALLRの中のフィールド、COLORを10桁目をおしりに印刷しています。注意事項があります。ここで、Blank After(後述)を指定してしまうと、L1はここで印刷する度にONになります。注意しましょう。

(25) O        T  1     L1                              

ここから、合計時の印刷の定義です。TはTotalの意味です。キーブレイクが起きた場合の定義です。L1はi仕様書のレベル標識L1と関連づけるために指定します。これで、L1がONになったときだけ、実行される部分となりました。

(26) O                                    1 'T'        

ここでは、1桁目に「T」を印刷します。本来こんなもの印刷しなくて良いのですが、後で印刷物を見てわかりやすいようにしただけです。実務ではこんなものは印刷しません

(27) O                         O1CNT JB  20         

ここで、C仕様書で、カウントしていた、O1CNTを、20桁目をおしりにして、編集コードJで印刷しています。その後のBは、Blank Afterのことで、印刷が完了すると。数字なら0に、文字ならばブランクにしてくれます。便利な反面、ロジックが分散(集計値を0にするタイミングは重要なので)するため、Blank Afterの使用を禁止する場合もあります。私は、便利なので、ばんばん使っています。集計して、印刷すれば、用の無くなった、集計値は、印刷直後に消えてくれればいいわけです。Blank Afterは、よく考えられた、オプションと考えています。

実行結果

これが、実行結果です。ここはPC上なので、漢字の前後に0E0Fが入っているものが、無くなっていることに注意して下さい。本来は、漢字の前後に1スペース空いています。

H   NUMBER OF BALLS BALLR1      実行日付: 98/10/10
H                               実行時間:  9:24:16
D    1緑
D    1緑
T                 2
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
D    2赤
T                11
D    3青
D    3青
D    3青
D    3青
D    3青
T                 5                                               

だいぶ、この講義も長くなってきました。フローチャートとの関連や、その他の例など、は次回以降に説明します。解説部分を良く読んで、ソースリストだけ見て、その内容を理解できるようにして下さい。では、今日は、ここまで。

起立、礼、着席

1998/10/25


[ Previous ] [ HOME ] [ Upper ] [ Next ]

You are at K's tips-n-kicks of AS/400

 

SEO [PR] 爆速!無料ブログ 無料ホームページ開設 無料ライブ放送