値の検索方法/値の更新方法
まず、更新するレコード (行) を検索する必要があります。これは通常、特定のキー値をテーブルで検索することによって行われます。COBOL には、これを行うための方法がいくつか用意されています。COBOL SEARCH
ステートメントを確認することから始めることをお勧めします。STRUCT-1
レコードがソートされている場合は、 を使用できますSEARCH ALL
。それ以外の場合はSEARCH
、独自の検索ループを使用するか、コーディングする必要があります。これらの手法を使用するには、プログラムのどこかで別の変数を宣言して、STRUCT-1
テーブルへのインデックス (オフセット) として使用する必要があります。COBOL では、特定のテーブルに固有のインデックスを宣言するためINDEXED BY
の句が句に
用意されています ( OCCURSを参照) 。OCCURS
STRUCT-1
更新する行を指すようにインデックスを設定したらMOVE
、その行内の適切な変数に値を設定します。たとえば、
123.456 を VALUE-2 (IDX-1) に移動
ここで、IDX-1 は上記のインデックスです。整数またはインデックス変数を使用して、更新する行番号を指定できることに注意してください。INDEX 型変数の使用に限定されません。ただし、一般に、他のタイプの変数よりも INDEX 変数を使用する方が効率的です。特に、プログラムがテーブルを多数参照する多次元テーブルを操作する場合は特にそうです。
新しい行を追加する方法
STRUCT-1
最初に、正確に 25 行が含まれていることを認識します。COBOL には、この数を動的に増減するメカニズムがありません (これは次の ISO COBOL 標準で可能になると聞いていますが、息を止めないでください)。技術的には、25 行すべてをいつでも使用できます。ただし、一般的な規則は、一度に 1 行ずつ、テーブルを空の状態から完全な状態に順次「成長」させることです。この規則を使用するには、最後に使用された行番号を追跡する変数を割り当てる必要があります (プログラムの起動時にこの変数をゼロに初期化することを忘れないでください)。あなたの例では、変数がこの仕事をしているように見えますNUMBER-OF-OCCURS
(私はそれについて言及しませんでしたが、上記の検索をバインドするにはこの変数が必要です)。
行を「追加」するには、1 だけインクリメントNUMBER-OF-OCCURS
します。テーブル サイズを超えないように注意してください。コード例は次のとおりです。
IF NUMBER-OF-OCCURS < (LENGTH OF TABLE-1 / LENGTH OF STRUCT-1 (1))
ADD +1 TO NUMBER-OF-OCCURS
ELSE
table is full, preform some error/recovery routine
END-IF
上記のコードは、発生回数の明示的な使用を回避しますTABLE-1
。これにより、OCCURS の回数が変更された場合に、多数のメンテナンスの問題を回避できます。
下部の注を参照してください。ここには非常に大きな Woops があります。わかりましたか?
検索問題に戻ります。次のコード例は、どのように進めるかを示しています。
WORKING-STORAGE 宣言:
01 FOUND-IND PIC X(1).
88 FOUND-YES VALUE 'Y'.
88 FOUND-NO VALUE 'N'.
77 MAX-IDX USAGE IS INDEX.
01 TABLE-1.
05 STRUCT-1 OCCURS 25 TIMES INDEXED BY IDX-1.
10 VALUE-1 PIC AAA.
10 VALUE-2 PIC 9(5)V999.
05 NUMBER-OF-OCCURS PIC 99.
追加されたもの:
FOUND-IND
探している行が見つかったかどうかを示すために使用されます。88 レベルは、設定/テストする特定の値を提供します
MAX-IDX
検索の上限を設定するために使用されます。NUMBER-OF-OCCURS
上限テストで使用できますが、これはすべてのテストでデータ型変換を強制するため、あまり効率的ではありません
IDX-1
テーブルへのインデックス (オフセット) として使用されSTRUCT-1
ます。
個人的には、あなたが持っているものはうまくいくと宣言NUMBER-OF-OCCURS
しPIC S9(4) BINARY
ます。
STRUCT-1
これがソートされておらずNUMBER-OF-OCCURS
、現在アクティブな行数を表していると仮定すると、値「ABC」を探すときSTRUCT-1
のコード例は次のようになります。SEARCH
SET FOUND-NO TO TRUE
IF NUMBER-OF-OCCURS > ZERO
SET IDX-1 TO 1
SET MAX-IDX TO NUMBER-OF-OCCURS
SEARCH STRUCT-1
WHEN IDX-1 > MAX-IDX
CONTINUE
WHEN VALUE-1 (IDX-1) = 'ABC'
SET FOUND-YES TO TRUE
END-SEARCH
END-IF
IF FOUND-YES
row found, use IDX-1 to reference the row containing 'ABC'
ELSE
row not found, IDX-1 does not contain a valid index
END-IF
使い方:
FOUND-NO
trueに設定して、行がテーブルにないと仮定することから始めます。
- 1つ目は、検索を開始する前に
IF
アクティブな行が少なくとも 1 つあることを確認しSTRUCT-1
ます (INDEX をゼロに設定するとエラーになるため、それを防ぐ必要があります)。
- は
SEARCH
、最初のSEARCH WHEN
句が満たされると終了します。そのため、検索する行がなくなったときに動詞「何もしない」CONTINUE
を使用できます。他の終了条件 (探している値を見つける) は、FOUND-YES
設定できる唯一の場所です。
- が
SEARCH
完了したら、成功または失敗をテストし、それに応じて対処します。
あなたが研究するためのいくつかの演習:
- ステートメント
AT END
で句をコーディングする必要がなかったのはなぜですか?SEARCH
- ステートメントで
VARYING
句をコーディングする必要がなかったのはなぜですか?SEARCH
WHERE
節をこの順序でコーディングしたのはなぜですか?
これが正しい道を歩み始めることを願っています。
編集
コメントでの質問への回答:検索のインデックスとして NUMBER-OF-OCCURS を使用できますか。答えはイエスですが、いくつかの異なるルールを実装する必要があります。インデックスとして使用NUMBER-OF-OCCURS
すると、現在有効なデータが含まれている行数を追跡するために使用できなくなります。これは、 で未使用の行を識別する別のメカニズムが必要であることを意味しますSTRUCT-1
。LOW-VALUE
これは、未使用の行を、実際にはテーブルに入れたくないセンティナル値 (例: ) で初期化することによって実現できます。は次のSEARCH
ようになります。
SET FOUND-NO TO TRUE
MOVE 1 TO NUMBER-OF-OCCURS
SEARCH STRUCT-1 VARYING NUMBER-OF-OCCURS
WHEN VALUE-1 (NUMBER-OF-OCCURS) = 'ABC'
SET FOUND-YES TO TRUE
END-SEARCH
上記は、検索STRUCT-1
している値 (つまりABC
) がテーブルにない場合に、すべての行を検索します。WHEN
最適化として、センティナル値が見つかったときに検索を終了する 2 番目の句を追加できます。
WHEN VALUE-1 (NUMBER-OF-OCCURS) = LOW-VALUE
CONTINUE
上記の仮定LOW-VALUE
は、未使用の行を識別するために使用されました。
このソリューションでは必要ないため、作業用ストレージからIDX-1
削除することもできます。MAX-IDX
インデックスとして使用NUMBER-OF-OCCURS
すると、空の行を検索して新しい値を挿入する方法を変更する必要があることも意味します。LOW-VALUE
これを行う最も簡単な方法は、 の代わりに上記のコード for を使用してテーブルを検索することです'ABC'
。FOUND-YES
検索の最後に が設定されている
場合NUMBER-OF-OCCURS
、 は最初の未使用行のインデックスです。が設定されている場合FOUND-NO
、テーブルはすでにいっぱいです。
上記のコードは、最初に提案したものよりもはるかに単純です。では、なぜもっと
複雑なソリューションを提供したのでしょうか。より複雑なソリューションは、テーブルを実行する際の内部オフセット計算とデータ型変換が大幅に少なくなるため、より効率的です。SEARCH
また、次の未使用の行を見つけるために追加を行うことも回避
します。これらの効率はアプリケーションでは問題にならないかもしれませんが、テーブルが大きくて頻繁にアクセスされる場合は、テーブルの検索と強制的なデータ型変換 (たとえば、PIC 99
フィールドをインデックス参照に変換するコスト) のパフォーマンス面に注意する必要があります。 .
ノート:
LENGTH OF
特殊レジスターを使用してテーブルがいっぱいかどうかを計算する私の元の例は、この例では機能しますが、非常に悪い組み込みの仮定があります! にはLENGTH OF TABLE-1
、STRUCT-1
テーブルだけでなく、も含まれNUMBER-OF-OCCURS
ます。の長さは のNUMBER-OF-OCCURS
1 回の出現に満たないSTRUCT-1
ため、結果が切り捨てられて整数値になるため、すべて正常に機能します。これは、間違った理由で正しく動作するコードの非常に良い例です! 適切な計算を行うには、作業用ストレージを次のように調整する必要があります。
01 TABLE-1.
05 STRUCT-TABLE.
10 STRUCT-1 OCCURS 25 TIMES.
20 VALUE-1 PIC AAA.
20 VALUE-2 PIC 9(5)V999.
05 NUMBER-OF-OCCURS PIC 99.
境界の計算は次のようになります。
IF NUMBER-OF-OCCURS < (LENGTH OF STRUCT-TABLE / LENGTH OF STRUCT-1 (1))
ADD +1 TO NUMBER-OF-OCCURS
ELSE
table is full, preform some error/recovery routine
END-IF
または、レコード定義NUMBER-OF-OCCURS
の外に移動することもできます。TABLE-1