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表中的索引(偏移量)。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-OCCURS1。注意不要超过表大小。示例代码可能是:

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-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-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-1MAX-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定义。

于 2010-03-08T20:37:30.590 回答
1

为了在工作存储部分的表中填充和修改数据,您需要使用下标/索引,您可以在工作存储中定义它,然后在程序部分中编写处理代码。在这种情况下,您可以使用 perform..until。

于 2010-03-08T19:46:19.340 回答
1

哇...这是一个很长的答案。假设一个名为 II 的数字:

从 1 到 1 执行不同的 II

直到 II > 出现次数

如果 Value-1 (II) = Known-Value-1

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

万一

结束执行

于 2010-06-08T09:12:49.913 回答