Compaq COBOL
User Manual


Previous Contents Index

5.3.5.4 Interference in Tally Argument Lists

When several tally arguments contain one or more identical characters active at the same time, they may interfere with each other, so that when one of the arguments finds a match, the scanner steps past any other matching characters, preventing those characters from being considered for a match.

The following two identical tally arguments do not interfere with each other because they are not active at the same time. The first A in FIELD1 causes the first argument to become inactive and the second argument to become active:


MOVE 0 TO T1 T2. 
INSPECT FIELD1 TALLYING 
        T1 FOR ALL "," BEFORE "A" 
        T2 FOR ALL "," AFTER "A". 

However, the next identical tally arguments interfere with each other since both are active at the same time:


INSPECT FIELD1 TALLYING 
        T1 FOR ALL "," 
        T2 FOR ALL "," AFTER "A". 

For any given position of the scanner, the arguments are applied to FIELD1 in the order in which they appear in the statement. When one of them finds a match, the scanner moves to the next position and ignores the remaining arguments in the argument list. Each comma in FIELD1 causes T1 to be incremented by 1 and the second argument to be ignored. Thus, T1 always contains an accurate count of all the commas in FIELD1, and T2 is always unchanged.

The following INSPECT statement arguments only partially interfere with each other:


INSPECT FIELD1 TALLYING 
        T2 FOR ALL "," AFTER "A" 
        T1 FOR ALL ",". 

The first argument does not become active until the scanner encounters an A. The second argument tallies all commas that precede the A. After the A, the first argument counts all commas and causes the second argument to be ignored. Thus, T1 contains the number of commas that precede the first A, and T2 contains the number of commas that follow the first A. This statement works well as written, but it could be difficult to debug.

The following three examples show that one INSPECT statement cannot count any character more than once. Thus, when you use the same character in more than one argument of an argument list, consider the possibility of interference and choose the order of the arguments carefully. The solution may require two or more INSPECT statements. Consider the following problem:


INSPECT FIELD1 TALLYING 
        T1 FOR ALL "AB" 
        T2 FOR ALL "BC". 

If FIELD1 contains ABCABC after the scan, T1 is incremented by 2, and T2 is unaltered. The successful matching of the argument includes each B in the item. Each match resets the scanner to the character position to the right of the B, so that the second argument is never successfully matched. The results remain the same even if the order of the arguments is reversed. Only separate INSPECT statements can develop the desired counts.

Sometimes you can use the interference characteristics of the INSPECT statement to your advantage. Consider the following sample argument list:


MOVE 0 TO T4 T3 T2 T1. 
INSPECT FIELD1 TALLYING 
        T4 FOR ALL "****" 
        T3 FOR ALL "***" 
        T2 FOR ALL "**" 
        T1 FOR ALL "*". 

The argument list counts all of the asterisks in FIELD1 in four different tally counters. T4 counts the number of times that four asterisks occur together; T3 counts the number of times three asterisks appear together; T2 counts double asterisks; and T1 counts singles.

If FIELD1 contains a string of more than four consecutive asterisks, the argument list breaks the string into groups of four and counts them in T4. It then counts the less-than-four remainder in T3, T2, or T1.

Reversing the order of the arguments in this list causes T1 to count all of the asterisks, and T2, T3, and T4 to remain unchanged.

When the LEADING condition is used with an argument in the argument list, that argument becomes inactive as soon as it fails to be matched in the item being inspected. Therefore, when two arguments in an argument list contain one or more identical characters and one of the arguments has a LEADING condition, the argument with the LEADING condition should appear first. Consider the following sample statement:


MOVE 0 TO T1 T2. 
INSPECT FIELD1 TALLYING 
        T1 FOR LEADING "*" 
        T2 FOR ALL "*". 

T1 counts only leading asterisks in FIELD1; the occurrence of any other character causes the first tally argument to become inactive. T2 keeps a count of any remaining asterisks in FIELD1.

Reversing the order of the arguments in the following statement results in an argument list that can never increment T1:


INSPECT FIELD1 TALLYING 
        T2 FOR ALL "*" 
        T1 FOR LEADING "*". 

If the first character in FIELD1 is not an asterisk, neither argument can match it, and the second argument becomes inactive. If the first character in FIELD1 is an asterisk, the first argument matches it and causes the second argument to be ignored. The first character in FIELD1 that is not an asterisk fails to match the first argument, and the second argument becomes inactive because it has not found a match in any of the preceding characters.

An argument with both a LEADING condition and a BEFORE phrase can sometimes successfully delimit the item being inspected, as in the following example:


MOVE 0 TO T1 T2. 
INSPECT FIELD1 TALLYING 
        T1 FOR LEADING SPACES 
        T2 FOR ALL "   " BEFORE "." 
        T2 FOR ALL "  " BEFORE "." 
        T2 FOR ALL " " BEFORE ".". 
IF T2 > 0 ADD 1 TO T2. 

These statements count the number of words in the English statement in FIELD1, assuming that no more than three spaces separate the words in the sentence, that the sentence ends with a period, and that the period immediately follows the last word. When FIELD1 has been scanned, T2 contains the number of spaces between the words. Because a count of the spaces renders a number that is one less than the number of words, the conditional statement adds 1 to the count.

The first argument removes any leading spaces, counting them in a different tally counter. This shortens FIELD1 by preventing the application of the second to the fourth arguments until the scanner finds a nonspace character. The BEFORE phrase on each of the other arguments causes them to become inactive when the scanner reaches the period at the end of the sentence. Thus, the BEFORE phrases shorten FIELD1 by making the second to the fourth arguments inactive before the scanner reaches the rightmost position of FIELD1. If the sentence in FIELD1 is indented with tab characters instead of spaces, a second LEADING argument can count the tab characters. For example:


INSPECT FIELD1 TALLYING 
        T1 FOR LEADING SPACES 
        T1 FOR LEADING TAB 
        T2 FOR ALL "    " 
        . 
        . 
        . 

When an argument list contains a CHARACTERS argument, it should be the last argument in the list. Because the CHARACTERS argument always matches the item, it prevents the application of any arguments that follow in the list. However, as the last argument in an argument list, it can count the remaining characters in the item being inspected. Consider the following example.


MOVE 0 TO T1 T2 T3 T4 T5. 
INSPECT FIELD1 TALLYING 
        T1 FOR LEADING SPACES 
        T2 FOR ALL "." BEFORE "," 
        T3 FOR ALL "+" BEFORE "," 
        T4 FOR ALL "-" BEFORE "," 
        T5 FOR CHARACTERS BEFORE ",". 

If FIELD1 is known to contain a number in the form frequently used to input data, it can contain a plus or minus sign, and a decimal point; furthermore, the number can be preceded by spaces and terminated by a comma. When this statement is compiled and executed, it delivers the following results:

The sum of T1 to T5, plus 1, gives the character position occupied by the terminating comma.

5.3.6 Using the REPLACING Phrase

When an INSPECT statement contains a REPLACING phrase, that statement selectively replaces characters or groups of characters in the designated item.

The REPLACING phrase names a search argument of one or more characters and a condition under which the string can be applied to the item being inspected. Associated with the search argument is the replacement value, which must be the same length as the search argument. Each time the search argument finds a match in the item being inspected, under the condition stated, the replacement value replaces the matched characters.

A BEFORE/AFTER phrase can be used to delimit the area of the item being inspected. A search argument applies only to the delimited area of the item.

5.3.6.1 The Search Argument

The search argument of the REPLACING phrase names a character string and a condition under which the character string should be compared to the delimited string being inspected.

The CHARACTERS form of the search argument specifies that every character in the delimited string being inspected should be considered to match an imaginary character that serves as the search argument. Thus, the replacement value replaces each character in the delimited string. For example:


INSPECT ITEMA REPLACING CHARACTERS ... 

The ALL, LEADING, and FIRST forms of the search argument specify a particular character string, which can be represented by a literal or an identifier. The search argument character string can be any length. However, each character of the argument must match a character in the delimited string before the compiler considers the argument matched. For example:


INSPECT ITEMA REPLACING ALL ... 

The necessary literal and identifier characteristics are as follows:

The words ALL, LEADING, and FIRST supply conditions that further delimit the inspection operation:

5.3.6.2 The Replacement Value

Whenever the search argument finds a match in the item being inspected, the matched characters are replaced by the replacement value. The word BY followed by an identifier or literal specifies the replacement value. For example:


INSPECT ITEMA REPLACING ALL "A" BY "X" ALL "D" BY "X". 

The replacement value must always be the same size as its associated search argument.

If the replacement value is a literal character-string, it must be either a nonnumeric literal or a figurative constant (other than ALL literal). A figurative constant represents as many characters as the length of the search argument requires.

If the replacement value is an identifier, it must be an elementary item of DISPLAY usage. It can be any class. However, if it is not alphanumeric, the compiler conducts an implicit redefinition of the item. This redefinition is the same as the BEFORE/AFTER redefinition discussed in Section 5.3.2.

5.3.6.3 The Replacement Argument

The replacement argument consists of the search argument (with its condition and character-string), the replacement value, and an optional BEFORE/AFTER phrase, as shown in Figure 5-5.

Figure 5-5 The Replacement Argument


5.3.6.4 The Replacement Argument List

One INSPECT...REPLACING statement can contain more than one replacement argument. Several replacement arguments form an argument list, and the manner in which the list is processed affects the action of any given replacement argument.

The following examples show INSPECT statements with replacement argument lists. The text following each one tells how that list will be processed.


INSPECT FIELD1 REPLACING 
        ALL "," BY SPACE 
        ALL "." BY SPACE 
        ALL ";" BY SPACE. 

The previous three replacement arguments all have the same replacement value, SPACE, and are active over the entire item being inspected. The statement replaces all commas, periods, and semicolons with space characters and leaves all other characters unchanged.


INSPECT FIELD1 REPLACING 
        ALL "0" BY "1" 
        ALL "1" BY "0". 

Each of these two replacement arguments has its own replacement value and is active over the entire item being inspected. The statement exchanges zeros for 1s and 1s for zeros. It leaves all other characters unchanged.


INSPECT FIELD1 REPLACING 
        ALL "0" BY "1" BEFORE SPACE 
        ALL "1" BY "0" BEFORE SPACE. 

Note

When a search argument finds a match in the item being inspected, the code replaces that character-string and scans to the next position beyond the replaced characters. It ignores the remaining arguments and applies the first argument in the list to the character-string in the new position. Thus, it never inspects the new value that was supplied by the replacement operation. Because of this, the search arguments can have the same values as the replacement arguments with no chance of interference.

The statement also exchanges zeros and 1s. Here, however, the first space in FIELD1 causes both arguments to become inactive.


INSPECT FIELD1 REPLACING 
        ALL "0" BY "1" BEFORE SPACE 
        ALL "1" BY "0" BEFORE SPACE 
        CHARACTERS BY "*" BEFORE SPACE. 

The first space causes the three replacement arguments to become inactive. This argument list exchanges zeros for 1s, 1s for zeros, and asterisks for all other characters in the delimited area. If the BEFORE phrase is removed from the third argument, that argument will remain active across all of FIELD1. Within the area delimited by the first space character, the third argument replaces all characters except 1s and zeros with asterisks. Beyond this area, it replaces all characters (including the space that delimited FIELD1 for the first two arguments, and any zeros and 1s) with asterisks.

5.3.6.5 Interference in Replacement Argument Lists

When several search arguments, all active at the same time, contain one or more identical characters, they can interfere with each other---and consequently affect the replacement operation. This interference is similar to the interference that occurs between tally arguments.

The action of a search argument is never affected by the BEFORE/AFTER delimiters of other arguments, because the compiler scans for delimiter matches before it scans for replacement operations.

The action of a search argument is never affected by the characters of any replacement value, because the scanner does not inspect the replaced characters again during execution of the INSPECT statement. Interference between search arguments, therefore, depends on the order of the arguments, the values of the arguments, and the active/inactive status of the arguments. The discussion in Section 5.3.5.4 about interference in tally argument lists generally applies to replacement arguments as well.

The following rules help minimize interference in replacement argument lists:

  1. Place search arguments with LEADING or FIRST conditions at the start of the list.
  2. Place any arguments with the CHARACTERS condition at the end of the list.
  3. Consider the order of appearance of any search arguments that contain identical characters.

5.3.7 Using the CONVERTING Option

When an INSPECT statement contains a CONVERTING phrase, that statement selectively replaces characters or groups of characters in the designated item; it executes as if it were a Format 2 INSPECT statement with a series of ALL phrases. (Refer to the INSPECT statement formats in the Compaq COBOL Reference Manual.)

An example of the use of the CONVERTING phrase follows:


IDENTIFICATION DIVISION. 
PROGRAM-ID.  PROGX. 
ENVIRONMENT DIVISION. 
DATA DIVISION. 
WORKING-STORAGE SECTION. 
01 X PIC X(28). 
PROCEDURE DIVISION. 
A.                                              
    MOVE "ABC*ABC*ABC ABC@ABCABC" TO X. 
    INSPECT X CONVERTING "ABC" TO "XYZ" 
            AFTER "*" BEFORE "@". 
    DISPLAY X. 
    STOP RUN. 
 
    X before INSPECT executes      X after INSPECT executes 
 
     ABC*ABC*ABC ABC@ABCABC         ABC*XYZ*XYZ XYZ@ABCABC 

5.3.8 Common INSPECT Statement Errors

Programmers most commonly make the following errors when writing INSPECT statements:


Previous Next Contents Index