操纵COBOL数据结构

4 cobol

我想知道操纵表的信息.
我遇到一些像下面这样的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.
Run Code Online (Sandbox Code Playgroud)

你如何更新价值观?(当您知道VALUE-1时更新VALUE-2)
如何查找值并添加新值?
非常感谢!

Nea*_*alB 8

如何查找值/如何更新值

首先,您必须查找要更新的记录(行).这通常通过在表中搜索给定的键值来完成.COBOL提供了两种方法来实现这一点.我建议您首先查看COBOL SEARCH 语句.如果STRUCT-1记录已排序,您可以使用SEARCH ALL,否则您必须使用SEARCH或只编写自己的搜索循环.为了使用这些技术中的任何一种,您需要在程序中的某处声明另一个变量,以用作表中的索引(偏移量)STRUCT-1.COBOL INDEXED BYOCCURS子句上提供了一个短语 来声明特定于给定表的索引(参见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
Run Code Online (Sandbox Code Playgroud)

上面的代码避免明确使用发生的次数,在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.
Run Code Online (Sandbox Code Playgroud)

添加了什么:

  • FOUND-IND用于指示是否找到了您要查找的行.88级给出了设定/测试的特定值
  • MAX-IDX用于设置搜索的上限.您可以NUMBER-OF-OCCURS在上限测试中使用,但这会强制每次测试的数据类型转换效率不高
  • IDX-1用作表中的索引(偏移量)STRUCT-1.

就个人而言,我会宣布NUMBER-OF-OCCURS,PIC S9(4) BINARY但你所拥有的将会奏效.

假设STRUCT-1未排序并NUMBER-OF-OCCURS表示当前活动行数,STRUCT-1这是一个示例,说明SEARCH在查找值'ABC'时如何编码:

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
Run Code Online (Sandbox Code Playgroud)

这个怎么运作:

  • 首先假设行不在表中,设置FOUND-NO为true.
  • 第一个IF确保STRUCT-1在开始搜索之前至少有一个活动行(将INDEX设置为零是错误的 - 所以你需要防范它).
  • SEARCH终止时,第一SEARCH WHEN条是在线北京.这就是为什么CONTINUE当我们用完行搜索时,可以使用'什么都不'的动词.另一个终止条件(找到您要查找的值)是唯一FOUND-YES可以设置的地方.
  • SEARCH完成,试验成功或失败,然后采取相应的行动.

一些练习供您研究:

  • 为什么我不必AT ENDSEARCH声明中编写一个条款?
  • 为什么我不必VARYINGSEARCH声明中编写一个条款?
  • 为什么我WHERE按照我的顺序编写了这些条款?

希望这能让你开始走正确的道路.

编辑

在评论中回答您的问题:我们可以使用NUMBER-OF-OCCURS作为搜索索引.答案是肯定的,但您需要实施一些不同的规则.当NUMBER-OF-OCCURS 用作索引时,您不能再使用它来跟踪当前包含有效数据的行数.这意味着您需要另一种机制来识别未使用的行STRUCT-1.这可以通过初始化未使用的行来实现,这些行具有LOW-VALUE您永远不会真正想要放入表中的sentinal值(例如).将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 
Run Code Online (Sandbox Code Playgroud)

如果STRUCT-1您要搜索的值(即.ABC)不在表中,上面将搜索每一行.作为优化,您可以添加第二个WHEN子句以在找到sentinal值时终止搜索:

WHEN VALUE-1 (NUMBER-OF-OCCURS) = LOW-VALUE
   CONTINUE
Run Code Online (Sandbox Code Playgroud)

以上假设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. 
Run Code Online (Sandbox Code Playgroud)

并且边界计算将变为:

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 
Run Code Online (Sandbox Code Playgroud)

或者你可以NUMBER-OF-OCCURS离开TABLE-1记录定义.