String Handling

identifier(start:length) addresses a substring (positions start at 1):

19.1 Reference modification

identifier(start:length) addresses a substring (positions start at 1):

Start and length can be variables or expressions: WS-TEXT(WS-POS:WS-LEN).

01  WS-PHONE      PIC X(10) VALUE "5551234567".
      * ...
           DISPLAY "(" WS-PHONE(1:3) ") "
                   WS-PHONE(4:3) "-" WS-PHONE(7:4)
      *    (555) 123-4567
           MOVE "X" TO WS-PHONE(10:1)
           DISPLAY WS-PHONE(4:)            *> from position 4 to the end

19.2 STRING — concatenation

DELIMITED BY SIZE copies the whole item; DELIMITED BY SPACE (or any literal) stops at the first occurrence. STRING does not clear the target — MOVE SPACES first.

Caution: DELIMITED BY SPACE stops at the *first* space, so "Mary Ann" becomes "Mary". Use FUNCTION TRIM with DELIMITED BY SIZE for multi-word values, or delimit by two spaces (DELIMITED BY " ").

01  WS-FIRST      PIC X(15) VALUE "Grace".
       01  WS-LAST       PIC X(15) VALUE "Hopper".
       01  WS-FULL       PIC X(40).
       01  WS-PTR        PIC 99.
      * ...
           MOVE SPACES TO WS-FULL
           MOVE 1 TO WS-PTR
           STRING WS-LAST  DELIMITED BY SPACE
                  ", "     DELIMITED BY SIZE
                  WS-FIRST DELIMITED BY SPACE
               INTO WS-FULL
               WITH POINTER WS-PTR
               ON OVERFLOW DISPLAY "Name truncated"
           END-STRING
      *    WS-FULL = "Hopper, Grace", WS-PTR = 14 (next free position)

19.3 UNSTRING — splitting

Extra options: DELIMITER IN (captures which delimiter matched), COUNT IN (length of each piece), WITH POINTER (start position). ALL SPACES treats consecutive spaces as one delimiter.

01  WS-CSV        PIC X(50) VALUE "1001,Smith,John,2500.75".
       01  WS-ID         PIC X(6).
       01  WS-LNAME      PIC X(20).
       01  WS-FNAME      PIC X(20).
       01  WS-AMT-TEXT   PIC X(12).
       01  WS-FIELDS     PIC 99 VALUE 0.
      * ...
           UNSTRING WS-CSV DELIMITED BY "," OR ALL SPACES
               INTO WS-ID WS-LNAME WS-FNAME WS-AMT-TEXT
               TALLYING IN WS-FIELDS
               ON OVERFLOW DISPLAY "More fields than receivers"
           END-UNSTRING
           COMPUTE WS-AMOUNT = FUNCTION NUMVAL(WS-AMT-TEXT)

19.4 INSPECT — counting, replacing, converting

TALLYING adds to the counter — initialize it first. REPLACING requires the replacement to be the same length as the matched text.

CONVERTING does character-by-character translation (great for case conversion or masking).

01  WS-TEXT       PIC X(30) VALUE "BANANA BANDANA".
       01  WS-COUNT      PIC 99 VALUE 0.
       01  WS-LEAD       PIC 99 VALUE 0.
       01  WS-AMT-IN     PIC X(10) VALUE "    123.45".
      * ...
           INSPECT WS-TEXT TALLYING WS-COUNT FOR ALL "A"
      *    WS-COUNT = 6
           INSPECT WS-TEXT TALLYING WS-COUNT FOR ALL "AN"
                                             BEFORE INITIAL SPACE
           INSPECT WS-AMT-IN TALLYING WS-LEAD FOR LEADING SPACES
           INSPECT WS-TEXT REPLACING ALL "AN" BY "on"
           INSPECT WS-AMT-IN REPLACING LEADING SPACES BY ZEROS
           INSPECT WS-TEXT REPLACING FIRST "B" BY "C"
           INSPECT WS-TEXT CONVERTING "abcdefghijklmnopqrstuvwxyz"
                                   TO "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

19.5 Useful string functions

FUNCTION TRIM(x), TRIM(x LEADING), TRIM(x TRAILING), UPPER-CASE, LOWER-CASE, REVERSE, LENGTH, CONCATENATE (GnuCOBOL), SUBSTITUTE (GnuCOBOL), STORED-CHAR-LENGTH (GnuCOBOL), ORD, CHAR. Example — length of text without trailing spaces:

COMPUTE WS-LEN =
               FUNCTION LENGTH(FUNCTION TRIM(WS-NAME TRAILING))