4

テーブルを操作するための情報が欲しいです。
以下のような COBOL コードで問題が発生することはほとんどありません。

01 TABLE-1.  
    05 STRUCT-1 OCCURS 25 TIMES.
        10 VALUE-1 PIC AAA.  
        10 VALUE-2 PIC 9(5)V999.  
    05 NUMBER-OF-OCCURS PIC 99.

どのように値を更新しますか? (VALUE-1 がわかっている場合は VALUE-2 を更新します)
値を検索して新しい値を追加するにはどうすればよいですか?
どうもありがとう!

4

3 に答える 3

8

値の検索方法/値の更新方法

まず、更新するレコード (行) を検索する必要があります。これは通常、特定のキー値をテーブルで検索することによって行われます。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-OCCURSPIC 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-NOtrueに設定して、行がテーブルにないと仮定することから始めます。
  • 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-1LOW-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-1STRUCT-1テーブルだけでなく、も含まれNUMBER-OF-OCCURSます。の長さは のNUMBER-OF-OCCURS1 回の出現に満たない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

于 2010-03-08T20:37:30.590 に答える
1

作業領域セクションのテーブルにデータを入力して修正するには、作業領域で定義できる添え字/インデックスを使用する必要があり、手続き部に処理コードを記述します。この場合、perform..until を使用できます。

于 2010-03-08T19:46:19.340 に答える
1

うわぁ…長い答えでした。II という名前の数値を想定します。

変化するIIを1つずつ実行する

II > 発生回数まで

値 1 (II) = 既知の値 1 の場合

 Move New-Value-2 to Value-2 (II)

End-If

エンドパフォーム

于 2010-06-08T09:12:49.913 に答える