我想要信息来操作表格。
我遇到如下一段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)
如何查找值并添加新值?
非常感谢!
我想要信息来操作表格。
我遇到如下一段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)
如何查找值并添加新值?
非常感谢!
如何查找值/如何更新值
首先,您必须查找要更新的记录(行)。这通常通过在表中搜索给定的键值来完成。COBOL 提供了几种方法来做到这一点。我建议您首先查看 COBOL SEARCH
语句。如果STRUCT-1
记录已排序,您可以使用SEARCH ALL
,否则您必须使用SEARCH
或只编写自己的搜索循环。为了使用这些技术中的任何一种,您需要在程序中的某处声明另一个变量以用作STRUCT-1
表中的索引(偏移量)。COBOLINDEXED BY
在子句上提供短语
OCCURS
来声明特定于给定表的索引(请参阅OCCURS)
一旦您将索引设置为STRUCT-1
指向要更新的行,您只需MOVE
将该行中的相应变量的值设置为,例如
将 123.456 移至 VALUE-2 (IDX-1)
其中 IDX-1 是上面提到的索引。请注意,您可以使用整数或索引变量来指定要更新的行号,您不限于使用 INDEX 类型变量。但是,使用 INDEX 变量通常比使用其他类型的变量更有效,特别是在处理程序对表进行大量引用的多维表时。
如何添加新行
首先认识到STRUCT-1
恰好包含 25 行。COBOL 没有动态增加或减少这个数字的机制(我听说这将在下一个 ISO COBOL 标准中实现 - 但不要屏住呼吸等待它)。从技术上讲,所有 25 行都随时可用。然而,一个常见的约定是按顺序将一个表从空到满“增长”,一次一行。要使用此约定,您需要分配一个变量来跟踪上次使用的行号(不要忘记在程序启动时将此变量初始化为零)。在您的示例中,看起来该变量NUMBER-OF-OCCURS
完成了这项工作(我没有提到它,但是您需要这个变量来绑定上面讨论的 SEARCH)。
要“添加”一行,只需增加NUMBER-OF-OCCURS
1。注意不要超过表大小。示例代码可能是:
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 - 你有没有抓住它!
现在回到搜索问题。以下代码示例说明了您可以如何进行:
工作存储声明:
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 来假设该行不在表中。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
子句以在找到标记值时终止搜索:
WHEN VALUE-1 (NUMBER-OF-OCCURS) = LOW-VALUE
CONTINUE
上述假设LOW-VALUE
用于识别未使用的行。您也可以从您的工作存储中删除IDX-1
,MAX-IDX
因为此解决方案不需要它们。
NUMBER-OF-OCCURS
用作索引还意味着您必须更改搜索空行以插入新值的方式。最简单的方法是使用上面的代码搜索表,LOW-VALUE
而不是'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
小于一次,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
定义。
为了在工作存储部分的表中填充和修改数据,您需要使用下标/索引,您可以在工作存储中定义它,然后在程序部分中编写处理代码。在这种情况下,您可以使用 perform..until。
哇...这是一个很长的答案。假设一个名为 II 的数字:
从 1 到 1 执行不同的 II
直到 II > 出现次数
如果 Value-1 (II) = Known-Value-1
Move New-Value-2 to Value-2 (II)
万一
结束执行