1

我正在尝试使用 DISPLAY 输出以下行,并且在 Visual Studio 和 Tutorialspoint COBOL 编译器中的 Micro Focus COBOL 中获得了正确的结果,但是在使用 IBM 的 Enterprise COBOL 在 z/OS 大型机上运行它时有些奇怪:

01 W05-OUTPUT-ROW.
   05 W05-OFFICE-NAME PIC X(13).
   05 W05-BENEFIT-ROW OCCURS 5 TIMES.
       10 PIC X(2) VALUE SPACES.
       10 W05-B-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.
   05 PIC X(2) VALUE SPACES.
   05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.

在 Enterprise COBOL 中显示空格被忽略,并且添加了一个额外的零填充列,即使 PERFORM VARYING 和 DISPLAY 代码在两个版本中完全相同:

PERFORM VARYING W02-O-IDX FROM 1 BY 1
   UNTIL W02-O-IDX > W12-OFFICE-COUNT

   MOVE W02-OFFICE-NAME(W02-O-IDX) TO W05-OFFICE-NAME

   PERFORM 310-CALC-TOTALS VARYING W02-B-IDX FROM 1 BY 1
       UNTIL W02-B-IDX > W13-BENEFIT-COUNT

   MOVE W02-O-TOTAL(W02-O-IDX) TO W05-OFFICE-TOTAL
   DISPLAY W05-OUTPUT-ROW
END-PERFORM

W13-BENEFIT-COUNT 是 5 并且在程序中永远不会改变,所以第 6 列对我来说是个谜。

正确的输出:

正确的输出

奇怪的输出:

奇怪的输出

编辑:根据要求,这里是 W02-OFFICE-TABLE:

01 W02-OFFICE-TABLE.
    05 W02-OFFICE-ROW OCCURS 11 TIMES
    ASCENDING KEY IS W02-OFFICE-NAME
    INDEXED BY W02-O-IDX.
        10 W02-OFFICE-CODE PIC X(6).
        10 W02-OFFICE-NAME PIC X(13).
        10 W02-BENEFIT-ROW OCCURS 5 TIMES
        INDEXED BY W02-B-IDX.
            15 W02-B-CODE PIC 9(1).
            15 W02-B-TOTAL PIC 9(5)V99 VALUE ZERO.
        10 W02-O-TOTAL PIC 9(5)V99 VALUE ZERO.

并且 W12-OFFICE-COUNT 始终为 11,永不改变:

01 W12-OFFICE-COUNT PIC 99 VALUE 11.
4

2 回答 2

4

问题不在于“为什么 Enterprise COBOL 这样做?”,因为它已记录在案,因为“为什么其他两个编译器生成执行我想要的程序?”,这可能也记录在案。

以下是 2014 年 COBOL 标准草案的引述(实际标准需要花钱):

C.3.4.1 使用索引名称下标

为了方便诸如表搜索和操作特定项目之类的操作,可以使用一种称为索引的技术。为了使用这种技术,程序员将一个或多个索引名称分配给其数据描述条目包含 OCCURS 子句的项目。与 index-name 关联的索引充当下标,其值对应于与 index-name 关联的项目的出现次数。

INDEXED BY 短语是 OCCURS 子句的可选部分,通过该短语标识索引名称并将其与其表相关联。没有单独的条目来描述与 index-name 关联的索引,因为它的定义完全是面向硬件的。在运行时,索引的内容对应于与索引关联的表的特定维度的出现次数;但是,对应的方式由实现者决定。索引在运行时的初始值是未定义的,使用前需要对索引进行初始化。索引的初始值由带有 VARYING 短语的 PERFORM 语句、带有 ALL 短语的 SEARCH 语句或 SET 语句分配。

[...]

索引名称可以用于仅引用通过 INDEXED BY 短语与之关联的表。

从第二段可以看出,如何实现索引取决于编译器的实现者。这意味着索引实际包含的内容以及它在内部的操作方式可能因编译器而异,只要结果相同即可。

引用的最后一段表明,根据标准,特定索引只能用于定义该特定索引的表。

您有一些与此等效的代码310-CALC-TOTALS:使用其表中的索引获取源数据项,并使用“错误”表中的该索引来存储从该索引派生的值在不同的表中。

这打破了“一个索引名称可用于仅引用通过 INDEXED BY 短语与之关联的表”。

因此,您将 310-CALC-TOTALS 中的代码更改为:使用其表中的索引获取源数据项,并使用在目标表上定义的数据名称或索引来存储从不同表中派生的值.

所以你的代码现在可以工作了,并且每个编译器都会给你相同的结果。

如果标准(与以前的标准相同)禁止使用企业 COBOL 代码,为什么还要编译?

IBM 有一个语言扩展。实际上有两个扩展,适用于您的案例(引用自附录 A中的Enterprise COBOL 语言参考):

索引和下标...引用具有为不同表定义的索引名称的表

OCCURS ... 在未指定 INDEXED BY 短语时通过索引引用表

因此,您不会收到编译错误,因为使用来自不同表的索引和在表上未定义索引时使用索引都可以。

那么,当您使用另一个索引时,它会做什么?再次来自语言参考,这次是使用索引名称进行下标(索引)

索引名称可用于引用任何表。但是,被引用的表的元素长度和与索引名称关联的表的元素长度应该匹配。否则,引用将不会指向每个表中的相同表元素,并且您可能会遇到运行时错误。

这正是发生在你身上的事情。OCCURS 中项目的长度差异取决于 PICture 中用于显示的表格的“插入编辑”符号。如果两个表中的项目长度相同,您就不会注意到问题。

您为表项提供了一个 VALUE 子句(不必要,因为您总是在 are 输出之前将某些内容放入其中),这留下了您的“第六”列,前面的五个列被写为较短的项。请注意,当编辑完成一个长度并使用不同的隐式长度完成存储时引起的混乱,您甚至会覆盖第二个小数位。

IBM 的 INDEXED BY 实现意味着被索引的项目的长度是固有的。因此,当引用的字段实际上是不同的长度时,会出现意想不到的结果。

其他两个编译器呢?您需要查看他们的文档以确定正在发生的事情(就像索引由条目号表示(如此简单的 1、2、3 等)一样简单,并且允许索引引用另一个表就足够了)。应该有两个扩展:允许在未定义该索引的表上使用索引;允许在未定义索引的表上使用索引。这两者在逻辑上成对出现,并且两者都只需要具体(第一个会这样做),因为它们是专门针对标准的。

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,西蒙今天再次联系了谁,还没有。

作为一个附带问题,您似乎正在使用SEARCH ALL对表进行二进制搜索。对于“小”表,SEARCH ALL 提供的广义二进制搜索机制的开销可能超过任何预期的机器资源节省。如果您要处理大量数据,那么简单的 SEARCH 可能会比 SEARCH ALL 更有效。

“小”有多小取决于您的数据。5 很可能在接近 100% 的情况下很小。

通过编码可以实现比 SEARCH 和 SEARCH ALL 功能更好的性能,但请记住,SEARCH 和 SEARCH ALL 不会出错。

然而,特别是使用 SEARCH ALL,程序员很容易出错。如果数据乱序,SEARCH ALL 将无法正确运行。定义的数据多于填充的数据也会使表格快速失序。如果将 SEARCH ALL 与可变数量的项目一起使用,请考虑对表使用 OCCURS DEPENDING ON,或者使用超出可能存在的最大键值的值“填充”未使用的尾随条目。

于 2016-03-28T00:14:44.107 回答
2

我会非常犹豫是否将 WS 混合VALUEOCCURS重新编码为

01 W05-OUTPUT-ROW.
   05 W05-OFFICE-NAME  PIC X(13).
   05 W05-BENEFITS     PIC X(55) VALUE SPACES.
   05 FILLER REDEFINES W05-BENEFITS.
     07 W05-BENEFIT-ROW OCCURS 5 TIMES.
       10 FILLER       PIC X(02).
       10 W05-B-TOTAL  PIC ZZ,ZZ9.99.
   05 FILLER           PIC X(02) VALUE SPACES.
   05 W05-OFFICE-TOTAL PIC ZZ,ZZ9.99 VALUE ZEROS.

也许它与缺少的字段名有关?

啊! 邪恶INDEXED的。我会让两个 ***-IDX 变量都变成简单的 99。

于 2016-03-27T20:30:56.413 回答