如何防止 COBOL 中的内部表溢出?

Posted

技术标签:

【中文标题】如何防止 COBOL 中的内部表溢出?【英文标题】:How do I prevent internal table overflow in COBOL? 【发布时间】:2016-07-18 09:20:20 【问题描述】:

这可能是一个菜鸟问题,但我仍然很难弄清楚如何在 COBOL 中使用表。

目前我正在编写一个可以被其他程序调用的简单模块。 我的程序必须在内部表中搜索数据,如果没有找到,请添加。

我有这张桌子:

01 TB-1 OCCURS 10 INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

当然,我可以增加 OCCURS 的数量,这样表溢出的可能性就会降低。但是,在测试模块时,我必须处理还有一条不适合表格的记录要添加的情况。

处理此问题的最佳方法是什么?我正在考虑通过返回错误消息来防止 ABEND。

为此,我想我应该定义一个新字段并将其用作计数器。所以基本上,每次我的模块添加记录时,它也会向计数器添加 +1。有点像这样:

IF COUNTER < 10 
     PERFORM ADD-RECORD
ELSE DISPLAY 'INPUT HAS EXCEEDED MAX OF 10 OCCURRENCES'
     GOBACK 
END-IF
.

ADD-RECORD.
    MOVE INPUT-CLIENT-NAME  TO CLIENT-NAME(X1)  IN TB-1.
    MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER(X1) IN TB-1.
    ADD +1 TO COUNTER
    .

这是一个好方法吗?你还有其他建议吗?在此先感谢您的帮助。

【问题讨论】:

我猜你的代码看起来像 SET X1 UP BY 1 MOVE INPUT-CLIENT-NAME TO CLIENT-NAME IN TB-1 (X1)MOVE INPUT-CLIENT-NAME TO CLIENT-NAME IN TB-1 (COUNTER),不是吗? 你是对的,它是第一个。我忘了提到索引,哎呀! 哪个 COBOL 编译器?哪个操作系统? @Lena,提供的答案之一对您有用吗?如果是:请将其标记为答案,如果否:请评论您错过的答案。 【参考方案1】:

该问题错过了您实际使用的编译器的信息,因此您必须检查答案的哪一部分适合您。

最好的选择是:没有最大值(COBOL 2014 功能,您的编译器不太可能支持此功能

01 TB-1 OCCURS DYNAMIC DEPENDING ON COUNTER
                     INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

由于您已经使用了计数器,请检查是否使用了 INDEXED 子句(例如 SEARCH),否则将其删除并仅使用计数器。

无论如何,我个人更喜欢使用计数器进行边界检查,即使在您的范围内(性能稍差但更安全,因为如果出现问题,您的程序将异常终止):

    01 BOUND-ERR.
       03 FILLER         PIC X(26) VALUE 
          'INPUT HAS EXCEEDED MAX OF '.
       03 BOUND-MAX      PIC 9(03).
       03 FILLER         PIC X(11) VALUE 
          'OCCURENCES.'.
    01 TB-1-COUNT        PIC 9(03) VALUE 0.
   *> may not work on your compiler...
    01 TB-1-MAX          AS CONSTANT 10.
   *> ... then try the level 78 extension:
    78 TB-1-MAX          VALUE 10.       
   *> if this doesn't work, too, then use REPLACE for the actual bound:
    REPLACE TB-1-MAX BY 10.
    01 TB-1 OCCURS       1 TO TB-1-MAX DEPENDING ON TB-1-COUNT
                         INDEXED BY X1.
       03 CLIENT-NAME    PIC N(30).
       03 ORDER-NUMBER   PIC 9(06).


        IF TB-1-COUNT = TB-1-MAX
           MOVE TB-1-MAX TO BOUND-MAX
           DISPLAY BOUND-ERR
           MOVE 1 TO RETURN-CODE
           GOBACK 
        END-IF
        ADD +1 TO TB-1-COUNT
        SET X1 UP BY 1
        MOVE INPUT-CLIENT-NAME  TO CLIENT-NAME  (X1) IN TB-1.
        MOVE INPUT-ORDER-NUMBER TO ORDER-NUMBER (X1) IN TB-1.

【讨论】:

快速查看 Lena 的个人资料显示 mainframe 作为标签。我们从之前的问题中得知 Lena 正在使用 Enterprise COBOL。【参考方案2】:

处理此问题的最佳方法是进行解释。最终,您将达到限制并且无法在表中添加新条目。

我的经验是,大多数程序员选择的表大小的上限既合理又比他们预期的要大。例如。当他们被告知永远不会超过 100 个条目时,他们会将表格的大小设为 200 个条目。

如果您使用的是 IBM Enterprise COBOL v5.2 或更高版本,您可以指定...

01 TB-1 OCCURS 1 TO UNBOUNDED 
   DEPENDING NB-ITEMS INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).

77  NB-ITEMS PIC 9(009) COMP VALUE 10.

...在您达到 15,151,516 个条目之前,一切正常。这假定一次出现的大小是 66 字节。 UNBOUNDED 表的限制为 999,999,998 字节; 999999998 / 66 = 15151515(和变化)。

如果您使用的是早期版本的 IBM Enterprise COBOL,您可以为您的表大小选择一个合理的上限,或者您可以冒险进入动态分配存储的领域(通过 LE 可调用服务),这很有用 在某些情况下,但通常是矫枉过正。

【讨论】:

我没用过 V5+,但是你需要一个 OCCURS DEPENDING ON 表,你仍然需要为它分配存储空间。您无需分配最大存储空间,只需分配您想要使用的存储空间即可。如果您需要在飞行中进行扩展,可以这样做,但会涉及到 LE 复制整个表,所以不要经常这样做。 999,999,998 字节是 记录的 限制,但我猜这是文档中的错误(它说“小于”)。 @BillWoodger 根据您的 ODO 注释进行了更正。是的,动态分配将是对 CEEGSTST 的调用和随后的 CEECZST 调用以根据需要调整大小,后者将复制数据。出于礼貌,提供一种释放存储空间的机制也很好,尽管 LE应该在 enclave 终止时处理这个问题。【参考方案3】:

不要使用 magic 数字来固定表格的大小,而是使用 REPLACE 语句。

REPLACE ==TB-1-TABLE-SIZE== BY ==10==.
01 TB-1 OCCURS TB-1-TABLE-SIZE INDEXED X1.
   03 CLIENT-NAME    PIC N(30).
   03 ORDER-NUMBER   PIC 9(06).
IF COUNTER < TB-1-TABLE-SIZE
     PERFORM ADD-RECORD
ELSE DISPLAY 'INPUT HAS EXCEEDED MAX OF ' TB-1-TABLE-SIZE ' OCCURRENCES'
     GOBACK 
END-IF
.

使用REPLACE 可以将任何更改放在一处。

对于 2002,可以使用 CONSTANT

01 TB-1-TABLE-SIZE CONSTANT 20.

【讨论】:

以上是关于如何防止 COBOL 中的内部表溢出?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用淘汰赛绑定表中的内部数组

防止孩子增加父母的宽度[重复]

zset如何解决内部链表查找效率低下

zset如何解决内部链表查找效率低下

zset如何解决内部链表查找效率低下

如何获取在 SQL Server 内部数据库的不同表中重复的列[重复]