开发者

Data Verification in COBOL

I am in the last course I will have for COBOL in college, and I have to write interacting programs that are supposed to keep track of inventory for a business. I have reached a few parts that I am having problems with. The first is verifying that the date is between the years 2011 and 2012, and the second is that the month and day numbers are between 1-12 and 1-31, respectively. When I run my program, it always says in the error report that the year is wrong, even when I put it in right. Here is my code for that part:

   WORKING-STORAGE SECTION.
       05  POLI-DATE-REQUESTED-S.
           10 POLI-DATE-REQUESTED-S-1  PIC XX.
           10 POLI-DATE-REQUESTED-S-2  PIC XX.
           10 POLI-DATE-REQUESTED-S-3  PIC XX.
           10 POLI-DATE-REQUESTED-S-4  PIC XX.

   SCREEN SECTION.
   01  SCREEN-IMAGE.
       05  BLANK SCREEN
           BACKGROUND-COLOR 0.
       05  LINE 02  COLUMN 02          PIC X(8)
               FROM TIME-HHMMSSXX-COLONS
               FOREGROUND-COLOR 15.
       05  LINE 02  COLUMN 25
               VALUE 'Purchase Order Line Item Maintenance'
               FOREGROUND-COLOR 14.
       05  LINE 02  COLUMN 70          PIC X(8)
               FROM DATE-MMDDYY-SLASHES
               FOREGROUND-COLOR 15.
       05  LINE 04  COLUMN 02  VALUE 'FUNCTION CODE:'
               FOREGROUND-COLOR 10.
       05  LINE 04  COLUMN 18          PIC X(3)
               USING FUNCTION-CODE-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 04  COLUMN 23  VALUE '(ADD, CHG, DEL, INQ, END)'
               FOREGROUND-COLOR 11.
       05  LINE 07  COLUMN 23  VALUE 'NUMBER:'
               FOREGROUND-COLOR 10.
       05  LINE 07  COLUMN 50          PIC X(4)
               USING POLI-VEND-NUMBER-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 08  COLUMN 23  VALUE 'ORDER ID:'
               FOREGROUND-COLOR 10.
       05  LINE 08  COLUMN 50          PIC X(8)
               USING POLI-ORDER-ID-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 09  COLUMN 23  VALUE 'LINE ITEM:'
               FOREGROUND-COLOR 10.
       05  LINE 09  COLUMN 50          PIC X(4)
               USING POLI-LINE-ITEM-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 10  COLUMN 23  VALUE 'ITEM ID:'
               FOREGROUND-COLOR 10.
       05  LINE 10  COLUMN 50          PIC X(10)
               USING POLI-ITEM-ID-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 11  COLUMN 23  VALUE 'QUANTITY:'
               FOREGROUND-COLOR 10.
       05  LINE 11  COLUMN 50          PIC X(5)
               USING POLI-QUANTITY-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 12  COLUMN 23  VALUE 'DATE REQUESTED (YYYYMMDD):'
               FOREGROUND-COLOR 10.
       05  LINE 12  COLUMN 50          PIC X(8)
               USING POLI-DATE-REQUESTED-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 13  COLUMN 23  VALUE 'QUOTED COST:'
               FOREGROUND-COLOR 10.
       05  LINE 13  COLUMN 50          PIC X(7)
               USING POLI-QUOTED-COST-S
               FOREGROUND-COLOR 15 AUTO.
       05  LINE 17  COLUMN 23  VALUE 'DATE ADDED:'
               FOREGROUND-COLOR 10.
       05  LINE 17  COLUMN 40  PIC X(10)
               USING POLI-DATE-ADDED-S
               FOREGROUND-COLOR 15.
       05  LINE 18  COLUMN 23  VALUE 'DATE-CHANGED:'
               FOREGROUND-COLOR 10.
       05  LINE 18  COLUMN 40  PIC X(10)
               USING POLI-DATE-CHANGED-S
               FOREGROUND-COLOR 15.
       05  LINE 23  COLUMN 23  PIC X(55)
               FROM ERROR-MESSAGE-S
               FOREGROUND-COLOR 12.

   PROCEDURE DIVISION.
   900-VALIDATE-THE-FIELDS.
       IF POLI-DATE-REQUESTED-S-1 IS NOT = 20
           MOVE 'Year must be 2011 OR 2012' TO ERROR-MESSAGE-S
           GO TO 999-EXIT
       END-IF
       IF POLI-DATE-REQUESTED-S-2 IS NOT = 11 OR 12
           MOVE 'Year Must Be 2011 Or 2012' TO ERROR-MESSAGE-S
           GO TO 999-EXIT
       END-IF
     开发者_运维技巧  IF POLI-DATE-REQUESTED-S-3 IS < 1 OR > 12
           MOVE 'Month Must Be 1 Through 12' TO ERROR-MESSAGE-S
           GO TO 999-EXIT
       END-IF
       IF POLI-DATE-REQUESTED-S-4 IS < 1 OR > 31
           MOVE 'Day Must Be 1 Through 31' TO ERROR-MESSAGE-S
           GO TO 999-EXIT
       END-IF.

Also, I have to make sure that a record in a field called POLI-ITEM-ID already exists in another indexed file called ITEM-MASTER. I am not exactly sure how to do this, but I assume that it involves temporarily opening the file and searching it. If anyone could show me how to do this I would be grateful, as these two things seem to be the only things holding me back today. I thank everyone for all the help in advance.

Edit: The input data is written on a screen image that is part of the program. Thus I know that what I put in in correct at the time of entry. If it helps, I have put the SCREEN SELECTION in the code, but I do not think it has any bearing on why my date entry is considered an error (i.e. I put in "2011" and it tells me on the screen "Year must be 2011 OR 2012").


   05  POLI-DATE-REQUESTED-S.
       10 POLI-DATE-REQUESTED-S-1  PIC 9999.
          88 Year-Valid            value 2011 thru 2012.
       10 POLI-DATE-REQUESTED-S-2  PIC 99.
          88 Month-Valid           value 01 thru 12.
       10 POLI-DATE-REQUESTED-S-4  PIC 99.              
          88 Day-Valid             value 01 thru 31.

Try redefining your fields like this. Then you can do a simple test of the fields with:

  IF not Year-Valid
       MOVE 'Year must be 2011 OR 2012' TO ERROR-MESSAGE-S
  Else
       IF not Month-Valid
          MOVE 'Month Must Be 1 Through 12' TO ERROR-MESSAGE-S
       Else
          IF not Day-Valid
              MOVE 'Day Must Be 1 Through 31' TO ERROR-MESSAGE-S
          END-IF
       END-IF
  END-IF

To deal with your lookup, do a direct read on the ITEM-MASTER file. That will involve something like this:

   SELECT ITEM-MASTER ASSIGN TO "fname.txt"
      ORGANIZATION IS INDEXED
      ACCESS MODE IS DYNAMIC
      RECORD KEY IS ITEM-MASTER-KEY.

and then do a direct read:

  READ ITEM-MASTER
     KEY IS POLI-ITEM-ID
     INVALID KEY  DISPLAY "error or something"
  END-READ


Be careful - the accepted solution does not guarantee numeric values. The following program illustrates the point:

   PROGRAM-ID. EXAMPLE.                       
   DATA DIVISION.                             
   WORKING-STORAGE SECTION.                   
   01  TXT-VALUE        PIC X(4).             
   01  NUM-VALUE        PIC 9(4).             
       88 WS-VALID-NUM  VALUE  2000 THRU 2999.
   PROCEDURE DIVISION.                        
       MOVE '21b1' TO TXT-VALUE               
       MOVE TXT-VALUE TO NUM-VALUE            
       DISPLAY 'NUM-VALUE: ' NUM-VALUE        
       IF WS-VALID-NUM                        
          DISPLAY 'passed the range test.'    
       END-IF                                 
       IF NUM-VALUE IS NUMERIC                
          DISPLAY 'passed numeric test.'      
       ELSE                                   
          DISPLAY 'failed numeric test.'      
       END-IF                                 

Which results in the following output:

NUM-VALUE: 21b1       
passed the range test.
failed numeric test.  

Lesson: Always validate numeric fields with an IS NUMERIC test and then a range test.

Furthermore, unless input data have been pre-edited for validity, it is not a good idea to read external data directly into numeric data types. Reading '1b' from an input file directly into a PIC 9(2) data item yields the value 12 (in an ebcdic based environment). This will now pass an IS NUMERIC test as well as range tests even though the actual input data were not numeric. The reasons for the "automatic" conversion are a bit beyond this discussion - lets just say data movement rules in COBOL are much more complex than most people appreciate.


Joe Zitzelberger's post is the recommended and 'clean' way to do this.

I would just point out that the error in your original code was to mix up XX and numeric types. You should either have used character literals in your tests:

IF POLI-DATE-REQUESTED-S-1 IS NOT = '20'

or, better, defined your data values as numbers:

 10 POLI-DATE-REQUESTED-S-1  PIC 99.


01  FILLER. 
05  POLI-DATE-REQUESTED-S. 
    10  POLI-DATE-REQUESTED-S-1  PIC XXXX. 
        88  YEAR-VALID            VALUE "2011" THRU "2012". 
    10  POLI-DATE-REQUESTED-S-2  PIC XX. 
        88  MONTH-VALID           VALUE "01" THRU "12". 
        88  MONTH-IS-FEB          VALUE "02". 
        88  MONTH-IS-30-DAYS      VALUE "04" "06" "09" "11".
    10  POLI-DATE-REQUESTED-S-4  PIC XX. 
        88  DAY-MAY-BE-VALID      VALUE "01" THRU "31". 
        88  VALID-FEB-DAYS        VALUE "01" THRU "28". 
        88  VALID-30-DAYS         VALUE "01" THRU "30". 

Then the "first cut", with a student who doesn't have to worry about the actual number of days a month has:

MOVE SPACE                   TO ERROR-MESSAGE-S
EVALUATE TRUE 
  WHEN NOT POLI-DATE-REQUESTED-S NUMERIC 
      MOVE 'DATE MUST ONLY BE NUMBERS' 
                             TO ERROR-MESSAGE-S
  WHEN NOT YEAR-VALID 
    MOVE 'YEAR MUST BE 2011 OR 2012' 
                             TO ERROR-MESSAGE-S
  WHEN NOT MONTH-VALID 
    MOVE 'MONTH MUST BE 01 THROUGH 12' 
                             TO ERROR-MESSAGE-S
  WHEN NOT DAY-MAY-BE-VALID 
    MOVE "DAY IS ZERO OR MORE THAN 31" 
                             TO ERROR-MESSAGE-S
END-EVALUATE 

And then amended later for the actual number of days.

MOVE SPACE                   TO ERROR-MESSAGE-S
EVALUATE TRUE 
  WHEN NOT POLI-DATE-REQUESTED-S NUMERIC 
      MOVE 'DATE MUST ONLY BE NUMBERS' 
                             TO ERROR-MESSAGE-S
  WHEN NOT YEAR-VALID 
    MOVE 'YEAR MUST BE 2011 OR 2012' 
                             TO ERROR-MESSAGE-S
  WHEN NOT MONTH-VALID 
    MOVE 'MONTH MUST BE 01 THROUGH 12' 
                             TO ERROR-MESSAGE-S
  WHEN NOT DAY-MAY-BE-VALID 
    MOVE "DAY IS ZERO OR MORE THAN 31" 
                             TO ERROR-MESSAGE-S
  WHEN ( MONTH-IS-FEB 
       AND NOT VALID-FEB-DAYS ) 
   MOVE 'TOO MANY DAYS FOR FEBRUARY' 
                             TO ERROR-MESSAGE-S
  WHEN ( MONTH-IS-30-DAYS 
       AND NOT VALID-30-DAYS ) 
   MOVE 'NO 31ST THIS MONTH' 
                             TO ERROR-MESSAGE-S
END-EVALUATE 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜