对于作为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.
我习惯使用一种记录类型的文件。
这项任务比我在这里描述的要复杂得多,但是 对于这部分问题,我的程序必须读取并处理销售记录记录并打印它已读取的这些记录的总量,并将其与标题记录中列出的数量进行比较。如果两者不匹配,我需要在输出列表中有一个语句来记录这个错误。
答案 0 :(得分:2)
您可以在单个FD
下定义两个记录,您可以完全按照您的显示进行定义。这将为您提供隐含的REDEFINES。
在SELECT语句中对文件使用FILE STATUS(always)。始终检查文件状态字段是否获得预期值。使用88条件名称为" 10"识别文件结束。请勿使用AT END
/ NOT AT END
。
请注意,您无法完成练习,因为文件尚未正确定义。没有迹象表明标题记录或数据记录。唯一的迹象是"标题是第一个,其余的都是数据"。这可能看起来很好,但是当有人挑选最初编写文件的程序时,它会变成邋and,并且没有标题或两个或更多标题。
如果文件具有结构,则结构应该在数据内,因为它可以被检查。处理坏文件就好像它是一个好文件可能非常昂贵。而且很尴尬。
此外,您需要知道文件是否允许"为空"。由于它有一个标题记录,一个"空"文件应包含具有零数据记录计数的标头记录。您的情况可能有所不同,因为文件未设计。
在初始处理中(输入文件为OPEN
之后),您将读取第一条记录。处理"空文件"如果是这样的话。检查它是一个标题。存储记录计数。
然后您阅读下一条记录。你检查它是不是标题。
然后处理您的数据,记住您有第一个可用的数据记录。
Loop until end-of-input
process record
read next record
End-Loop
在文件结尾处(循环结束时),您检查标题上的记录数(从存储的值)到您读取的数据记录数(在记录处理过程中计算)。 / p>
一旦你有了你的程序,你就会拥有一个"模型"以其他程序为基础。你只需得到通用"这就是我处理文件的方式"纠正一次,然后将其用作下一个文件处理程序的起点。下一个程序会更复杂,所以最终会得到另一个模型。
一段时间之后,您将拥有大约五个模型,每个模型都基于更简单任务的工作代码。
我反对使用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
.
Vs以上。
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
您无法在END-READ之后输入任何代码而无需测试WS-EOF。人们确实如此。
可靠性和易操作性
如果为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。
答案 1 :(得分: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
确保所有这些都嵌入在我的示例链接中描述的循环中,它应该可以工作。