Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当位置未知时,如何从文件中获取COBOL格式的字符串?_Cobol_Cobol85 - Fatal编程技术网

当位置未知时,如何从文件中获取COBOL格式的字符串?

当位置未知时,如何从文件中获取COBOL格式的字符串?,cobol,cobol85,Cobol,Cobol85,我对这个网站和COBOL都是新手。我试图编写一个程序,读入一个80字节的文件,找到一个特定的字符串,然后抓取另一个紧跟其后的字符串。我遇到的唯一问题是,字符串的起始位置在整个文件中并不总是在同一字节中。例如,我试图在下面查找的字符串是在整个文件中出现两次的长度(######)字符串: LENGTH(14909135) FILEID(DD:EDIREC) MSGDATE(130723) MSGDATELONG(20130723) MSGTIME(091053) MSGSEQO(001390) MS

我对这个网站和COBOL都是新手。我试图编写一个程序,读入一个80字节的文件,找到一个特定的字符串,然后抓取另一个紧跟其后的字符串。我遇到的唯一问题是,字符串的起始位置在整个文件中并不总是在同一字节中。例如,我试图在下面查找的字符串是在整个文件中出现两次的长度(######)字符串:

LENGTH(14909135) FILEID(DD:EDIREC) MSGDATE(130723) MSGDATELONG(20130723) MSGTIME(091053) MSGSEQO(001390) MSGNAME(00008557) MSGSEQNO(00001) SESSIONKEY(XXXXXXXX) DELIMITED(E) SYSNAME(XXXXX-XX) SYSLEVEL(XXXX) TIMEZONE(L) DATATYPE(E) EDITYPE(XXX) SENDERFILE(#####) RECFM(????) RECLEN(#) RECDLM(E) UNIQUEID(XXXXXXXX) SYSTYPE(##) SYSVER(#); RECEIVED ACCOUNT(XXXX) USERID(XXXXXXXX) CLASS(#E2) CHARGE(3) LENGTH(14911043) FILEID(DD:EDIREC) MSGDATE(130723) MSGDATELONG(20130723) MSGTIME(093045) MSGSEQO(001392) MSGSEQNO(00000) SESSIONKEY(XXXXXXXX) DELIMITED(C) SYSNAME(XXXXX-XX) SYSLEVEL(XXXX) TIMEZONE(L) DATATYPE(E) EDITYPE(UNFORMATTED) SENDERFILE(XXXXXXXXXXXXX) RECFM(????) RECLEN(0) RECDLM(C) UNIQUEID(XXXXXXXX) SYSTYPE(24) SYSVER(5); 长度(14909135)文件ID(DD:EDIREC)MSGDATE(130723)MSGDATELONG(20130723) MSGTIME(091053)MSGSEQO(001390)MSGNAME(00008557)MSGSEQNO(00001) 会话密钥(XXXXXXXX)分隔(E)系统名(XXXXX-XX)系统级(XXXXX)时区(L) 数据类型(E)编辑类型(XXX)发送器文件(E)RECFM(??)RECEN(E) UNIQUEID(XXXXXXXX)系统类型(##)系统版本(#); 已接收帐户(XXXX)用户ID(XXXXXXXX)类别(#E2)费用(3)长度(14911043) 文件ID(DD:EDIREC)MSGDATE(130723)MSGDATELONG(20130723)MSGTIME(093045) MSGSEQO(001392)MSGSEQNO(00000)会话密钥(XXXXXXXX)分隔(C) 系统名称(XXXXX-XX)系统级别(XXXX)时区(L)数据类型(E)编辑类型(未格式化) 发送方文件(XXXXXXXXXXXX)RECFM(??)RECEN(0)RECDLM(C)唯一ID(XXXXXXXX) 系统类型(24)系统版本(5); 请注意两个长度(#####)字符串。下面的代码设法计算长度字符串出现的次数,并获取最终长度字符串计数(我真正想要的是长度字符串中的数字),但仅当它们位于这两个位置时:

WORKING-STORAGE SECTION. 01 WS-INPUT-RECORD PIC X(80). 01 WS-STRINGS. 05 LENGTH-STRING PIC X(7) VALUE 'LENGTH('. 01 WS-COUNTERS. 05 WS-MSG-COUNT PIC 9(11). 01 WS-CHAR-TOTALS. 05 CHAR-TOTAL PIC 9(11) VALUE ZEROS. 05 TMP-TOTAL PIC X(11) VALUE ZEROS. ...... PROCEDURE DIVISION. 2200-GET-MSG-TOTAL. INSPECT WS-INPUT-RECORD TALLYING WS-MSG-COUNT FOR ALL LENGTH-STRING. 2300-CHAR-TOTAL. IF WS-INPUT-RECORD(1:7) = LENGTH-STRING MOVE WS-INPUT-RECORD(8:9) TO TMP-TOTAL UNSTRING TMP-TOTAL DELIMITED BY ')' INTO CHAR-TOTAL END-IF IF WS-INPUT-RECORD(61:7) = LENGTH-STRING MOVE WS-INPUT-RECORD(68:9) TO TMP-TOTAL UNSTRING TMP-TOTAL DELIMITED BY ')' INTO CHAR-TOTAL END-IF 工作和储存科。 01 WS-INPUT-RECORD PIC X(80)。 01 WS-STRINGS。 05长度字符串PIC X(7)值“长度(”。 01个WS-COUNTERS。 05 WS-MSG-COUNT图9(11)。 01 WS-CHAR-TOTALS。 05字符-总PIC 9(11)值为零。 05 TMP-总PIC X(11)值为零。 ...... 程序司。 2200-GET-MSG-TOTAL。 检查WS-INPUT-RECORD 统计所有长度字符串的WS-MSG-COUNT。 总共2300个字符。 如果WS-INPUT-RECORD(1:7)=长度字符串 将WS-INPUT-RECORD(8:9)移动到TMP-TOTAL 解压TMP-TOTAL,以“')分隔 转换为字符总数 端到端IF 如果WS-INPUT-RECORD(61:7)=长度字符串 将WS-INPUT-RECORD(68:9)移动到TMP-TOTAL 解压TMP-TOTAL,以“')分隔 转换为字符总数 端到端IF 该代码对于上面输入示例中显示的两个位置非常有效。但如果长度(######)结束于任何其他字节位置,则它将不起作用。除了编码80个IF语句来检查文件中每个字节的字符串外,还有更简单的方法来获取长度参数中的值吗?我查看了很多其他帖子,并考虑过使用指针或表格,但我似乎不太明白。您可以使用“执行变化”循环查看每行中字符串的每个块,其中每个块都是一个字符串,即您要查找的字符串的长度。下面是一个在OpenCobol中工作的示例:

   IDENTIFICATION DIVISION.
   PROGRAM-ID. FIND-STRING.

   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
   SELECT IN-FILE ASSIGN TO 'SAMPLE-LEN.TXT'
       ORGANIZATION IS LINE SEQUENTIAL.

   DATA DIVISION.
   FILE SECTION.
   FD  IN-FILE.
   01  IN-RECORD                        PIC X(80).

   WORKING-STORAGE SECTION.
   01  END-OF-FILE-SWITCH               PIC XXX VALUE 'NO '.
       88  END-OF-FILE                  VALUE 'YES'.
   01  STRING-MARKER                    PIC X(7) VALUE 'LENGTH('.
   01  STRING-MARKER-LENGTH             PIC 99 VALUE 7.
   01  STRING-SOUGHT                    PIC X(11).
   01  STRING-INDEX                     PIC 99.
   01  RECORD-LENGTH                    PIC 99 VALUE 80.

   PROCEDURE DIVISION.
   MAIN.
       OPEN INPUT IN-FILE
       PERFORM UNTIL END-OF-FILE
           READ IN-FILE
               AT END
                   SET END-OF-FILE TO TRUE
               NOT AT END
                   PERFORM FIND-STRING
           END-READ
       END-PERFORM
       CLOSE IN-FILE
       STOP RUN
       .

   FIND-STRING.
       PERFORM VARYING STRING-INDEX FROM 1 BY 1
           UNTIL STRING-INDEX > (RECORD-LENGTH
                                 - STRING-MARKER-LENGTH)
           IF IN-RECORD(STRING-INDEX:STRING-MARKER-LENGTH) =
              STRING-MARKER
              UNSTRING IN-RECORD(STRING-INDEX
                                 + STRING-MARKER-LENGTH : 10)
                  DELIMITED BY ')' INTO STRING-SOUGHT 
              END-UNSTRING 
              DISPLAY STRING-SOUGHT END-DISPLAY 
           END-IF 
       END-PERFORM 
       . 

使用INSPECT来确定当前记录上的长度

仅当存在时,执行以下操作:

使用长度(作为带有两个接收字段的分隔符)解除拉伸

取消对第二个接收字段的排序,该字段由分隔符)分隔,并将数字留给您

例如:

01  delimiting-field PIC X(7) VALUE "LENGTH(".
01  desitnation-field-1 PIC X.
01  destination-field-2 PIC X(18) JUST RIGHT.

UNSTRING source-field DELIMITED BY delimiting-field INTO desitnation-field-1
                                                         destination-field-2
放弃destination-field-1。使用destination-field-2作为第二次解编的输入

使用有意义的名称,而不是我所展示的那些来说明示例

所以

01 WS-INPUT-RECORD PIC X(80)。
01长度数二进制PIC 9(4)。
01分隔符计数二进制PIC 9(4)。
88个无分隔符值为零。
88单分隔符值1。
01长度-开口-帕伦图X(7)
值“长度(”。
01数据忽略图X。
01数据长度值PIC X(80)。
01收盘价(PIC X值“)。
01长度值一张图片X(18)正好。
最重要的事。
将无分隔符设置为TRUE
检查WS-INPUT-RECORD计数分隔符计数
适用于所有长度的开放式排列
评价真实
当没有分隔符时
继续
当一个分隔符
执行获取数据
当其他
表演哦,天哪,不止一个
最终评估
. 
获取最新数据。
取消对由分隔符分隔的WS-INPUT记录的排序
长度开环
进入数据到忽略状态
数据长度值
使用长度值解列数据
由CLOSING-PAREN分隔
转化为长度的值
显示“这就是我们发现的”
显示“>”
长度值
"" 
WS-INPUT-RECORD

“根据比尔·伍德格的评论,这里有一个更好的解决方案。感谢比尔的比尔,教我不要懈怠:)我仍然喜欢循环浏览每一张唱片,作为在一行捕捉多个匹配项的一种方式,所以我保留了那部分。


谢谢!我会试一试这很有效,但我想我应该提到,我必须将记录长度变量更改为68,因为这是最后一个“长度”的位置('可能会出现。当我以80开始尝试它时,它导致异常终止,因为它超出了记录的范围。再次感谢!谢谢,比尔。我将根据您的评论发布一个更好的解决方案。谢谢您的评论,尽管是快速问题。您如何使用长度(作为带有两个接收字段的分隔符?如果您使用执行代码,我将包括INSP
    01  WS-INPUT-RECORD                     PIC X(80). 
    01  NUMBER-OF-LENGTHS            BINARY PIC 9(4). 
    01  DELIMITER-COUNT              BINARY PIC 9(4). 
        88  NO-DELIMITERS                   VALUE ZERO. 
        88  ONE-DELIMITER                   VALUE 1. 
    01  LENGTH-OPEN-PAREN                   PIC X(7) 
                                            VALUE "LENGTH(". 
    01  DATA-TO-IGNORE                      PIC X. 
    01  DATA-WITH-LENGTH-VALUE              PIC X(80). 
    01  CLOSING-PAREN                       PIC X VALUE ")". 
    01  VALUE-OF-LENGTH-AN                  PIC X(18) JUST RIGHT.

   THE-STUFF. 
       SET NO-DELIMITERS            TO TRUE 
       INSPECT WS-INPUT-RECORD      TALLYING DELIMITER-COUNT 
                                     FOR ALL LENGTH-OPEN-PAREN
       EVALUATE TRUE 
           WHEN NO-DELIMITERS 
               CONTINUE 
           WHEN ONE-DELIMITER 
               PERFORM              GET-THE-DATA 
           WHEN OTHER 
               PERFORM              OH-DEAR-MORE-THAN-ONE 
       END-EVALUATE 
       . 
   GET-THE-DATA. 
       UNSTRING WS-INPUT-RECORD     DELIMITED BY 
                                    LENGTH-OPEN-PAREN 
           INTO                     DATA-TO-IGNORE 
                                    DATA-WITH-LENGTH-VALUE 
       UNSTRING DATA-WITH-LENGTH-VALUE 
                                    DELIMITED BY CLOSING-PAREN
           INTO                     VALUE-OF-LENGTH-AN 
       DISPLAY "THIS IS WHAT WE FOUND" 
       DISPLAY ">" 
               VALUE-OF-LENGTH-AN 
               "<" 
       . 
   OH-DEAR-MORE-THAN-ONE. 
       DISPLAY "THE FOLLOWING LINE HAS MORE THAN ONE LENGTH(" 
       DISPLAY ">" 
               WS-INPUT-RECORD 
               "<" 
       . 
   IDENTIFICATION DIVISION.
   PROGRAM-ID. FIND-STRING-2.

   ENVIRONMENT DIVISION.
   INPUT-OUTPUT SECTION.
   FILE-CONTROL.
   SELECT IN-FILE ASSIGN TO 'SAMPLE-LEN.TXT'
       ORGANIZATION IS LINE SEQUENTIAL
       FILE STATUS IS IN-FILE-STATUS.

   DATA DIVISION.
   FILE SECTION.
   FD  IN-FILE.
   01  IN-RECORD                        PIC X(80).

   WORKING-STORAGE SECTION.
   01  IN-FILE-STATUS                   PIC XX.
   01  END-OF-FILE-SWITCH               PIC XXX VALUE 'NO '.
       88  END-OF-FILE                  VALUE 'YES'.
   01  STRING-MARKER-LEFT               PIC X(7) VALUE 'LENGTH('.
   01  STRING-MARKER-RIGHT              PIC X VALUE ')'.
   01  STRING-MARKER-LENGTH             PIC 99 USAGE BINARY.
   01  STRING-INDEX                     PIC 99 USAGE BINARY.
   01  START-INDEX                      PIC 99 USAGE BINARY.
   01  END-INDEX                        PIC 99 USAGE BINARY.
   01  RECORD-LENGTH                    PIC 99 USAGE BINARY.
   01  SEARCH-LENGTH                    PIC 99 USAGE BINARY.
   01  IS-END-FOUND                     PIC XXX VALUE 'NO '.
       88  END-FOUND                    VALUE 'YES'.
       88  END-NOT-FOUND                VALUE 'NO '.

   PROCEDURE DIVISION.
   MAIN.
       OPEN INPUT IN-FILE

       IF IN-FILE-STATUS NOT = '00'
           DISPLAY 'FILE READ ERROR ' IN-FILE-STATUS
           END-DISPLAY
           PERFORM EXIT-PROGRAM
       END-IF

       PERFORM INITIALIZE-LENGTHS

       PERFORM UNTIL END-OF-FILE
           READ IN-FILE
               AT END 
                   SET END-OF-FILE TO TRUE
               NOT AT END
                   PERFORM FIND-STRING
           END-READ
       END-PERFORM
       PERFORM EXIT-PROGRAM
       .

   INITIALIZE-LENGTHS.
       MOVE FUNCTION LENGTH(IN-RECORD) TO RECORD-LENGTH 
       COMPUTE STRING-MARKER-LENGTH = FUNCTION LENGTH(
           STRING-MARKER-LEFT)
       END-COMPUTE
       COMPUTE SEARCH-LENGTH = RECORD-LENGTH - STRING-MARKER-LENGTH
       END-COMPUTE
       .

   FIND-STRING.
       PERFORM VARYING STRING-INDEX FROM 1 BY 1
           UNTIL STRING-INDEX > SEARCH-LENGTH 
           IF IN-RECORD(STRING-INDEX:STRING-MARKER-LENGTH) =
              STRING-MARKER-LEFT
              COMPUTE START-INDEX = STRING-INDEX 
                  + STRING-MARKER-LENGTH
              END-COMPUTE
              SET END-NOT-FOUND TO TRUE
              PERFORM VARYING END-INDEX FROM START-INDEX BY 1 
              UNTIL END-INDEX > RECORD-LENGTH OR END-FOUND
                  IF IN-RECORD(END-INDEX:
                  FUNCTION LENGTH(STRING-MARKER-RIGHT)) = 
                  STRING-MARKER-RIGHT
                      SET END-FOUND TO TRUE
                  END-IF
              END-PERFORM
              COMPUTE END-INDEX = END-INDEX - START-INDEX - 1
              END-COMPUTE
              DISPLAY IN-RECORD(START-INDEX:END-INDEX)
              END-DISPLAY
           END-IF
       END-PERFORM
       .

   EXIT-PROGRAM.
       CLOSE IN-FILE
       STOP RUN
       .