![]() | プログラムの呼び出し | システムと開発環境による制限 | ![]() |
この章では、COBOL の拡張開発機能のいくつかを紹介します。これらの機能を使用して開発上の一般的な問題を解決すると、アプリケーションのパフォーマンスを向上させることができます。アプリケーションのコードが、より単純になる場合もあります。
再帰ルーチンとは自身を呼び出すルーチンのことです。再帰ルーチンは、次の各処理の最も一般的な実装手段です。
再帰ルーチンのかわりに同じルーチンを繰り返し記述することも可能ですが、再帰ルーチンを使用するとプログラムのロジックが単純になります。
Server Express システムでは、他のプログラム内でネストされておらず、局所記憶節 (LOCAL-STORAGE SECTION) を持つプログラムであれば、自身を再帰的に呼び出すことができます。プログラムの再帰的な呼び出しには、プログラム自身の PROGRAM-ID または入口点を使用します。
再帰ルーチンの呼び出しを行うと、そのたびにルーチンのインスタンスが 1 つ開始されます。再帰ルーチンの各インスタンスでは、ルーチン内で使用される一連のデータ項目を、それぞれ独自に確保する必要があります。そのための手段として Server Express システムで利用できるのが局所記憶節です。再帰ルーチンの新しいインスタンスを開始すると、局所記憶節で定義された一連のデータ項目が新たに初期化され、メモリに格納されます。これらのデータ項目は、対応するインスタンスが終了するとクリアされます。局所記憶節を持たないプログラムで再帰呼び出しを試みると、ランタイムエラーのメッセージが表示されます。
次に COBOL の再帰プログラムの具体例を示します。このコード例は、ある人物を頂点とする家系データの表を読み取り、家系内の各個人を次々にチェックして、子供を持たない個人の名前を表示します。
この例では、family-tree
項目に家系データの表が格納されています (この表には、ある人物とその子孫に対応するエントリがあらかじめ登録されているものとします)。表の最初のエントリが、家系の最上位の人物に対応します。各エントリには該当する個人の名前のほか、その個人の第一子に関するエントリの表内での位置 (eldest-pointer
項目)、およびその個人の次の弟または妹に関するエントリの位置 (sibling-pointer
項目) が含まれています。子供を持たない個人の eldest-pointer
の値、および弟や妹がいない個人の sibling-pointer
の値は、それぞれ 99 に設定されています。
identification division. program-id. family. . . . working-storage section. 01 family-tree. 03 individual occurs 50. 05 ind-name pic x(30). 05 eldest-pointer pic 9(2). 05 sibling-pointer pic 9(2). local-storage section. 01 tree-pointer pic 9(2). linkage section. 01 parent-pointer pic 9(2). procedure division. move 1 to tree-pointer call "children" using tree-pointer stop run. entry "children" using parent-pointer move eldest-pointer(parent-pointer) to tree-pointer if tree-pointer = 99 display ind-name(parent-pointer) else perform until tree-pointer = 99 call "children" using tree-pointer move sibling-pointer(tree-pointer)to tree-pointer end-perform end-if.
子供を持たない個人のエントリが見つかると、children
ルーチンはその個人名を表示して終了します。それ以外の場合には、children
ルーチンはその個人の第一子から順次、すべての子供を対象に自身を再帰的に呼び出します。
この例では、入口点 factorl
で識別されるルーチンによって、ユーザが入力した数値の階乗が計算されます。
1 working-storage section. 2 01 n pic x(4) comp-x. 3 01 factorial pic x(4) comp-x. 4 01 m pic x(4) comp-x. 5 6 local-storage section. 7 8 procedure division. 9 accept n 10 move 1 to factorial 11 call "factorl" using n 12 display "factorial of " n " is " factorial 13 stop run. 14 15 entry "factorl" using m. 16 if m < 1 17 move 1 to factorial 18 else 19 if m > 1 20 multiply m by factorial 21 subtract 1 from m 22 call "factorl" using m 23 end-if 24 end-if 25 26 exit program.
6 行め
local-storage section
再帰ルーチンは複数回にわたって呼び出される可能性があるため、1 つの呼び出しで使用するローカルデータを、同じコードの別の呼び出しから保護する必要があります。この保護機能を実現するのが局所記憶節です。ルーチンのインスタンスが生成されるたびに、局所記憶節で定義された一連のデータ項目が新たに初期化され、メモリ上に確保されます。局所記憶節を持たないプログラムで再帰呼び出しを試みると、ランタイムシステムエラーのメッセージが表示されます。
このコード例にはローカル記憶域を使用するデータ項目はありませんが、そのようなデータ項目の有無にかかわらず、再帰ルーチンには局所記憶節の宣言が必要です。
15 行め
entry 'factorl' using m.
再帰ルーチン factorl
の入口点。プログラムの再帰的な呼び出しには、プログラム自身の PROGRAM-ID または入口点を使用します。
19-23 行め
if m > 1 multiply m by factorial subtract 1 from m call 'factorl' using m end-if
このループに再帰呼び出しが含まれています。
22 行め
call 'factorl' using m
再帰呼び出しを行う CALL 文。
COBOL データ項目の内容は、STRING 文と部分参照という 2 通りの手段で操作できます。
STRING 文は使いやすく、シンプルなコードで記述できますが、その半面でリソース消費が比較的大きいという欠点があります。特に、プログラム内で繰り返し使用される場合には、多くのリソースを消費します。そのため、そのほかに負荷の大きな処理 (頻繁なファイル入出力など) を行わないプログラムに適しています。
部分参照は STRING に比べ、処理効率の面では優れていますが、コードの読解と保守がより困難になる可能性もあります。STRING 文を頻繁に使用してプログラムの速度が低下したり、リソース消費が増大したりする場合に、パフォーマンスを改善する手段として効果的です。
次に示す 2 つの文の一方は STRING、もう一方は部分参照を使用して同じ処理を実装しています。どちらの文でも、street-address
のサイズは 25 バイトです。
string street-address delimited by size into print-rec with pointer num-char
move street-address to print-rec (num-char: 25)
STRING 文と部分参照の詳細については、『言語リファレンス』を参照してください。
文内で組み込み関数を使用すると、その文の実行中にデータ項目に値を格納できます。
組み込み関数を使用した文の例を次に示します。
compute x = function cos(y)
この文は、組み込み関数 cos
の結果をデータ項目に入れます。cos
によって、引数 y
で渡した角度 (ラジアン単位) の逆余弦が計算され、x
に入れます。
組み込み関数の詳細については、『言語リファレンス』を参照してください。
このサンプルファイル (intrins.cbl) は、プログラムで組み込み関数を利用するいくつかの方法を示しています。
注: 組み込み関数には、整数型関数、数字型関数、英数字型関数の 3 種類があります。このサンプルで使用している FACTORIAL は、数字型関数の 1 つです。ここで紹介しているコーディング方法が、他の種類の組み込み関数にも有効であるとは限りません。
1$set mf noosvs ans85 2 3********************************************************* 4* Copyright © 2002 Micro Focus International Limited. All rights reserved. * 5* このサンプルプログラム (以下、「本サンプル」と記する) * 6* は Micro Focus 社製品のユーザ向けに提供されており、当該ユ * 7* ーザは自身のアプリケーションの一部として、本サンプル * 8* を使用、変更、および配布することができます。ただし、 * 9* 本サンプルの著作権は Micro Focus 社に帰属します。 * 10********************************************************* 11 12********************************************************* 13* * 14* INTRINS.CBL * 15* * 16* このプログラムは、COBOL アプリケーションで組み込み * 17* 関数を使用するいくつかの方法を示しています。 * 18* 具体的には、FACTORIAL 関数を使用して次の各処理を * 19* 実行します。 * 20* * 21* 1) 関数値をデータ項目に入れる。 * 22* 2) 関数を EVALUATE 文内でデータ項目 * 23* として使用する。 * 24* 3) 関数を IF 文内でデータ項目として * 25* 使用する。 * 26* 4) 関数の引数として表要素 (固定) を * 27* 使用する。 * 28* 5) 関数の引数として表要素 (可変) を * 29* 使用する。 * 30* 6) 関数値を引数として関数に渡し、 * 31* その戻り値をデータ項目に入れる。 * 32* 7) 関数値を入れたデータ項目を COMPUTE * 33* 文で使用する。 * 34* 8) 2 つの関数値の合計をデータ項目に * 35* 入れる。 * 36* 9) 関数を PERFORM ... UNTIL 文の * 37* UNTIL 指定の条件として使用する。 * 38* * 39* * 40* 組み込み関数の構文について理解するには、Animator * 41* 上で INTRINS を実行する方法が有効です。 * 42* * 43* プログラムを次の指令でコンパイルします。 * 44* * 45* COBOL INTRINS ANIM; * 46* * 47* 次のコマンドでアニメートします。 * 48* * 49* ANIMATE INTRINS * 50* * 51* * 52* 詳細については、『言語リファレンス』と * 53* 『PC Programmer's Guide』を参照してください。 * 54* * 55********************************************************* 56 working-storage section. 57 78 fals value 0. 58 78 tru value 1. 59 60 01 true-or-false pic 9(1). 61 62 01 factor pic s9(10). 63 64 01 val pic s9(10). 65 66 01 indx pic 9(5) comp-x. 67 68 01 arg pic 9(2) comp-x value 5. 69 70 01 arr value "40537". 71 03 elem occurs 5 times pic 9. 72 73 procedure division. 74 75 main-section. 76 77********************************************************* 78* 例 1 − 関数値をデータ項目に入れます。 * 79* * 80********************************************************* 81 82 compute factor = function factorial(0) 83 84********************************************************* 85* 例 2 − 関数を EVALUATE 文のデータ項目 * 86* として使用します。 * 87********************************************************* 88 89 evaluate function integer(6.5) 90 when 6 91 move tru to true-or-false 922 when other 93 move fals to true-or-false 94 end-evaluate 95 96********************************************************* 97* 例 3 − 関数を IF 文のデータ項目として * 98* 使用します。 * 99********************************************************* 100 101 if function integer (function factorial(arg)) = 120 102 then move tru to true-or-false 103 else 104 move fals to true-or-false 105 end-if 106 107********************************************************* 108* 例 4 − 関数の引数として表要素 (固定) * 109* を使用します。 * 110********************************************************* 111 112 compute factor = function factorial(elem(4)) 113 114********************************************************* 115* 例 5 − 関数の引数として表要素 (可変) * 116* を使用します。 * 117********************************************************* 118 119 move 4 to indx 120 compute factor = function factorial(elem(indx)) 121 122********************************************************* 123* 例 6 − 関数値を引数として関数に渡し、その戻り値を * 124* データ項目に入れます。 * 125********************************************************* 126 127 compute factor = function factorial( 128 function factorial(3)) 129 130********************************************************* 131* 例 7 − 関数値を入れたデータ項目を COMPUTE * 132* 文で使用します。 * 133********************************************************* 134 135 compute val = function factorial(3) + 5 136 137********************************************************* 138* 例 8 − 2 つの関数値の合計をデータ項目に * 139* 入れます。 * 140********************************************************* 141 142 compute val = function factorial(3) + 143 function factorial(5) 144 145********************************************************* 146* 例 9 − 関数を PERFORM ... UNTIL 文 * 147* の UNTIL 指定の条件として使用します。 * 148********************************************************* 149 150 move 1 to indx 151 perform para-1 until function integer (function 152 factorial(indx)) = 120 153 stop run. 154 155 para-1. 156 compute indx = indx + 1.
82 行め
compute factor = function factorial(0)
組み込み関数の値をデータ項目に入れています。
89 〜 94 行め
evaluate function integer(6.5) when 6 move tru to true-or-false when other move fals to true-or-false end-evaluate
組み込み関数を EVALUATE 文のデータ項目として使用しています。
101 〜 105 行め
if function integer (function factorial(arg)) = 120 then move tru to true-or-false else move fals to true-or-false end-if
組み込み関数を IF 文のデータ項目として使用しています。
数字型関数の結果は浮動小数点型であり、整数値は期待できません。この例では、IF 文の条件として整数を使用するため、integer
関数値を整数に変換しています。
112 行め
compute factor = function factorial(elem(4))
組み込み関数の引数として、固定の配列要素を使用しています。
119 〜 120 行め
move 4 to indx compute factor = function factorial(elem(indx))
組み込み関数の引数として、可変の表要素を使用しています。
127 〜 128 行め
compute factor = function factorial (function factorial(3))
関数値を引数として関数に渡し、その戻り値をデータ項目に入れています。
135 行め
compute val = function factorial(3) + 5
組み込み関数値を入れたデータ項目を COMPUTE 文で使用しています。
142 〜 143 行め
compute val = function factorial(3) + function factorial(5)
2 つの組み込み関数値を合計し、その結果をデータ項目に入れています。
150 〜 156 行め
move 1 to indx perform para-1 until function integer (function factorial(indx)) = 120 stop run. para-1. compute indx = indx + 1.
組み込み関数を PERFORM ... UNTIL 文の UNTIL 指定の条件として使用しています。
環境変数の操作には X/Open で定義された構文を使用します。DISPLAY ... UPON ENVIRONMENT-NAME
構文で環境変数の名前を ENVIRONMENT-NAME
に格納し、続いて ACCEPT ... FROM ENVIRONMENT-VALUE
構文でその値を取得する、または DISPLAY ... UPON ENVIRONMENT-VALUE
構文で変更します。
これらの構文を使用すると、アプリケーションの実行中に環境変数の設定を動的に変更できます。
アプリケーションが使用する環境変数空間を X/Open の構文で読み取り、更新を行うと、物理ファイルに関連付けられた論理ファイルを変更できます。変更後のファイルには、COBOL の入出力構文でアクセスします。
アプリケーションの実行中に変更した環境変数の値は、そのアプリケーションが終了するとオリジナルの値に戻ります。アプリケーションの実行中には、最大 64 KB のメモリ領域を環境変数で使用できます (この値は上限値であり、実際の値は物理メモリの空き容量に左右されます)。
COBOL による開発では、文字や項目、レコード、ファイルなどのほか、ビット単位でのデータ操作も必要になります。たとえば、次のような処理を行うアプリケーションにはビット操作が必要です。
Server Express ランタイムシステムの COBOL システムライブラリルーチンには論理演算ルーチンが含まれており、ビット操作を容易に実行できます。
各種の論理演算における入力ビットと出力ビットの関係を次に示します。
A | 0 | 0 | 1 | 1 | |
B | 0 | 1 | 0 | 1 | |
CBL_NOT | (NOT A) | 1 | 1 | 0 | 0 |
CBL_AND | (A AND B) | 0 | 0 | 0 | 0 |
CBL_OR | (A OR B) | 0 | 1 | 1 | 1 |
CBL_EQ | (A EQ B) | 1 | 0 | 0 | 1 |
CBL_XOR | (A XOR B) | 0 | 1 | 1 | 0 |
CBL_IMP | (A IMP B) | 1 | 1 | 0 | 1 |
たとえば、ビット A とビット B の CBL_EQ (論理等価) では、A と B がともに 0 (または 1) であれば結果ビットは 1、それ以外であれば 0 になります。
論理演算ルーチンの構文を紹介する前に、構文で使用するデータ項目を次に示します。
データ項目 |
説明 |
source |
入力データ項目。形式は任意。 |
target |
出力データ項目。形式は任意。 |
length |
source と target のバイト長。左端のバイトから開始される。 |
CBL_NOT 以外の各ルーチンは次の規則に従います。
すべての論理演算ルーチンは、次の規則に従います。
length
オペランドによって演算範囲のバイト長が指定される。target
データ項目が length
で指定されたサイズより長い場合は、target
の残りの部分は変更されない。警告: source
や target
が length
の値より短い場合は、該当するデータ項目の直後のバイトが、不足するバイト数だけ処理されます。
CBL_NOT ルーチンは次の構文で使用します。
call "CBL_NOT" using target by value length
CBL_NOT |
データ項目の target の各ビットの論理否定。 |
その他のビット操作ルーチンの構文では、以下のとおりです。
call "log_oper" using source target by value length
log_oper
には、次のいずれかを指定します。
CBL_AND |
2 つのデータ項目の対応するビット間の論理積。 |
CBL_OR |
2 つのデータ項目の対応するビット間の論理和。 |
CBL_EQ |
2 つのデータ項目の対応するビット間の論理等価。 |
CBL_XOR |
2 つのデータ項目の対応するビット間の排他的論理和。 |
CBL_IMP |
2 つのデータ項目の対応するビット間の論理包含。 |
論理演算用のライブラリルーチンの詳細については、『ライブラリルーチン』の章を参照してください。
Copyright © 2002 Micro Focus International Limited. All rights reserved.
本書、ならびに使用されている固有の商標および商品名は国際著作権法で保護されています。
![]() | プログラムの呼び出し | システムと開発環境による制限 | ![]() |