Cobol 参考其他结构中的通用结构

Cobol 参考其他结构中的通用结构,cobol,Cobol,我需要定义copybook,描述我的文件格式。在我的文件中,有不同格式的行,但所有行的第一部分是相同的。如何仅定义一次公共结构并从其他结构中引用它? 我需要这样的东西: 01 Header. 02 Id PIC X(2). 02 Name PIC X(10). 01 LineA. 02 Header. "how can I reference the above Header, to not define it in every LineA, Line B?** 02 Some

我需要定义copybook,描述我的文件格式。在我的文件中,有不同格式的行,但所有行的第一部分是相同的。如何仅定义一次公共结构并从其他结构中引用它? 我需要这样的东西:

01 Header.
  02 Id PIC X(2).
  02 Name PIC X(10).
01 LineA.
  02 Header.  "how can I reference the above Header, to not define it in every LineA, Line B?**
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineA.
  02 Header.
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
  ...

谢谢。

您可以使用IN关键字(或其同义词OF)来指代不同结构中具有相同名称的结构成员

    05  FORMAT-CODE           PIC X(1).
        88  FORMAT-IS-CUSTOMER    VALUE "C".
        88  FORMAT-IS-EMPLOYEE    VALUE "E".
    05  CUSTOMER-LAYOUT.
        07  FIRST-NAME        PIC X(10).
        07  STREET-ADDRESS    PIC X(30).
        07  CUSTOMER-ID       PIC X(7).
* * * 
    05  EMPLOYEE-LAYOUT       REDEFINES CUSTOMER-LAYOUT.
        07  FIRST-NAME        PIC X(10).
        07  STREET-ADDRESS    PIC X(30).
        07  EMPLOYEE-ID       PIC 9(5).
* * *
IF FORMAT-IS-CUSTOMER
    MOVE INPUT-FIRST-NAME TO FIRST-NAME IN CUSTOMER-LAYOUT
* * *
COBOL对此的术语是“资格”

在上面的片段中,您可以将名字和街道地址定义放在副本组中,并将其复制两次到您的程序中

您还可以使用COPY语句的替换短语为成员生成唯一的名称。(但我还没有见过这种语言功能经常使用。)

如果你对这个话题的兴趣只是好奇,那么任何一种方式都适合你。但是,如果您正在编写生产代码,您的经理和编码标准将指示如何处理此问题并建立命名标准。请记住,许多COBOL商店依赖于数据字典工具或与DBMS的集成来生成源代码记录布局,因此您根本不必编写自己的数据分区代码

在您的后续行动的提示下,我记得以下方法更像我过去的做法。利用重定义和填充:

01  ALL-LAYOUTS.
    03  COMMON-LAYOUT.
        05  HEADER.
            07  ID                   PIC X(02).
            07  NAME                 PIC X(10).
            07  FORMAT-CODE          PIC X(1).
                88  FORMAT-IS-A          VALUE "A".
                88  FORMAT-IS-B          VALUE "B".
        05      FILLER               PIC X(67).
    03  LINE-A-LAYOUT                REDEFINES COMMON-LAYOUT.
        05      FILLER               PIC X(13).
        05  LINE-A-SOME-FIELD-1      PIC X(01).
        05  LINE-A-SOME-FIELD-2      PIC X(01).
        05      FILLER               PIC X(66).
    03  LINE-B-LAYOUT                REDEFINES COMMON-LAYOUT.
        05      FILLER               PIC X(13).
        05  LINE-B-SOMETHING-ELSE    PIC X(40).
        05      FILLER               PIC X(27).

* * *

    MOVE "A" TO FORMAT-CODE
    MOVE INPUT-ID TO ID
    MOVE INPUT-NAME TO NAME
    MOVE INPUT-SOME-FIELD-1 TO LINE-A-SOME-FIELD-1
    MOVE INPUT-SOME-FIELD-2 TO LINE-A-SOME-FIELD-2

您需要某种类型的记录类型指示符(FORMAT-CODE),这样当您从存储器中读回记录时,您将知道哪种格式是适用的。

您可以使用IN关键字(或其同义词of)来引用不同结构中具有相同名称的结构成员

    05  FORMAT-CODE           PIC X(1).
        88  FORMAT-IS-CUSTOMER    VALUE "C".
        88  FORMAT-IS-EMPLOYEE    VALUE "E".
    05  CUSTOMER-LAYOUT.
        07  FIRST-NAME        PIC X(10).
        07  STREET-ADDRESS    PIC X(30).
        07  CUSTOMER-ID       PIC X(7).
* * * 
    05  EMPLOYEE-LAYOUT       REDEFINES CUSTOMER-LAYOUT.
        07  FIRST-NAME        PIC X(10).
        07  STREET-ADDRESS    PIC X(30).
        07  EMPLOYEE-ID       PIC 9(5).
* * *
IF FORMAT-IS-CUSTOMER
    MOVE INPUT-FIRST-NAME TO FIRST-NAME IN CUSTOMER-LAYOUT
* * *
COBOL对此的术语是“资格”

在上面的片段中,您可以将名字和街道地址定义放在副本组中,并将其复制两次到您的程序中

您还可以使用COPY语句的替换短语为成员生成唯一的名称。(但我还没有见过这种语言功能经常使用。)

如果你对这个话题的兴趣只是好奇,那么任何一种方式都适合你。但是,如果您正在编写生产代码,您的经理和编码标准将指示如何处理此问题并建立命名标准。请记住,许多COBOL商店依赖于数据字典工具或与DBMS的集成来生成源代码记录布局,因此您根本不必编写自己的数据分区代码

在您的后续行动的提示下,我记得以下方法更像我过去的做法。利用重定义和填充:

01  ALL-LAYOUTS.
    03  COMMON-LAYOUT.
        05  HEADER.
            07  ID                   PIC X(02).
            07  NAME                 PIC X(10).
            07  FORMAT-CODE          PIC X(1).
                88  FORMAT-IS-A          VALUE "A".
                88  FORMAT-IS-B          VALUE "B".
        05      FILLER               PIC X(67).
    03  LINE-A-LAYOUT                REDEFINES COMMON-LAYOUT.
        05      FILLER               PIC X(13).
        05  LINE-A-SOME-FIELD-1      PIC X(01).
        05  LINE-A-SOME-FIELD-2      PIC X(01).
        05      FILLER               PIC X(66).
    03  LINE-B-LAYOUT                REDEFINES COMMON-LAYOUT.
        05      FILLER               PIC X(13).
        05  LINE-B-SOMETHING-ELSE    PIC X(40).
        05      FILLER               PIC X(27).

* * *

    MOVE "A" TO FORMAT-CODE
    MOVE INPUT-ID TO ID
    MOVE INPUT-NAME TO NAME
    MOVE INPUT-SOME-FIELD-1 TO LINE-A-SOME-FIELD-1
    MOVE INPUT-SOME-FIELD-2 TO LINE-A-SOME-FIELD-2

您需要某种类型的记录类型指示符(FORMAT-CODE),这样当您从存储器中读回记录时,您将知道哪种格式适用。

我想您可能正在寻找COBOL重新定义。这允许使用相同的数据结构 在运行时可以选择不同的内部结构

例如:

  01 TRANSACTION.
     05 TRANS-SQNBR              PIC 9(5).
     05 TRANS-TIMESTAMP          PIC X(26).
     05 TRANS-TYPE               PIC X(2).
        88 TRANS-PO              VALUE '01'.
        88 TRANS-MO              VALUE '02'.
     05 TRANS-DATA.
        10                       PIC X(220).
     05 PO-TRANS REDEFINES TRANS-DATA.
        10 PURCHASE-ORDER-ID     PIC X(10).
        10 CLIENT-ID             PIC X(7).
        10 SHIP-BY-DATE          PIC X(10).
        10 CLIENT-REF-ID         PIC X(30).
        10 .... more Purchase Order data
     05 MO-TRANS REDEFINES TRANS-DATA.
        10 CLIENT-NAME           PIC X(45).
        10 SHIP-ADDRESS-1        PIC X(40).
        10 SHIP-ADDRESS-2        PIC X(40).
        10 SHIP-CITY             PIC X(30).
        10 SHIP-POST-CODE        PIC X(6).
        10 .... More Mail Order Data  
 EVALUATE TRUE
    WHEN TRANS-PO
       MOVE PURCHASE-ORDER-ID TO whatever...
       ...
    WHEN TRANS-MO
       MOVE CLIENT-NAME TO whatever...
    WHEN OTHER
       PERFORM UNKNOWN-RECORD-TYPE-ERROR
 END-EVALUATE 
上面的记录布局描述了某种类型的事务。前几个字段很常见 适用于所有类型的事务(TRANS-SQNBR、TRANS-TIMESTAMP和TRANS-TYPE)。反式 有一个关联的88级别,用于确定记录的其余部分将如何保存 解释。当TRANS-TYPE的值为“01”(TRANS-PO为真)时,PO-TRANS的记录布局 将描述记录的其余部分。当TRANS-TYPE为“02”(TRANS-MO为真)时,MO-TRANS记录布局 应该使用

TRANS-DATA、PO-TRANS和MO-TRANS记录布局相互排斥,因为它们 都将占用相同的物理内存。也就是说,上述记录中的总记录长度 例如,公共数据项长度(5+26+2=33)加上 TARNS-DATA(220,后续重新定义的数据项)。这是一个完整的记录 33+220的长度=253。无法重新定义TRANS-DATA的记录长度 超过传输数据的长度(可能较短,但不能较长)

请注意,TRANS-DATA有一个未命名的从属10级别。有时这被称为填充,但是 不需要指定名称。本项的目的是定义管道的长度 备用记录定义中的最长区域。基本上,它只是一个虚拟的占位符

PO-TRANS重新定义分配用于保存TRANS-DATA的内存,使其具有完整的 不同的解释。类似地,MO-TRANS重新定义了TRANS-DATA

TRANS-TYPE下的88个级别名称实际上并不需要,但提供了文档和 一组定义的值,用于在备选记录布局中进行选择

要使用此记录布局,您需要填充它(可能通过READ语句)。 TRANS-SQNBR、TRANS-TIMESTAMP和TRANS-TYPE将直接在这些目录下提供 名字。为了解释记录的其余部分,您需要测试TRANS-TYPE和 然后根据需要使用其他数据名称。例如:

  01 TRANSACTION.
     05 TRANS-SQNBR              PIC 9(5).
     05 TRANS-TIMESTAMP          PIC X(26).
     05 TRANS-TYPE               PIC X(2).
        88 TRANS-PO              VALUE '01'.
        88 TRANS-MO              VALUE '02'.
     05 TRANS-DATA.
        10                       PIC X(220).
     05 PO-TRANS REDEFINES TRANS-DATA.
        10 PURCHASE-ORDER-ID     PIC X(10).
        10 CLIENT-ID             PIC X(7).
        10 SHIP-BY-DATE          PIC X(10).
        10 CLIENT-REF-ID         PIC X(30).
        10 .... more Purchase Order data
     05 MO-TRANS REDEFINES TRANS-DATA.
        10 CLIENT-NAME           PIC X(45).
        10 SHIP-ADDRESS-1        PIC X(40).
        10 SHIP-ADDRESS-2        PIC X(40).
        10 SHIP-CITY             PIC X(30).
        10 SHIP-POST-CODE        PIC X(6).
        10 .... More Mail Order Data  
 EVALUATE TRUE
    WHEN TRANS-PO
       MOVE PURCHASE-ORDER-ID TO whatever...
       ...
    WHEN TRANS-MO
       MOVE CLIENT-NAME TO whatever...
    WHEN OTHER
       PERFORM UNKNOWN-RECORD-TYPE-ERROR
 END-EVALUATE 
如上图所示,当使用多个记录布局时,最好使用 在输入错误的情况下,一个错误捕获所有信息,因此出现上面所示的未知记录类型错误

评论回复

您问题中的记录结构有点问题,因为
02标题。
没有PICTURE子句或从属数据项 所以这不是一个有效的声明。 如果你有这样的事情:

01 Generic-Header.
  02 Id PIC X(2).
  02 Name PIC X(10).
01 LineA.
  02 Header     PIC X(12).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineB.
  02 Header     PIC X(12).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
你可以这样做:

MOVE Header OF LineA to Generic-Header
  02 Id PIC X(2).
  02 Name PIC X(10).
01 LineA.
  COPY GENHDR.
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineB.
  COPY GENHDR.
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineA.
  02 Id PIC X(2).
  02 Name PIC X(10).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineB.
  02 Id PIC X(2).
  02 Name PIC X(10).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
现在,您可以从通用标题中引用
Id
Name
。然而,你只有一个 通用标题记录,如果您需要同时使用
LineA
LineB
通用标题
可以容纳一个或另一个标题,但不能同时容纳两个标题!如

MOVE Header of LineA to Generic-Header
IF Id = Current-Id  <== This is the Id from LineA
   work with LineA
END-IF

MOVE Header of LineB to Generic-Header
IF Id = Current-Id  <== This is the Id from LineB
   work with LineB
END-IF
您的主程序将在一个单独的文件中,我们称之为MYPROG。该文件的一部分看起来 比如:

MOVE Header OF LineA to Generic-Header
  02 Id PIC X(2).
  02 Name PIC X(10).
01 LineA.
  COPY GENHDR.
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineB.
  COPY GENHDR.
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineA.
  02 Id PIC X(2).
  02 Name PIC X(10).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
01 LineB.
  02 Id PIC X(2).
  02 Name PIC X(10).
  02 SomeField1 PIC X.
  02 SomeField2 PIC X.
编译MYPROG时,会插入GENHDR的副本