使用COBOL

时间:2015-05-25 21:09:37

标签: file-io cobol

我是COBOL的新手,无法搜索.dat文件中的特定条目。 我们的想法是在文件中搜索其中一个字段中具有特定代码的所有记录。

我试图在谷歌找到答案,但我到处都回答不同,我不知道为什么我不能适应我的问题。

我也发现了这个问题:

How to insert records in a table in a text file using COBOL and search and display record(s) which satisfy a condition?

但答案并没有详细说明。

这是我的代码:

IDENTIFICATION DIVISION.
   program-id. AR AS "A.AR".

   environment division.
   configuration section.
   special-names.  DECIMAL-POINT   IS  COMMA.
   INPUT-OUTPUT    SECTION.
   FILE-CONTROL.
       SELECT  ARQ-ATUALIZACAO  ASSIGN  "C:\temp\atualizacao.dat"
       ORGANIZATION    IS  INDEXED
       ACCESS  MODE    IS  SEQUENTIAL
       RECORD  KEY     IS ID-ATUALIZACAO
       ALTERNATE RECORD KEY IS COD-RASTREIO
       FILE    STATUS  IS  ST-ATUALIZACAO.

   data division.
   FILE    SECTION.
   FD  ARQ-ATUALIZACAO.
   01  REG-ATUALIZACAO.
       05  ID-ATUALIZACAO  PIC 9(10).
       05  COD-RASTREIO    PIC X(13).
       05  TITULO          PIC X(15).
       05  DESCRICAO       PIC X(30).
       05  FILLER          PIC X(30).
   working-storage section.
   01 WS-RECORD.
       03 ENTRIES OCCURS 18 TIMES INDEXED BY I.
           05 WS-ID   PIC 9(10).
           05 WS-RAST PIC X(13).
           05 WS-TIT  PIC X(15).
           05 WS-DESC PIC X(30).
   77  ARE-THERE-MORE-RECORDS PIC XXX VALUE "YES".
   77  NAME-COUNT          PIC 99.
   77  PROCURA             PIC X(13).
   77  ST-ATUALIZACAO      PIC XX  VALUE   SPACES.

   procedure division.
   OPEN INPUT ARQ-ATUALIZACAO
       PERFORM UNTIL ARE-THERE-MORE-RECORDS = 'NO '
           READ ARQ-ATUALIZACAO
               AT END
                   MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
               NOT AT END
                   PERFORM 300-STORE-NAME
           END-READ
       END-PERFORM
   CLOSE ARQ-ATUALIZACAO.

   300-STORE-NAME.
   ADD 1 TO NAME-COUNT
   MOVE REG-ATUALIZACAO TO ENTRIES OF WS-RECORD(NAME-COUNT).

   OPEN    I-O ARQ-ATUALIZACAO

       DISPLAY "CODIGO DA ENCOMENDA.:" AT  1010
       DISPLAY "STATUS:"       AT  2433
       DISPLAY ST-ATUALIZACAO   AT  2440
       ACCEPT  PROCURA    AT 1030 WITH REQUIRED FULL
       SEARCH ENTRIES
           AT END DISPLAY "CODIGO NAO ENCONTRADO" AT 0210
           WHEN  WS-RAST(I) = PROCURA
           DISPLAY "REGISTROS ENCONTRADOS" AT 0210
           DISPLAY WS-RAST(I)  AT 0310
           DISPLAY WS-ID(I)    AT 0410
           DISPLAY WS-TIT(I)   AT 0510
           DISPLAY WS-DESC(I)  AT 0610
       END-SEARCH
   CLOSE ARQ-ATUALIZACAO
   EXIT PROGRAM.

编辑 - 我更改了代码,所以我会在这里发布新代码:

   IDENTIFICATION DIVISION.
   program-id. ATUALIZACAOR AS "ATUALIZACAO.ATUALIZACAOR".
   environment division.
   configuration section.
   special-names.  DECIMAL-POINT   IS  COMMA.
   INPUT-OUTPUT    SECTION.
   FILE-CONTROL.
       SELECT  ARQ-ATUALIZACAO  ASSIGN  "C:\temp\atualizacao.dat"
       ORGANIZATION    IS  INDEXED
       RECORD  KEY     IS  ID-ATUALIZACAO
       ALTERNATE RECORD KEY IS COD-RASTREIO
       ACCESS  MODE    IS  RANDOM
       FILE    STATUS  IS  ST-ATUALIZACAO.

   data division.
   FILE    SECTION.
   FD  ARQ-ATUALIZACAO.
   01  REG-ATUALIZACAO.
       05  ID-ATUALIZACAO  PIC 9(10).
       05  COD-RASTREIO    PIC X(13).
       05  TITULO          PIC X(15).
       05  DESCRICAO       PIC X(30).
       05  FILLER          PIC X(30).
   working-storage section.
   01  ST-ATUALIZACAO      PIC XX.
       88 end-of-input-file    VALUE   "10".
       88  INPUT-FILE-OK       VALUE ZERO "10".
   77  PROCURA             PIC X(13). 
   77  RESP                PIC X   VALUE   SPACE.

   procedure division.
   INICIO.
       PERFORM WITH    TEST    AFTER   UNTIL   RESP    =   "N"
           DISPLAY "CODIGO DA ENCOMENDA.:" AT  1010 ERASE SCREEN
           DISPLAY "STATUS:"       AT  2433
           DISPLAY ST-ATUALIZACAO   AT  2440
           ACCEPT  PROCURA    AT 1030 WITH REQUIRED FULL
           OPEN I-O ARQ-ATUALIZACAO
           PERFORM                      priming-READ-input-file
               PERFORM
                   UNTIL end-of-input-file
               PERFORM                  process-input
               PERFORM                  READ-input-file
           END-PERFORM
           DISPLAY "DESEJA CONSULTAR OUTRA ATUALIZACAO? (S/N)"   
               AT 2001                                                  
               ACCEPT  RESP        AT  2044    WITH    UPPER
       END-PERFORM
       CLOSE ARQ-ATUALIZACAO
       EXIT PROGRAM
   .

   priming-READ-input-file.
       PERFORM     READ-input-file
       IF end-of-input-file
           DISPLAY "END OF FILE" AT 2510
       END-IF
   .

   READ-input-file.
       READ ARQ-ATUALIZACAO
           IF NOT INPUT-FILE-OK
               DISPLAY "FILE NOT OK" AT 2310
               DISPLAY ST-ATUALIZACAO   AT  2440
               STOP " "
           END-IF
   .

   process-input.
       IF COD-RASTREIO = PROCURA
           DISPLAY ID-ATUALIZACAO AT 2410 
           STOP " "
       END-IF
   .

我在文件中提供的示例数据' atualizacao.dat'是:

ID-ATUALIZACAO:0000000001
COD-RASTREIO:qweqweqweqweqwee
TITULO:测试
DESCRICAO:说明

ID-ATUALIZACAO:0000000002
COD-RASTREIO:qweqweqweqweqwee
TITULO:test2
DESCRICAO:description2

1 个答案:

答案 0 :(得分:2)

因为SELECT中有ACCESS RANDOMREAD file-name(没有NEXT或KEY)的默认操作是键控读取。

将其更改为ACCESS SEQUENTIAL

无论如何,将其更改为READ file-name NEXT,这是一个明确的顺序读取。

我总是在READ上使用显式的NEXT或KEY,以便不依赖于默认行为,这取决于文件的类型(以及OPEN的类型)。

我忘记明确的时候就是当我复制其他人的例子而不够小心的时候,我很抱歉我错过了你原本没有NEXT。

因为您没有使用OPEN I-O(您没有使用键控读取或START,所以您不需要ACCESS的RANDOM或DYNAMIC)只需使用OPEN ... INPUT

您尚未提及用户输入的要求。用户输入可能/可能不需要处于循环中。

您的OPEN后没有检查文件状态字段。你会发现那里有问题。在同一程序中多次打开同一文件是不好的做法,即使您多次关闭文件(您没有这样做,因此可能存在问题。

好的,首先是READ。好的,先退回到SELECT上的文件状态。

在文件上使用FILE STATUS会获得一个双字节字段,告诉您上次IO操作发生了什么。如果该字段包含零,一切都很好。

我建议您对可能使用的所有文件使用FILE STATUS,并在文件上的每个IO之后检查文件状态字段(每个文件保持唯一)。

对文件使用文件状态告诉COBOL运行时"我将处理出现的任何问题,通过在此字段中输入代码告诉我何时出现问题&#34 34。

如果您使用文件状态而不要检查文件状态字段,则IO错误会悄然消失。

现在回到READ。

这将读取下一个可用记录。

READ file-name

如果遇到文件结尾,则文件状态字段将设置为" 10"。

您可以为文件状态字段定义88级条件名称:

01  input-file-status                   PIC XX.
    88  end-of-input-file               VALUE "10".

你的循环可以是:

PERFORM
  UNTIL end-of-input-file
    READ input-file
END-PERFORM

只是阅读一个文件并没有多大用处,你也想要处理数据。使代码更复杂的一种方法是在READ和PERFORM之后测试输入结束文件,如果不是:

PERFORM
  UNTIL end-of-input-file
    READ input-file
    IF NOT end-of-input-file
        PERFORM process-input
    END-IF
END-PERFORM

使用" priming read"将其与同一事物进行比较,这意味着您在开始循环之前读取第一条记录(如果存在):

READ input-file
PERFORM
  UNTIL end-of-input-file
    PERFORM process-input
    READ input-file
END-PERFORM

每次通过PERFORM,都有一个可用于处理的记录,或者在上一个PERFORM结束时已经识别出文件结尾。

将此与您所拥有的相比较:

PERFORM 
  UNTIL ARE-THERE-MORE-RECORDS = 'NO '
    READ ARQ-ATUALIZACAO
      AT END
         MOVE 'NO ' TO ARE-THERE-MORE-RECORDS
      NOT AT END
         PERFORM 300-STORE-NAME
    END-READ
END-PERFORM        

我说过在每个IO之后测试文件状态字段。这会让事情变得混乱,那么如何避免呢? PERFORM:

PERFORM                      READ-input-file
PERFORM
  UNTIL end-of-input-file
    PERFORM                  process-input
    PERFORM                  READ-input-file
END-PERFORM

然后READ-input-file可以检查文件状态字段(88级),而不会使代码混乱。

进一步改善。你有两个PERFORMs" read",但它们不一样,所以给它们命名不同:

PERFORM                      priming-READ-input-file
PERFORM
  UNTIL end-of-input-file
    PERFORM                  process-input
    PERFORM                  READ-input-file
END-PERFORM

然后:

priming-READ-input-file.
    PERFORM                  READ-input-file
    .

现在代码和以前一样,但是讲的是一个更好的故事。并且可以进一步改进,而不会复杂化:

priming-READ-input-file.
    PERFORM                  READ-input-file
    IF end-of-input-file
        do something which says "hey, there should always be records,
        a bad thing has happened" and then crash whilst DISPLAYing
        necessary information
    END-IF
    .

然后你有一个简单的通用程序,它在一个循环中读取一个文件直到文件结束,你可以在任何需要的时候用它作为基础。

您可以轻松地沿着相同的行扩展代码以处理"文件标题"在一个文件上,然后进行一些更改以处理"文件预告片",确保每个只有一个,标题是第一个,预告片是最后一个,标题是正确的文件和正确的营业日期和预告片具有正确的记录计数和哈希总数。

所有这些都不会干扰程序的控制逻辑。

然后你有第二个程序,你也可以用作基础。

对于您的任务,您首先需要与用户交互,存储用户数据,针对每条记录测试数据。这可能是用户输入的一个,或几个,你没有说。

如果用户的输入取决于已显示的结果,则只需存储文件中的记录。可能就是这种情况,你没有说。

如果用户提供一条输入以匹配一个字段,则只需在处理每条记录时测试该值(已获取)。

原始程序出现问题:

在SELECT上使用的文件状态但没有检查文件状态字段(ST-ATUALIZACAO)。

文件的第二个OPEN,它将在300-STORE-NAME中失败(文件已经打开)。

300-STORE-NAME中文件的关闭。哪个会奏效。但现在当您执行下一次READ时,您的文件将被关闭。所以READ不会起作用。它是如何运作的(如果它会做什么)?好吧,我想,因为我不知道,因为我没有这样编码,那就是阅读指定了FILE STATUS的关闭文件和AT END将导致AT END被处理。肯定FD下01级的内容是不确定的。

每次向表格添加记录时,您都试图搜索表格。如果你需要将所有记录存储在一个表中,只有在你有文件结束并且所有内容都在表格中时才进行搜索。

一旦有了工作程序,就会有另一个名为Code Review的StackExchange站点,您可以在其中询问如何更好地编写代码。

创建一个非常简单的程序,它在循环中读取输入文件,直到文件结束。

在该程序开始时,获取用户输入。如果有多个用户输入,请将其存储在带有OCCURS的表中。

对于每个读取的记录,请检查用户数据(单个字段或表格),并在得到匹配项时生成输出。

在这里查看答案Cobol Read statement format. Can it be redone a different way?,然后点击链接。注意如何使用启动读取,以及如何使用文件状态字段来实际检查错误并在顺序读取文件时识别文件的结尾。