問題は、「なぜ Enterprise COBOL がそれを行うのか?」ということではなく、「他の 2 つのコンパイラーが、私が望むことを行うプログラムを生成するのはなぜですか?」ということです。
以下は、2014 COBOL 標準となったものの草案からの引用です (実際の標準には費用がかかります)。
C.3.4.1 索引名を使用した添え字付け
テーブルの検索や特定の項目の操作などの操作を容易にするために、索引付けと呼ばれる手法が利用できます。この手法を使用するには、プログラマは、データ記述エントリに OCCURS 句が含まれる項目に 1 つまたは複数の指標名を割り当てます。索引名に関連付けられた索引は添字として機能し、その値は索引名が関連付けられた項目の出現番号に対応します。
指標名を識別し、そのテーブルに関連付ける INDEXED BY 句は、OCCURS 句のオプションの部分です。index-name の定義は完全にハードウェア指向であるため、 index-name に関連付けられたインデックスを記述する個別のエントリはありません。実行時のインデックスの内容は、インデックスが関連付けられているテーブルの特定のディメンションのオカレンス番号に対応します。ただし、対応の方法は実装者によって決定されます。実行時のインデックスの初期値は未定義であり、インデックスは使用前に初期化されます。指標の初期値は、PERFORM文のVARYING指定、SEARCH文のALL指定、またはSET文で代入します。
[...]
指標名は、INDEXED BY 句を介して関連付けられているテーブルのみを参照するために使用できます。
2 番目の段落から、インデックスがどのように実装されるかは、コンパイラの実装者次第であることは明らかです。つまり、結果が同じである限り、インデックスに実際に含まれるものと内部で操作される方法は、コンパイラごとに異なる可能性があります。
引用された最後の段落は、標準により、特定のインデックスは、その特定のインデックスを定義するテーブルにのみ使用できることを示しています。
にこれと同等のコードがあり310-CALC-TOTALS
ます。テーブルのインデックスを使用してソース データ項目を取得し、「間違った」テーブルからそのインデックスを使用して、それから派生した値を別のテーブルに格納します。
これは、「インデックス名は、INDEXED BY 句を介して関連付けられているテーブルのみを参照するために使用できます」を破ります。
そのため、310-CALC-TOTALS のコードを次のように変更しました: テーブルのインデックスを使用してソース データ項目を取得し、宛先テーブルで定義されたデータ名またはインデックスを使用して、そこから派生した値を別のテーブルに格納します。 .
したがって、コードが機能するようになり、各コンパイラで同じ結果が得られます。
標準 (これは以前の標準でも同じでした) が使用を禁止しているのに、なぜ Enterprise COBOL コードがコンパイルされたのですか?
IBM には言語拡張機能があります。実際、あなたのケースに適用できる 2 つの拡張機能 (付録 AのEnterprise COBOL 言語リファレンスから引用):
索引付けと添字付け ... 別の表に定義された索引名を持つ表の参照
と
OCCURS ... INDEXED BY句を指定しない場合の索引付けによる表の参照
したがって、別のテーブルのインデックスを使用することも、テーブルにインデックスが定義されていないときにインデックスを使用することもできるため、コンパイル エラーは発生しません。
では、別のインデックスを使用するとどうなるでしょうか? 再び言語リファレンスから、今回は添字名を使用した添字 (索引付け)について
索引名は、任意の表を参照するために使用できます。ただし、参照される表と指標名が関連付けられている表の要素の長さは一致している必要があります。そうしないと、各テーブルの同じテーブル要素が参照されず、実行時エラーが発生する可能性があります。
それはまさにあなたに起こったことです。OCCURS 内の項目の長さの違いは、表示元のテーブルの PICture 内の「挿入編集」記号にまで及びます。2 つのテーブルのアイテムが同じ長さである場合、問題に気付かなかったでしょう。
テーブル項目に VALUE 句を指定しました (出力の前に常に何かを入れるため、不要です)。編集が 1 つの長さで行われ、格納が別の暗黙的な長さで行われた場合に生じる混乱に注意してください。小数点以下第 2 位を上書きすることさえあります。
IBM の INDEXED BY の実装は、索引付けされる項目の長さが固有であることを意味します。したがって、参照されるフィールドが実際には異なる長さである場合、予期しない結果になります。
他の 2 つのコンパイラはどうですか? 何が起こっているのかを確認するには、ドキュメントを参照する必要があります (インデックスがエントリ番号で表されるのと同じくらい単純なもの (非常に単純な 1、2、3 など)、およびインデックスが別のインデックスを参照できるようにすること)。テーブルで十分です)。2 つの拡張が必要です。インデックスを定義していないテーブルでインデックスを使用できるようにするため。インデックスが定義されていないテーブルでインデックスを使用できるようにします。この 2 つは論理的にはペアであり、特に標準に反しているため、どちらも具体的である必要があります (最初のものはそうでなければそうします)。
Micro Focus には言語拡張機能があり、あるテーブルのインデックスを使用して別のテーブルのデータを参照できます。これには、インデックスが定義されていないテーブルの参照が含まれることは明示されていませんが、明らかにそうです。
Tutorialspoint は OpenCOBOL 1.1 を使用します。OpenCOBOL は GnuCOBOL になりました。GnuCOBOL 1.1 は現在のリリースであり、OpenCOBOL 1.1 とは異なり、より最新です。GnuCOBOL 2.0 が間もなく登場します。私は SourceForge.Net の GnuCOBOL のディスカッション エリアに貢献し、そこで問題を提起しました。GnuCOBOL プロジェクトの Simon Sobisch 氏は以前、旧式の OpenCOBOL 1.1 の使用について Ideaone と Tuturialspoint にアプローチしました。Ideaone は肯定的なフィードバックを提供してくれましたが、Tutorialspoint には、Simon が今日再び連絡を取りましたが、まだ何もありません。
副次的な問題として、SEARCH ALL
テーブルのバイナリ検索を使用しているようです。「小さい」テーブルの場合、SEARCH ALL によって提供される一般化されたバイナリ検索のメカニズムのオーバーヘッドが、マシン リソースの予想される節約を上回る可能性があります。大量のデータを処理する場合、SEARCH ALL よりも単純な SEARCH の方が効率的である可能性があります。
どの程度「小さい」かは、データによって異なります。5 は 100% 近く小さい可能性があります。
SEARCH および SEARCH ALL 機能よりも優れたパフォーマンスは、コーディングによって実現できますが、SEARCH および SEARCH ALL は間違いを犯さないことに注意してください。
しかし、特に SEARCH ALL はプログラマーのミスが起きやすいです。データの順序がずれていると、SEARCH ALL が正しく動作しません。入力されているよりも多くのデータを定義すると、テーブルもすぐに順不同になります。可変数のアイテムで SEARCH ALL を使用する場合は、テーブルに OCCURS DEPENDING ON を使用するか、未使用の後続エントリに存在可能な最大キー値を超える値を「埋め込む」ことを検討してください。