Here are some suggestions ...
Use a hierarchical record structure to view data in different ways. For instance:
01 ITEM-REC. 05 ITEM-CODE. 10 ITEM-NUM-CODE PIC 9(3). 10 ITEM-CHAR-CODE PIC A(3). 88 ITEM-TYPE-A VALUE 'AAA' THRU 'AZZ'. 88 ITEM-TYPE-B VALUE 'BAA' THRU 'BZZ'. 05 QUANTITY PIC 9(4).
ITEM-CODE is a field of symbol group 6, the first part of which is numeric (ITEM-NUMBER CODE), and the last part is alphabetic (ITEM-CHAR -CODE). You can reference any of these three variables in your program. When you access ITEM-CODE or any other member of a group, COBOL processes the variable as if it were declared as PIC X This means that you can MOVE anything in it without raising errors. For instance:
MOVE 'ABCdef' TO ITEM-CODE
or
MOVE 'ABCdef0005' TO ITEM-REC
None of them can cause an error, even if the ITEM-NUM-CODE elementary data element is definitely not a number. To check the validity of your data after a group move, you must check each elementary data element separately (except you know for sure that data type errors could not occur). There are many ways to do this. For example, if a data item must be numeric, the following will work:
IF ITEM-NUM-CODE IS NUMERIC CONTINUE ELSE DISPLAY 'ITEM-NUM-CODE IS NOT NUMERIC' PERFORM BIG-BAD-ERROR END-IF
COBOL provides various class tests that can be applied to a data item. For example: NUMERIC, ALPHABETIC AND ALPHABETIC are commonly used.
Another common way to test ranges of values ββis to define different 88 levels - but exercise caution. In the above Example, ITEM-TYPE-A is level 88, which defines the data range from βAAAβ to βAZZβ based on the current sort sequence. To make sure that ITEM-CHAR-CODE contains only letter symbols and the first letter is βAβ or βBβ, you can do something like:
IF ITEM-CHAR-CODE ALPHABETIC DISPLAY 'ITEM-CHAR-CODE is alphabetic.' EVALUATE TRUE WHEN ITEM-TYPE-A DISPLAY 'ITEM-CHAR-CODE is in range AAA through AZZ' WHEN ITEM-TYPE-B DISPLAY 'ITEM-CHAR-CODE is in range BAA through BZZ' WHEN OTHER DISPLAY 'ITEM-CHAR-CODE is in some other range' END-EVALUATE ELSE DISPLAY 'ITEM-CHAR-CODE is not alphabetic' END-IF
Check out the separate test for ALPHABETIC above. Why does this happen when level 88 tests could do the job? In fact, 88 are not sufficient, as they cover the entire range from AAA to AZZ based on the sorting sequence currently in effect. In an environment based on EBCDIC (a very large number of COBOL stores use EBCDIC), this captures values ββsuch as A}\ . The closing and backslash characters are not alpha, but fall in the middle of the range βAβ to βZβ (what the * * @!)? Also note that this value is because "aaa" does not satisfy the ITEM-TYPE-A condition, because lowercase letters go beyond a certain range. It may be time to check the EBCDIC character table.
Finally, you can count the number of occurrences of a character or character string in a variable with the verb INSPECT as follows:
INSPECT ITEM-CODE TALLING DASH-COUNT FOR ALL '-'
DASH-COUNT must be a numeric element and contain the number of characters in ITEM-CODE . INSPECT verb is not so useful if you want to count the number of digits. To do this, you will need one operator for each digit.
It may be easier to just code the loop like this:
PERFORM VARYING I FROM 1 BY 1 UNTIL I > LENGTH OF ITEM-CODE EVALUATE ITEM-CODE(I:1) WHEN '-' COMPUTE DASH-COUNT = DASH-COUNT + 1 WHEN '0' THRU '9' COMPUTE DIGIT-COUNT = DIGIT-COUNT + 1 WHEN OTHER COMPUTE OTHER-COUNT = OTHER-COUNT + 1 END-EVALUATE END-PERFORM
Now ask yourself, why was it convenient for me to use a range check from zero to 9? Hint: look at the sort sequence.
Hope this helps.