如何使用两种不同类型的记录处理顺序文件?

问题描述 投票:1回答:2

对于作为COBOL课程一部分的作业,我的输入文件是一个名为BRANCHTOT.SEQ的顺序文件,它有两种类型的记录:

第一个是我称之为标题记录,它表明文件中的记录总量(不包括标题记录本身)。这只是一条记录。

如果这是文件中唯一的记录,我将其定义如下:

01 header-record.
   03 record-count  PIC 9(6).
   03 FILLER        PIC X(13). 

第二种类型的记录是我必须阅读和处理输出的记录。其结构如下:

01 sales-record.
   03 branch-nr    PIC X(5).
   03 office-nr    PIC 9(2).
   03 count        PIC 9(5).
   03 sum          PIC 9(5)V99.
  1. 如何在我的文件部分和工作存储部分中定义BRANCHTOT.SEQ文件?我是否使用重新定义?

我习惯使用一种记录类型的文件。

  1. 如何在不阻止标题记录的情况下阅读和处理销售记录类型的记录?

分配比我在这里描述的要复杂得多,但是对于这部分问题,我的程序必须读取并处理销售记录记录并打印它已读取的这些记录的总量,并将其与金额进行比较在标题记录中列出。如果两者不匹配,我需要在输出列表中有一个语句来记录这个错误。

  1. 我该怎么做?
cobol
2个回答
2
投票

您可以在单个FD下定义两个记录,您可以完全按照您的显示进行定义。这将为您提供隐含的REDEFINES。

在SELECT语句中对文件使用FILE STATUS(always)。始终检查文件状态字段是否获得预期值。使用88条件名称值“10”来标识文件结尾。不要使用AT END / NOT AT END

请注意,您无法完美地执行此练习,因为文件尚未正确定义。没有迹象表明标题记录或数据记录。唯一的迹象是“标头是第一个,其余都是数据”。这可能看起来很好,但是当有人腌制最初编写文件的程序时,它会变成斯洛克,并且不会给你带任何标题或两个或更多的标题。

如果文件具有结构,则结构应该在数据内,因为它可以被检查。处理坏文件就好像它是一个好文件可能非常昂贵。而且很尴尬。

您还需要知道文件是否允许“空”。由于它具有标题记录,因此“空”文件应包含具有零数据记录计数的标题记录。您的情况可能有所不同,因为文件未设计。

在初始处理中(在输入文件为OPENed之后),您将读取第一条记录。如果是这样,处理“空文件”。检查它是一个标题。存储记录计数。

然后,您阅读下一条记录。你检查它不是标题。

然后处理您的数据,记住您有第一个可用的数据记录。

Loop until end-of-input
  process record
  read next record
End-Loop

在文件结束时(循环结束时),您可以检查标题上的记录数(从存储的值)到您读取的数据记录数(在记录处理过程中计算)。

一旦你有了你的程序,你就有了一个“模型”来建立其他程序。您只需将常规“这是我处理文件的方式”更正一次,然后将其用作下一个文件处理程序的起点。下一个程序会更复杂,所以最终会得到另一个模型。

经过一段时间,你将拥有大约五个模型,每个模型都基于一个简单任务的工作代码。

我反对使用AT END / NOT AT END来读取文件有几个原因:

复杂性和可理解性

a-pargraph-for-SO-formatting.
   PERFORM priming-read
   PERFORM 
     UNTIL end-of-infile
       PERFORM process-data
       PEFORM read-next
   END-PERFORM
   .
priming-read.
   PERFORM read-next
   .
read-next.
   READ IN-FILE
   IF NOT IN-FILE-STATUS-OK
       PERFORM diagnostic-message-and-fail
   END-IF
   .

比。

  PERFORM UNTIL WS-EOF='Y'
     READ STUDENT INTO WS-STUDENT
        AT END MOVE 'Y' TO WS-EOF
        NOT AT END DISPLAY WS-STUDENT
     END-READ
  END-PERFORM

在不测试WS-EOF的情况下,您无法在END-READ之后放置任何代码。然而人们呢。

可靠性和易操作性

如果为SELECT中的文件指定了FILE STATUS,则由程序员进行测试。如果出现问题,AT END显然不是真的,但没有新记录。随后的READ将获得相同的情况,并且随后会出现Big Fat Loop。所以应该测试file-status-field(如果使用了FILE STATUS),那么,为什么不使用file-status-field来测试文件结尾,因为它更简单,而不是在不在最后。

当然,如果你不使用文件状态,运行时将处理事情,但是以一种广泛而直率的方式,没有机会提供额外的诊断信息,

当然,你可以使用USE AFTER ...但是这种情况更加复杂,许多人不习惯。

它鼓励使用GO TO“摆脱困境”

READ IN-FILE
  AT END GO TO no-more-records
END-READ

为什么要在FD下定义记录,为什么不在WORKING-STORAGE中

或者,READ ...READ ... INTO ...有什么区别?

FD中的FILE SECTION允许描述“记录区域”中的记录。

对于输入文件,这将是成功读取的最后一条记录。如果有的话。文件的OPEN将使记录区域可用。遇到文件结束后,将不再有当前记录。当文件CLOSEd时(无论是否到达文件结尾),都不会有当前记录。

这意味着您不应在文件打开之前,CLOSE之后或文件结束之后访问记录区域。在IBM大型机上不应该经常不能,因为它可以很容易导致S0C4异常终止,一个保护例外。输入区域实际上是在处理文件的IO例程中定义的,而不是在COBOL程序中。 FD只是将您的定义映射到记录区的地址。如果当时记录区域不存在,则无法访问它。

对于简单的文件结构,您不需要同时访问不同记录中的数据,您始终可以使用FD。

对于更复杂的结构,您需要存储来自不同记录类型的数据,因为只有当前记录在FD下可用。

您可以存储整个记录,也可以只存储您需要的部分。

在READ之后的某个时刻,您可以使用MOVE为各个字段存储所需的部件。

您可以在READ之后通过FD下的整个记录​​的MOVE存储整个记录,或者使用READ ... INTO ...自动执行此操作。

READ ... INTO ...对输入文件中的每条记录执行MOVE(隐式)。如果你不需要它,那就浪费了资源,而且由于人们为大型机上的资源(比如CPU使用)付费,除非你迫切需要它,否则值得避免。

网站通常有本地标准。你遵循标准,即使它们不好(你试图改变它们,也不总是成功)。如果你被告知使用READ ... INTO ......你就用它了。

但是,有关信息,我不使用READ ... INTO ...(除非在上述情况下)并且从未遇到过使用FD和移动我想要的数据(单个字段或整个记录)的问题。

使用FD是“最好的”。除非当地标准另有规定。那么遵循当地标准是“最好的”。

需要注意的是,有些内容可以修改上述内容并为程序中的记录创建特定区域。如果INTO(和WRITE上的FROM)可以隐式地两次获得你的整个记录​​MOVEd。


0
投票

好的,感谢您的评论,这是一个课程,所以它在风格方面相当自由。 Here is an excellent beginning for reading a file

通常情况下,如果您谈到“重新定义”,则表示您的老师希望您使用一个。所以你的记录将被定义为:

01  my-record.
    05  my-header.
        10  record-count  PIC 9(6).
        10  FILLER        PIC X(13).
    05  my-sales-record redefines my-header.
        10 branch-nr    PIC X(5).
        10 office-nr    PIC 9(2).
        10 count        PIC 9(5).
        10 sum          PIC 9(5)V99.

它有效,因为它们都是19个字符。不需要额外的填充物或复杂的东西。

然后,稍后,你会有一个

READ myfile INTO my-record

使用计数器(我希望您知道如何使用简单的数字变量)来计算记录。并用它来知道它是否是标题:

IF current-record = 1
    (do something with the header)
ELSE
    (do something with the sales record)
END-IF

确保所有这些都嵌入在我的示例链接中描述的循环中,它应该可以工作。

© www.soinside.com 2019 - 2024. All rights reserved.