我正在尝试使用DISPLAY输出以下行,并在Visual Studio中的Micro Focus COBOL和Tutorialspoint COBOL编译器中获得正确的结果,但是使用IBM的Enterprise COBOL在z / OS Mainframe上运行它时有些奇怪:< / p>
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.
答案 0 :(得分:4)
问题不是那么多&#34;为什么企业COBOL会这样做?&#34;,因为它已被记录,因为&#34;为什么其他两个编译器会生成满足我想要的程序?& #34;,可能也有记录。
这里引用了2014年COBOL标准的草案(实际标准成本为金钱):
C.3.4.1使用索引名称进行订阅
为了便于表格搜索等操作 操纵特定项目,可以使用称为索引的技术。 要使用此技术,程序员会分配一个或多个索引名称 到数据描述条目包含OCCURS子句的项目。一个 与索引名称关联的索引充当下标及其值 对应于项目的出现次数 index-name是关联的。
INDEXED BY短语,用于标识索引名称和 与其表相关联,是OCCURS子句的可选部分。 没有单独的条目来描述与之关联的索引 index-name,因为它的定义完全是面向硬件的。在 运行时索引的内容对应于出现次数 对于索引所在表的特定维度 相关;但是,对应的方式是由 实现者。运行时索引的初始值未定义, 索引应在使用前初始化。一个初始值 index使用带有VARYING短语的PERFORM语句进行分配, 带有ALL短语或SET语句的SEARCH语句。
[...]
index-name可用于仅引用它所在的表 通过INDEXED BY短语关联。
从第二段开始,很明显索引的实现方式取决于编译器的实现者。这意味着索引实际包含的内容以及内部操作的方式因编译器而异,只要结果相同即可。
引用的最后一段表明,根据标准,特定索引只能用于定义该特定索引的表。
在310-CALC-TOTALS
中有一些与此相当的代码:使用其表中的索引获取源数据项,并使用&#34;错误&#34;中的索引。用于存储从不同表中派生的值的表。
这会打破&#34;索引名称可用于仅通过INDEXED BY短语引用与之关联的表。&#34;
因此,您将310-CALC-TOTALS中的代码更改为:使用其表中的索引获取源数据项,并使用目标表上定义的数据名或索引来存储从中导出的值。另一张桌子。
因此,您的代码现在可以正常运行,并且会为每个编译器提供相同的结果。
为什么企业COBOL代码编译,如果标准(以及之前的标准相同)禁止使用?
IBM有语言扩展。事实上两个扩展,适用于您的情况(引自附录A 中的企业COBOL语言参考):
索引和下标...引用具有索引名称的表 为不同的表定义
和
OCCURS ...当没有INDEXED BY时通过索引引用表 短语是指定的
因此,您不会遇到编译错误,因为使用不同表中的索引并在表上未定义索引时使用索引都可以。
那么,当你使用另一个索引时它会做什么?再次从语言参考,这次使用索引名称(索引)订阅
index-name可用于引用任何表。但是,元素 被引用的表的长度和表的长度 index-name与should match相关联。否则,参考 不会是每个表中相同的表元素,你可能会得到 运行时错误。
这正是发生在你身上的事。 OCCURS中项目长度的差异取决于&#34;插入编辑&#34;图片中的符号表示您显示的表格。如果两个表中的项目长度相同,则您没有发现问题。
你为你的表项提供了一个VALUE子句(不必要,因为你总是在输出之前把东西放进去),这就留下了你的&#34;第六个&#34;在列中,前五个列被写为较短的项目。请注意,当编辑完成一个长度并且使用不同的隐式长度完成存储时会导致混淆,甚至会覆盖第二个小数位。
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之前曾与Ideaone和Tuturialspoint讨论过他们使用过时的OpenCOBOL 1.1。 Ideaone提供了积极的反馈,Tutorialspoint,Simon今天再次联系,还没有。
作为一个侧面问题,您似乎正在使用SEARCH ALL
对表进行二进制搜索。对于&#34;小&#34;表,SEARCH ALL提供的广义二进制搜索的机制开销可能超过了机器资源的任何预期节省。如果您要处理大量数据,那么普通SEARCH可能比SEARCH ALL更有效。
小&#34;小&#34;取决于您的数据。在接近100%的时间里,五个可能很小。
比SEARCH和SEARCH更好的性能所有功能都可以通过编码来实现,但请记住,SEARCH和SEARCH ALL都不会出错。
然而,特别是SEARCH ALL,程序员的错误很容易。如果数据不按顺序,则SEARCH ALL将无法正常运行。定义比填充的数据更多的数据也会使表快速不按顺序排列。如果使用SEARCH ALL具有可变数量的项目,请考虑对表格使用OCCURS DEPENDING ON,或者使用&#34; padding&#34;未使用的尾随条目,其值超出可能存在的最大键值。
答案 1 :(得分:2)
我对将VALUE
与OCCURS
混合并将WS重新编码为
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。