首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何处理具有两种不同类型记录的顺序文件?

如何处理具有两种不同类型记录的顺序文件?
EN

Stack Overflow用户
提问于 2016-01-12 11:38:33
回答 2查看 3K关注 0票数 1

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

第一个是我所称的头记录,它说明文件中记录的总数(不包括头记录本身)。这只是一项记录。

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

代码语言:javascript
复制
01 header-record.
   03 record-count  PIC 9(6).
   03 FILLER        PIC X(13). 

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

代码语言:javascript
复制
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. 我该怎么做?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-01-12 14:01:17

如果您定义了这两个记录,您就可以在单个FD下完全按照您已经显示的那样做。这将给您一个隐含的重新定义。

在文件的SELECT语句上使用文件状态(始终)。始终检查文件状态字段是否获得期望值.使用88条件名作为值"10“来标识文件结束。不要使用AT END/NOT AT END

请注意,您不能在练习中完美地完成这个任务,因为文件没有被正确定义。没有标识头记录或数据记录的可用指示。唯一的指示是“头是第一位的,其余的都是数据”。这似乎很好,但当有人最初对编写文件的程序进行腌制,而没有给出标题或两个或两个以上的头时,就会转向slok。

如果一个文件有一个结构,那么这个结构应该在数据中,因为它可以被检查。处理一个糟糕的文件,就好像它是一个好的文件一样,可能会非常昂贵。也很尴尬。

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

在您的初始处理中(在输入文件被OPEN编辑之后),您将读取第一个记录。如果是这样的话,处理“空文件”。检查它是一个标题。把记录存起来。

然后你读下一张唱片。你检查它不是标题。

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

代码语言:javascript
复制
Loop until end-of-input
  process record
  read next record
End-Loop

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

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

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

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

复杂性和可理解性

代码语言:javascript
复制
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
   .

Vs.

代码语言:javascript
复制
  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,就不能在结束读取之后放入任何代码。但人们是这样做的。

可靠性和易用性

如果在SELECT中为一个文件指定了文件状态,那么就由程序员来测试它。如果有什么不对劲,很明显,最终是不正确的,但没有新的记录。随后的阅读将得到同样的情况,一个大脂肪圈接踵而至。因此,应该测试文件状态字段(如果使用了文件状态),那么,为什么不使用文件状态字段来测试文件结束,因为它更简单,而不是在非AT终端中的进一步条件。

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

当然,你也可以在.但这进一步复杂化了,许多人都不习惯。

它鼓励使用GO来“摆脱混乱”。

代码语言:javascript
复制
READ IN-FILE
  AT END GO TO no-more-records
END-READ

为什么在FD下定义记录,为什么不在工作存储中?

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

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

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

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

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

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

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

在读取之后的某个时间点,您可以通过移动单个字段来存储所需的部分。

在读取之后,您可以通过整个记录在FD下的移动来存储整个记录,或者使用READ .变成..。这是自动完成的。

读..。变成..。对输入文件上的每条记录进行移动(隐式)。如果您不需要这样做,这是对资源的浪费,而且由于人们为大型机上的资源(如CPU )付费,除非您迫切需要它,否则值得避免。

网站通常有当地的标准。你遵循这些标准,即使它们不是很好(你试图改变它们,不要总是成功)。如果你被告知使用阅读..。变成..。你用它。

不过,关于信息,我不使用阅读.变成..。(除非在上述情况下),并且从未遇到使用FD和MOVEing的问题--我想要的数据(无论是单个字段,还是整个记录)。

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

请注意,有一些东西可以修改上面的内容,并在程序中为记录创建一个特定的区域。如果进入(从写开始)可以隐式地获取整个记录MOVEd两次。

票数 2
EN

Stack Overflow用户

发布于 2016-01-12 13:41:18

好的,谢谢你的评论,这是一门课程,所以它在风格上是相当免费的。下面是读取文件的一个极好的开端

通常情况下,如果你说到“重新定义”,这意味着你的老师希望你使用一个。所以你的记录应该是这样定义的:

代码语言:javascript
复制
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个字符长。不需要额外的填料,也不需要复杂的东西。

然后,稍后,你会有一个

代码语言:javascript
复制
READ myfile INTO my-record

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

代码语言:javascript
复制
IF current-record = 1
    (do something with the header)
ELSE
    (do something with the sales record)
END-IF

确保所有这些都嵌入在一个循环中,就像我的示例链接中描述的那样,并且应该可以工作。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34742684

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档