输出错误
Output is wrong
编写了我的程序,但我无法获得所需的正确输出
下面是我的代码和我的输出输入。
还有我的程序程序是否有意义,是否应该修改它,似乎是有意义的,但看了不同的书,我不再确定了。
FD INPUT-FILE.
01 INPUT-RECORD.
05 EXCUSE-NUMBER PIC 9(02).
88 VALID-EXCUSE VALUE 1 THRU 10.
05 FILLER PIC X(03).
05 NUMBER-TIMES-USED PIC 9(02).
05 FILLER PIC X(73).
FD REPORT-FILE.
01 REPORT-RECORD PIC X(80).
FD ERROR-FILE.
01 ERROR-RECORD PIC X(80).
WORKING-STORAGE SECTION.
******************************************************************
* DEFINES PROCESSINGVARIABLES AND OUTPUT LINES *
******************************************************************
01 WS-AREA.
05 WS-IF-STATUS PIC X(02).
05 WS-OF-STATUS PIC X(02).
05 WS-EF-STATUS PIC X(02).
05 WS-END-OF-FILE PIC X(01) VALUE "N".
88 AT-WS-END-OF-FILE VALUE "Y".
05 WS-INVALID-RECORD PIC X(01) VALUE "N".
05 WS-LINE-NUMBER PIC 9(03) VALUE 0.
05 WS-MOST-USED-EXCUSE PIC 9(02) VALUE 0.
05 WS-EXCUSE PIC 9(02) VALUE 0.
05 WS-EXCUSE-TOTAL PIC 9(04).
01 BLANK-LINE.
05 PIC X(80).
******************************************************************
* (THIS IS WHERE THE HEADING ON THE PRINT OUT SHEET GOES) *
******************************************************************
01 HEADING-LINE-1.
05 FILLER PIC X(14) VALUE SPACES.
05 FILLER PIC X(37)
VALUE "TEN MOST OUTRAGEOUS HOME-WORK EXCUSES".
01 HEADING-LINE-2.
05 FILLER PIC X(11).
05 FILLER PIC X(06) VALUE "RECORD".
05 FILLER PIC X(08).
05 FILLER PIC X(05) VALUE "IMAGE".
******************************************************************
* DETAIL-LINE COMMENTS. *
* on the detail line we are writing out the Data information *
* in particular, when we write out the line-number, error *
* excuse number, excuses used, and how many times used *
* Detail summary will be reported out *
* Stars will be Display underneath bad data. *
*****************************************************************
01 DETAIL-LINE.
05 FILLER PIC X(03).
05 DL-EXCUSE-NUMBER PIC 9(02).
05 FILLER PIC X(03).
05 DL-EXCUSE-USED PIC X(51).
05 FILLER PIC X(03).
05 DL-AMOUNT-USED PIC ZZ9.
01 DETAIL-LINE-ERROR-1.
05 FILLER PIC X(08) VALUE SPACES.
05 DLE-LINE-NUMBER PIC ZZ9.
05 FILLER PIC X(09) VALUE SPACES.
05 DLE-ERROR PIC X(16).
01 DETAIL-LINE-ERROR-2.
05 FILLER PIC X(20) VALUE SPACES.
05 DLE-EXCUSE-NUMBER PIC X(02) VALUE SPACES.
05 FILLER PIC X(03) VALUE SPACES.
05 DLE-EXCUSE PIC X(02) VALUE SPACES.
01 DETAIL-TOTAL.
05 FILLER PIC X(41) VALUE SPACES.
05 FILLER PIC X(20)
VALUE "TOTAL EXCUSES USED =".
05 DT-TOTAL PIC ZZZ9 VALUE ZERO.
01 DETAIL-TOTAL-MOST-USED.
05 FILLER PIC X(34) VALUE SPACES.
05 FILLER PIC X(27)
VALUE "EXCUSE USE THE MOST TIMES =".
05 DTMU-HIGH PIC ZZZ9.
******************************************************************
* This is where we hard code the excuses used with the table *
* from the input file. *
******************************************************************
01 TABLE-EXCUSES-1.
05 PIC X(51)
VALUE "JOHN CONVINCE ME TO CONVERT TO LINUX".
05 PIC X(51)
VALUE "BEACUSE OF SECURITY REASON I CAN'T CONFIRM NOR DENY".
05 PIC X(51)
VALUE "BECAUSE THE HOSPITAL DOESN'T HAVE WIFI'".
05 PIC X(51)
VALUE "AFTER INSTALLING LINUX MY SYSTEM CRASHED".
05 PIC X(51)
VALUE "WHAT WAS THE QUESTION AGAIN".
05 PIC X(51)
VALUE "ARE YOU SURE, I REMEBER TURNING IT IN".
05 PIC X(51)
VALUE "I'M INVOKING MY 5TH AMENDMENT RIGHT".
05 PIC X(51)
VALUE "LINUX MADE ME CRAZY I THREW MY COMPUTER".
05 PIC X(51)
VALUE "SOMEONE STOLED MY BACKPACK".
05 PIC X(51)
VALUE "BEACUSE OF SECURITY REASON I CAN'T CONFIRM NOR DENY".
01 TABLE-EXCUSES-2 REDEFINES TABLE-EXCUSES-1.
05 TEN-EXCUSES OCCURS 10 TIMES PIC X(51).
01 TABLE-EXCUSES-COUNTER.
05 TABLE-EXCUSES-COUNT OCCURS 10 TIMES PIC 9(03).
PROCEDURE DIVISION.
******************************************************************
* Finally - where the real work gets done *
* it is divided into paragraphs (or modules) generally called *
* from the main controlling module (here 1000-MAIN-CONTROL). *
* 1000-Main be the control module, *
* 2000-Initialize *
* 3000-Process *
* 4000-Finish *
******************************************************************
1000-MAIN.
OPEN INPUT INPUT-FILE
OUTPUT REPORT-FILE, ERROR-FILE
PERFORM 2000-INITIALIZE
PERFORM UNTIL AT-WS-END-OF-FILE
READ INPUT-FILE
AT END MOVE "Y" TO WS-END-OF-FILE
NOT AT END PERFORM 3000-PROCESS
END-READ
END-PERFORM
PERFORM 4000-FINISH
VARYING WS-EXCUSE
FROM 1 BY 1
UNTIL WS-EXCUSE > 10
MOVE WS-MOST-USED-EXCUSE TO DTMU-HIGH
MOVE WS-EXCUSE-TOTAL TO DT-TOTAL
WRITE REPORT-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM DETAIL-TOTAL
WRITE REPORT-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM DETAIL-TOTAL-MOST-USED.
CLOSE INPUT-FILE REPORT-FILE ERROR-FILE
STOP RUN.
2000-INITIALIZE.
INITIALIZE WS-EXCUSE
INITIALIZE TABLE-EXCUSES-COUNTER
WRITE ERROR-RECORD FROM HEADING-LINE-2
WRITE ERROR-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM HEADING-LINE-1
WRITE REPORT-RECORD FROM BLANK-LINE.
3000-PROCESS.
MOVE "N" TO WS-INVALID-RECORD
ADD 1 TO WS-LINE-NUMBER
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF.
IF WS-INVALID-RECORD = "N"
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER IS NUMERIC
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF.
IF WS-INVALID-RECORD = "Y"
WRITE ERROR-RECORD FROM DETAIL-LINE-ERROR-1
WRITE ERROR-RECORD FROM DETAIL-LINE-ERROR-2
MOVE SPACES TO DETAIL-LINE-ERROR-1
MOVE SPACES TO DETAIL-LINE-ERROR-2
END-IF.
4000-FINISH.
MOVE WS-EXCUSE TO DL-EXCUSE-NUMBER
MOVE TEN-EXCUSES(WS-EXCUSE) TO DL-EXCUSE-USED
MOVE TABLE-EXCUSES-COUNT(WS-EXCUSE) TO DL-AMOUNT-USED
WRITE REPORT-RECORD FROM DETAIL-LINE
WRITE REPORT-RECORD FROM BLANK-LINE
MOVE SPACES TO DETAIL-LINE.
我的输出如下,然后是它应该是什么。
RECORD IMAGE
3 0r4000700 03
**
12 125999999 12
**
21 125000899 21
**
23 A01001111 23
**
应该是:
RECORD IMAGE
3 0r4000700 03
**
6 074000Q00 06
**
12 125999999 12
**
21 125000899 21
**
23 A01001111 23
**
VALID-EXCUSE 很可能实现为
EXCUSE-NUMBER >= '01' and EXCUSE-NUMBER < '12'
所以在过程 3000-PROCESS 中,我会尝试替换
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF.
和
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER is numeric
and VALID-EXCUSE
continue
else
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
if not NUMBER-TIMES-USED is numeric
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
end-if
同时删除以下内容:
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
此代码完全错误。
还有其他错误,例如
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
应该是
ADD 1 TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
您有两个问题导致记录 3 没有出现正确的错误,而记录 6 根本没有显示为错误。
我缩进了您的代码,以便您更好地了解发生了什么。
像往常一样,编译器不关心,不注意缩进,所以它是为人类准备的。那就去做吧。缩进。通常,您这样做会发现自己的一些错误。
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
IF WS-INVALID-RECORD = "N"
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER IS NUMERIC
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF
如果我们先记录三。
你在 88 上的范围测试(很好用 88s,多做)是这样的,十六进制:
X'3031' through X'3130'.
如果该字段已知为 NUMERIC,这将起作用,但否则,由于数字出现在 ASCII 中的字母之前,所以您不想要的一大堆内容将被视为 "valid"。值 12 被拒绝,因为它们大于 10 (X'3130')。任何以零开头的字母都将被视为有效,任何控制代码或恰好适合大量非数字值的任何剩余值也是如此。
正如 Bruce Martin 指出的那样,在应用该测试之前,您需要知道该字段是 NUMERIC。
IF EXCUSE-NUMBER NUMERIC
AND NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
人类阅读起来有点困难(编译器不介意)。 Bruce 的简化建议(积极检查和 CONTINUE
与 ELSE
以捕获不良数据)是一个很好的建议:
IF ( EXCUSE-NUMBER NUMERIC )
AND ( VALID-EXCUSE )
[all the good data goes here]
CONTINUE
ELSE
[leaving all the bad data here, ie both not numeric and
numeric but not in range]
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
注意:验证数据时需要 NUMERIC-plus-range。一旦您的系统中有良好的数据,范围检查就会起作用 "as expected",因为不会有干扰的非数字数据破坏情节。
您还可以同时针对 EXCUSE-NUMBER 执行两种类型的错误,从而简化以下 IF。
如果您可以在任何一个字段中有一个前导空白,您需要在任何检查之前处理它。您不需要使用 INSPECT
。
对于两个字节的字段,只需重新定义,这样您就可以为整个字段指定一个字母数字名称,第一个字节指定一个名称。将 88 放在值为 space 的那些上。如果 88 为真,则将其设置为零(整个字段或字节,两次测试):
IF 88-level
MOVE ZERO TO name-you've-given
END-IF
至此,记录三被视为有效。现在它进入了你的 nested-IF
。它的 EXCUSE-NUMBER 不是 NUMERIC,所以点击 ELSE
,您在其中对第二个字段进行了编码。因为你没有缩进,所以被遮住了。
记录三已被拒绝 "by accident"。
在嵌套的 IF 中,您打算检查 NUMBER-TIMES-USED
的 NUMERIC。
这就解释了为什么记录 6 没有显示为错误,因为唯一的错误是 NUMBER-TIMES-USED 不是 NUMERIC,您的程序目前没有注意到这一点。
您还错误地添加了 EXCUSE-NUMBER 而不是 NUMBER-TIMES-USED。
IF WS-INVALID-RECORD = "N"
[stuff for leading space]
IF NUMBER-TIMES-USED IS NUMERIC
ADD NUMBER-TIMES-USED TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF
请注意 TABLE-EXCUSES-COUNT
的大小大于 WS-MOST-USED-EXCUSE
的大小。如果你一直这样,当你有超过 99 个相同类型的借口时,你会得到意想不到的行为。
你的nested-IF有点曲折,有些重复。这里有一些简化:
IF ( EXCUSE-NUMBER NUMERIC )
AND ( VALID-EXCUSE )
PERFORM CHECK-NUMBER-TIMES-USED
ELSE
PERFORM SET-STANDARD-REJECTION
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
...
CHECK-NUMBER-TIMES-USED.
IF 88-level-first-byte-space
MOVE ZERO TO name-you've-given-the-first-byte
END-IF
IF 88-level-field-space
MOVE ZERO TO field
END-IF
IF NUMBER-TIMES-USED IS NUMERIC
ADD NUMBER-TIMES-USED TO TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
WS-EXCUSE-TOTAL
PERFORM CHECK-HIGHEST-EXCUSE-COUNT
ELSE
PERFORM SET-STANDARD-REJECTION
MOVE ALL "*" TO DLE-EXCUSE
END-IF
SET-STANDARD-REJECTION.
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
.
CHECK-HIGHEST-EXCUSE-COUNT.
IF TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
GREATER THAN WS-COUNT-OF-MOST-USED
MOVE TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
TO WS-COUNT-OF-MOST-USED
MOVE EXCUSE-NUMBER TO WS-EXCUSE
END-IF
.
当你得到总数时,至少还有一个简化,但看看结果如何。
编写了我的程序,但我无法获得所需的正确输出 下面是我的代码和我的输出输入。
还有我的程序程序是否有意义,是否应该修改它,似乎是有意义的,但看了不同的书,我不再确定了。
FD INPUT-FILE.
01 INPUT-RECORD.
05 EXCUSE-NUMBER PIC 9(02).
88 VALID-EXCUSE VALUE 1 THRU 10.
05 FILLER PIC X(03).
05 NUMBER-TIMES-USED PIC 9(02).
05 FILLER PIC X(73).
FD REPORT-FILE.
01 REPORT-RECORD PIC X(80).
FD ERROR-FILE.
01 ERROR-RECORD PIC X(80).
WORKING-STORAGE SECTION.
******************************************************************
* DEFINES PROCESSINGVARIABLES AND OUTPUT LINES *
******************************************************************
01 WS-AREA.
05 WS-IF-STATUS PIC X(02).
05 WS-OF-STATUS PIC X(02).
05 WS-EF-STATUS PIC X(02).
05 WS-END-OF-FILE PIC X(01) VALUE "N".
88 AT-WS-END-OF-FILE VALUE "Y".
05 WS-INVALID-RECORD PIC X(01) VALUE "N".
05 WS-LINE-NUMBER PIC 9(03) VALUE 0.
05 WS-MOST-USED-EXCUSE PIC 9(02) VALUE 0.
05 WS-EXCUSE PIC 9(02) VALUE 0.
05 WS-EXCUSE-TOTAL PIC 9(04).
01 BLANK-LINE.
05 PIC X(80).
******************************************************************
* (THIS IS WHERE THE HEADING ON THE PRINT OUT SHEET GOES) *
******************************************************************
01 HEADING-LINE-1.
05 FILLER PIC X(14) VALUE SPACES.
05 FILLER PIC X(37)
VALUE "TEN MOST OUTRAGEOUS HOME-WORK EXCUSES".
01 HEADING-LINE-2.
05 FILLER PIC X(11).
05 FILLER PIC X(06) VALUE "RECORD".
05 FILLER PIC X(08).
05 FILLER PIC X(05) VALUE "IMAGE".
******************************************************************
* DETAIL-LINE COMMENTS. *
* on the detail line we are writing out the Data information *
* in particular, when we write out the line-number, error *
* excuse number, excuses used, and how many times used *
* Detail summary will be reported out *
* Stars will be Display underneath bad data. *
*****************************************************************
01 DETAIL-LINE.
05 FILLER PIC X(03).
05 DL-EXCUSE-NUMBER PIC 9(02).
05 FILLER PIC X(03).
05 DL-EXCUSE-USED PIC X(51).
05 FILLER PIC X(03).
05 DL-AMOUNT-USED PIC ZZ9.
01 DETAIL-LINE-ERROR-1.
05 FILLER PIC X(08) VALUE SPACES.
05 DLE-LINE-NUMBER PIC ZZ9.
05 FILLER PIC X(09) VALUE SPACES.
05 DLE-ERROR PIC X(16).
01 DETAIL-LINE-ERROR-2.
05 FILLER PIC X(20) VALUE SPACES.
05 DLE-EXCUSE-NUMBER PIC X(02) VALUE SPACES.
05 FILLER PIC X(03) VALUE SPACES.
05 DLE-EXCUSE PIC X(02) VALUE SPACES.
01 DETAIL-TOTAL.
05 FILLER PIC X(41) VALUE SPACES.
05 FILLER PIC X(20)
VALUE "TOTAL EXCUSES USED =".
05 DT-TOTAL PIC ZZZ9 VALUE ZERO.
01 DETAIL-TOTAL-MOST-USED.
05 FILLER PIC X(34) VALUE SPACES.
05 FILLER PIC X(27)
VALUE "EXCUSE USE THE MOST TIMES =".
05 DTMU-HIGH PIC ZZZ9.
******************************************************************
* This is where we hard code the excuses used with the table *
* from the input file. *
******************************************************************
01 TABLE-EXCUSES-1.
05 PIC X(51)
VALUE "JOHN CONVINCE ME TO CONVERT TO LINUX".
05 PIC X(51)
VALUE "BEACUSE OF SECURITY REASON I CAN'T CONFIRM NOR DENY".
05 PIC X(51)
VALUE "BECAUSE THE HOSPITAL DOESN'T HAVE WIFI'".
05 PIC X(51)
VALUE "AFTER INSTALLING LINUX MY SYSTEM CRASHED".
05 PIC X(51)
VALUE "WHAT WAS THE QUESTION AGAIN".
05 PIC X(51)
VALUE "ARE YOU SURE, I REMEBER TURNING IT IN".
05 PIC X(51)
VALUE "I'M INVOKING MY 5TH AMENDMENT RIGHT".
05 PIC X(51)
VALUE "LINUX MADE ME CRAZY I THREW MY COMPUTER".
05 PIC X(51)
VALUE "SOMEONE STOLED MY BACKPACK".
05 PIC X(51)
VALUE "BEACUSE OF SECURITY REASON I CAN'T CONFIRM NOR DENY".
01 TABLE-EXCUSES-2 REDEFINES TABLE-EXCUSES-1.
05 TEN-EXCUSES OCCURS 10 TIMES PIC X(51).
01 TABLE-EXCUSES-COUNTER.
05 TABLE-EXCUSES-COUNT OCCURS 10 TIMES PIC 9(03).
PROCEDURE DIVISION.
******************************************************************
* Finally - where the real work gets done *
* it is divided into paragraphs (or modules) generally called *
* from the main controlling module (here 1000-MAIN-CONTROL). *
* 1000-Main be the control module, *
* 2000-Initialize *
* 3000-Process *
* 4000-Finish *
******************************************************************
1000-MAIN.
OPEN INPUT INPUT-FILE
OUTPUT REPORT-FILE, ERROR-FILE
PERFORM 2000-INITIALIZE
PERFORM UNTIL AT-WS-END-OF-FILE
READ INPUT-FILE
AT END MOVE "Y" TO WS-END-OF-FILE
NOT AT END PERFORM 3000-PROCESS
END-READ
END-PERFORM
PERFORM 4000-FINISH
VARYING WS-EXCUSE
FROM 1 BY 1
UNTIL WS-EXCUSE > 10
MOVE WS-MOST-USED-EXCUSE TO DTMU-HIGH
MOVE WS-EXCUSE-TOTAL TO DT-TOTAL
WRITE REPORT-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM DETAIL-TOTAL
WRITE REPORT-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM DETAIL-TOTAL-MOST-USED.
CLOSE INPUT-FILE REPORT-FILE ERROR-FILE
STOP RUN.
2000-INITIALIZE.
INITIALIZE WS-EXCUSE
INITIALIZE TABLE-EXCUSES-COUNTER
WRITE ERROR-RECORD FROM HEADING-LINE-2
WRITE ERROR-RECORD FROM BLANK-LINE
WRITE REPORT-RECORD FROM HEADING-LINE-1
WRITE REPORT-RECORD FROM BLANK-LINE.
3000-PROCESS.
MOVE "N" TO WS-INVALID-RECORD
ADD 1 TO WS-LINE-NUMBER
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF.
IF WS-INVALID-RECORD = "N"
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER IS NUMERIC
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF.
IF WS-INVALID-RECORD = "Y"
WRITE ERROR-RECORD FROM DETAIL-LINE-ERROR-1
WRITE ERROR-RECORD FROM DETAIL-LINE-ERROR-2
MOVE SPACES TO DETAIL-LINE-ERROR-1
MOVE SPACES TO DETAIL-LINE-ERROR-2
END-IF.
4000-FINISH.
MOVE WS-EXCUSE TO DL-EXCUSE-NUMBER
MOVE TEN-EXCUSES(WS-EXCUSE) TO DL-EXCUSE-USED
MOVE TABLE-EXCUSES-COUNT(WS-EXCUSE) TO DL-AMOUNT-USED
WRITE REPORT-RECORD FROM DETAIL-LINE
WRITE REPORT-RECORD FROM BLANK-LINE
MOVE SPACES TO DETAIL-LINE.
我的输出如下,然后是它应该是什么。
RECORD IMAGE
3 0r4000700 03
**
12 125999999 12
**
21 125000899 21
**
23 A01001111 23
**
应该是:
RECORD IMAGE
3 0r4000700 03
**
6 074000Q00 06
**
12 125999999 12
**
21 125000899 21
**
23 A01001111 23
**
VALID-EXCUSE 很可能实现为
EXCUSE-NUMBER >= '01' and EXCUSE-NUMBER < '12'
所以在过程 3000-PROCESS 中,我会尝试替换
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF.
和
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER is numeric
and VALID-EXCUSE
continue
else
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
if not NUMBER-TIMES-USED is numeric
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
end-if
同时删除以下内容:
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
此代码完全错误。
还有其他错误,例如
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
应该是
ADD 1 TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
您有两个问题导致记录 3 没有出现正确的错误,而记录 6 根本没有显示为错误。
我缩进了您的代码,以便您更好地了解发生了什么。
像往常一样,编译器不关心,不注意缩进,所以它是为人类准备的。那就去做吧。缩进。通常,您这样做会发现自己的一些错误。
IF NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
IF WS-INVALID-RECORD = "N"
INSPECT EXCUSE-NUMBER REPLACING LEADING SPACES BY ZERO
IF EXCUSE-NUMBER IS NUMERIC
ADD EXCUSE-NUMBER TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF
如果我们先记录三。
你在 88 上的范围测试(很好用 88s,多做)是这样的,十六进制:
X'3031' through X'3130'.
如果该字段已知为 NUMERIC,这将起作用,但否则,由于数字出现在 ASCII 中的字母之前,所以您不想要的一大堆内容将被视为 "valid"。值 12 被拒绝,因为它们大于 10 (X'3130')。任何以零开头的字母都将被视为有效,任何控制代码或恰好适合大量非数字值的任何剩余值也是如此。
正如 Bruce Martin 指出的那样,在应用该测试之前,您需要知道该字段是 NUMERIC。
IF EXCUSE-NUMBER NUMERIC
AND NOT VALID-EXCUSE
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
人类阅读起来有点困难(编译器不介意)。 Bruce 的简化建议(积极检查和 CONTINUE
与 ELSE
以捕获不良数据)是一个很好的建议:
IF ( EXCUSE-NUMBER NUMERIC )
AND ( VALID-EXCUSE )
[all the good data goes here]
CONTINUE
ELSE
[leaving all the bad data here, ie both not numeric and
numeric but not in range]
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
注意:验证数据时需要 NUMERIC-plus-range。一旦您的系统中有良好的数据,范围检查就会起作用 "as expected",因为不会有干扰的非数字数据破坏情节。
您还可以同时针对 EXCUSE-NUMBER 执行两种类型的错误,从而简化以下 IF。
如果您可以在任何一个字段中有一个前导空白,您需要在任何检查之前处理它。您不需要使用 INSPECT
。
对于两个字节的字段,只需重新定义,这样您就可以为整个字段指定一个字母数字名称,第一个字节指定一个名称。将 88 放在值为 space 的那些上。如果 88 为真,则将其设置为零(整个字段或字节,两次测试):
IF 88-level
MOVE ZERO TO name-you've-given
END-IF
至此,记录三被视为有效。现在它进入了你的 nested-IF
。它的 EXCUSE-NUMBER 不是 NUMERIC,所以点击 ELSE
,您在其中对第二个字段进行了编码。因为你没有缩进,所以被遮住了。
记录三已被拒绝 "by accident"。
在嵌套的 IF 中,您打算检查 NUMBER-TIMES-USED
的 NUMERIC。
这就解释了为什么记录 6 没有显示为错误,因为唯一的错误是 NUMBER-TIMES-USED 不是 NUMERIC,您的程序目前没有注意到这一点。
您还错误地添加了 EXCUSE-NUMBER 而不是 NUMBER-TIMES-USED。
IF WS-INVALID-RECORD = "N"
[stuff for leading space]
IF NUMBER-TIMES-USED IS NUMERIC
ADD NUMBER-TIMES-USED TO TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
IF TABLE-EXCUSES-COUNT(EXCUSE-NUMBER) >
WS-MOST-USED-EXCUSE
MOVE TABLE-EXCUSES-COUNT(EXCUSE-NUMBER)
TO WS-MOST-USED-EXCUSE
END-IF
ADD NUMBER-TIMES-USED TO WS-EXCUSE-TOTAL
ELSE
MOVE "Y" TO WS-INVALID-RECORD
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE INPUT-RECORD TO DLE-ERROR
MOVE ALL "*" TO DLE-EXCUSE
END-IF
END-IF
请注意 TABLE-EXCUSES-COUNT
的大小大于 WS-MOST-USED-EXCUSE
的大小。如果你一直这样,当你有超过 99 个相同类型的借口时,你会得到意想不到的行为。
你的nested-IF有点曲折,有些重复。这里有一些简化:
IF ( EXCUSE-NUMBER NUMERIC )
AND ( VALID-EXCUSE )
PERFORM CHECK-NUMBER-TIMES-USED
ELSE
PERFORM SET-STANDARD-REJECTION
MOVE ALL "*" TO DLE-EXCUSE-NUMBER
END-IF
...
CHECK-NUMBER-TIMES-USED.
IF 88-level-first-byte-space
MOVE ZERO TO name-you've-given-the-first-byte
END-IF
IF 88-level-field-space
MOVE ZERO TO field
END-IF
IF NUMBER-TIMES-USED IS NUMERIC
ADD NUMBER-TIMES-USED TO TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
WS-EXCUSE-TOTAL
PERFORM CHECK-HIGHEST-EXCUSE-COUNT
ELSE
PERFORM SET-STANDARD-REJECTION
MOVE ALL "*" TO DLE-EXCUSE
END-IF
SET-STANDARD-REJECTION.
MOVE INPUT-RECORD TO DLE-ERROR
MOVE WS-LINE-NUMBER TO DLE-LINE-NUMBER
MOVE "Y" TO WS-INVALID-RECORD
.
CHECK-HIGHEST-EXCUSE-COUNT.
IF TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
GREATER THAN WS-COUNT-OF-MOST-USED
MOVE TABLE-EXCUSES-COUNT ( EXCUSE-NUMBER )
TO WS-COUNT-OF-MOST-USED
MOVE EXCUSE-NUMBER TO WS-EXCUSE
END-IF
.
当你得到总数时,至少还有一个简化,但看看结果如何。