The STRING statement in COBOL provides a powerful way to concatenate multiple strings into a single string with precise control over the process. This ability to combine strings is essential for building formatted messages, report lines, data for display, or any situation requiring text assembly from various sources.
1234567STRING {identifier-1|literal-1} [DELIMITED BY {identifier-2|literal-2|SIZE}] [{identifier-3|literal-3} [DELIMITED BY {identifier-4|literal-4|SIZE}]] ... INTO identifier-5 [WITH POINTER identifier-6] [ON OVERFLOW imperative-statement-1] [NOT ON OVERFLOW imperative-statement-2] [END-STRING]
12345678910111213141516171819202122232425262728293031IDENTIFICATION DIVISION. PROGRAM-ID. STRINGSAMPLE. DATA DIVISION. WORKING-STORAGE SECTION. 01 FIRST-NAME PIC X(10) VALUE "John". 01 LAST-NAME PIC X(15) VALUE "Smith". 01 FULL-NAME PIC X(30) VALUE SPACES. 01 GREETING-MSG PIC X(50) VALUE SPACES. PROCEDURE DIVISION. MAIN-PARA. * Basic concatenation of first and last name with a space between STRING FIRST-NAME DELIMITED BY SIZE " " DELIMITED BY SIZE LAST-NAME DELIMITED BY SIZE INTO FULL-NAME END-STRING DISPLAY "Full name: " FULL-NAME * Using the result in another STRING operation STRING "Hello, " DELIMITED BY SIZE FULL-NAME DELIMITED BY SIZE "! How are you today?" DELIMITED BY SIZE INTO GREETING-MSG END-STRING DISPLAY GREETING-MSG STOP RUN.
This example demonstrates basic string concatenation. First, it combines a first and last name with a space between them, and then uses that result to build a greeting message. The DELIMITED BY SIZE clause ensures each field is used in its entirety.
The DELIMITED BY clause provides fine-grained control over how much of each source field is included in the concatenation. It can use specific delimiters or the special keyword SIZE.
1234567891011121314151617181920212223242526272829303132* Example of different DELIMITED BY options 01 PRODUCT-CODE PIC X(10) VALUE "ABC123****". 01 CUSTOMER-INFO PIC X(20) VALUE "SMITH,JOHN,ACTIVE". 01 RESULT-FIELD PIC X(50) VALUE SPACES. 01 TEMP-FIELD PIC X(50) VALUE SPACES. * Using SIZE - takes the entire field STRING PRODUCT-CODE DELIMITED BY SIZE INTO RESULT-FIELD END-STRING * Result: "ABC123****" * Using a specific delimiter - stops at the first occurrence STRING PRODUCT-CODE DELIMITED BY "*" INTO RESULT-FIELD END-STRING * Result: "ABC123" * Using a space delimiter 01 TEXT-WITH-SPACES PIC X(20) VALUE "Hello world example". STRING TEXT-WITH-SPACES DELIMITED BY SPACE INTO TEMP-FIELD END-STRING * Result: "Hello" * Using multiple fields with different delimiters STRING PRODUCT-CODE DELIMITED BY "*" " - " DELIMITED BY SIZE CUSTOMER-INFO DELIMITED BY "," INTO RESULT-FIELD END-STRING * Result: "ABC123 - SMITH"
The POINTER clause lets you control where in the receiving field the concatenation begins, and it's automatically updated as the operation progresses.
123456789101112131415161718192021222324252627282930313233* Example using the POINTER clause 01 OUTPUT-AREA PIC X(100) VALUE SPACES. 01 START-POS PIC 9(3) VALUE 1. 01 HEADER-TEXT PIC X(20) VALUE "Customer Report - ". 01 CURRENT-DATE PIC X(10) VALUE "2023/05/15". * Basic pointer usage STRING HEADER-TEXT DELIMITED BY SIZE CURRENT-DATE DELIMITED BY SIZE INTO OUTPUT-AREA WITH POINTER START-POS END-STRING DISPLAY "Result: " OUTPUT-AREA DISPLAY "New pointer position: " START-POS * Using the updated pointer for further concatenation STRING ": Page 1" DELIMITED BY SIZE INTO OUTPUT-AREA WITH POINTER START-POS END-STRING DISPLAY "Final result: " OUTPUT-AREA DISPLAY "Final pointer position: " START-POS * Using pointer to position within the field MOVE 10 TO START-POS STRING "**INSERTED**" DELIMITED BY SIZE INTO OUTPUT-AREA WITH POINTER START-POS END-STRING DISPLAY "After insertion: " OUTPUT-AREA
Key points about the POINTER clause:
The ON OVERFLOW clause allows you to handle situations where the receiving field is not large enough to hold the entire concatenated result.
123456789101112131415161718192021222324252627282930313233* Example of overflow handling 01 SMALL-FIELD PIC X(15) VALUE SPACES. 01 LONG-TEXT PIC X(50) VALUE "This is a very long text that will not fit in the small field". 01 OVERFLOW-FLAG PIC X VALUE "N". 88 OVERFLOW-OCCURRED VALUE "Y". * Without overflow handling - truncation occurs silently STRING LONG-TEXT DELIMITED BY SIZE INTO SMALL-FIELD END-STRING DISPLAY "Without overflow handling: " SMALL-FIELD * With overflow handling STRING LONG-TEXT DELIMITED BY SIZE INTO SMALL-FIELD ON OVERFLOW MOVE "Y" TO OVERFLOW-FLAG DISPLAY "Overflow occurred!" END-STRING DISPLAY "With overflow handling: " SMALL-FIELD DISPLAY "Overflow flag: " OVERFLOW-FLAG * Using NOT ON OVERFLOW MOVE SPACES TO SMALL-FIELD STRING "Short text" DELIMITED BY SIZE INTO SMALL-FIELD ON OVERFLOW DISPLAY "Overflow occurred (not expected)" NOT ON OVERFLOW DISPLAY "Operation completed without overflow" END-STRING
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354* Building formatted report lines 01 REPORT-LINE PIC X(80) VALUE SPACES. 01 LINE-POS PIC 9(2) VALUE 1. 01 PRODUCT-INFO. 05 PROD-ID PIC X(5) VALUE "P1234". 05 PROD-NAME PIC X(20) VALUE "Deluxe Widget". 05 PROD-PRICE PIC 9(4)V99 VALUE 24.99. 05 PROD-PRICE-DISPLAY PIC Z,ZZ9.99. * Format the numeric price for display MOVE PROD-PRICE TO PROD-PRICE-DISPLAY * Build the report line with proper alignment MOVE 1 TO LINE-POS STRING PROD-ID DELIMITED BY SIZE INTO REPORT-LINE WITH POINTER LINE-POS END-STRING MOVE 10 TO LINE-POS STRING PROD-NAME DELIMITED BY SIZE INTO REPORT-LINE WITH POINTER LINE-POS END-STRING MOVE 35 TO LINE-POS STRING "$" DELIMITED BY SIZE PROD-PRICE-DISPLAY DELIMITED BY SIZE INTO REPORT-LINE WITH POINTER LINE-POS END-STRING DISPLAY REPORT-LINE * Building formatted addresses 01 CUSTOMER-ADDRESS. 05 STREET PIC X(25) VALUE "123 Main Street". 05 CITY PIC X(15) VALUE "Springfield". 05 STATE PIC XX VALUE "IL". 05 ZIP PIC X(10) VALUE "62701". 01 FORMATTED-ADDRESS PIC X(80) VALUE SPACES. STRING STREET DELIMITED BY SIZE ", " DELIMITED BY SIZE CITY DELIMITED BY SIZE ", " DELIMITED BY SIZE STATE DELIMITED BY SIZE " " DELIMITED BY SIZE ZIP DELIMITED BY SIZE INTO FORMATTED-ADDRESS END-STRING DISPLAY FORMATTED-ADDRESS * "123 Main Street, Springfield, IL 62701"
These examples demonstrate practical applications of the STRING statement, including:
The UNSTRING statement is the counterpart to STRING, designed to break down a single string into multiple substrings. It's an essential tool for parsing input data, extracting specific parts of a string, or breaking down complex formatted text into its component parts.
12345678UNSTRING identifier-1 [DELIMITED BY [ALL] {identifier-2|literal-1} [OR [ALL] {identifier-3|literal-2}]...] INTO {identifier-4 [DELIMITER IN identifier-5] [COUNT IN identifier-6]}... [WITH POINTER identifier-7] [TALLYING IN identifier-8] [ON OVERFLOW imperative-statement-1] [NOT ON OVERFLOW imperative-statement-2] [END-UNSTRING]
12345678910111213141516171819202122232425262728293031323334353637IDENTIFICATION DIVISION. PROGRAM-ID. UNSTRINGSAMPLE. DATA DIVISION. WORKING-STORAGE SECTION. 01 FULL-NAME PIC X(30) VALUE "Smith,John,Robert". 01 NAME-PARTS. 05 LAST-NAME PIC X(15) VALUE SPACES. 05 FIRST-NAME PIC X(10) VALUE SPACES. 05 MIDDLE-NAME PIC X(10) VALUE SPACES. 01 DELIMITER-USED PIC X VALUE SPACE. PROCEDURE DIVISION. MAIN-PARA. * Basic parsing of a comma-separated name UNSTRING FULL-NAME DELIMITED BY "," INTO LAST-NAME FIRST-NAME MIDDLE-NAME END-UNSTRING DISPLAY "Last name: " LAST-NAME DISPLAY "First name: " FIRST-NAME DISPLAY "Middle name: " MIDDLE-NAME * Parsing with additional options UNSTRING FULL-NAME DELIMITED BY "," INTO LAST-NAME DELIMITER IN DELIMITER-USED FIRST-NAME MIDDLE-NAME END-UNSTRING DISPLAY "Delimiter used: '" DELIMITER-USED "'" STOP RUN.
This example demonstrates basic string parsing using UNSTRING. It breaks down a full name with comma separators into last, first, and middle names. The second example also captures the delimiter that was used.
The DELIMITED BY clause in UNSTRING determines how the source string should be broken down. You can specify multiple delimiters and control how consecutive delimiters are handled.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647* Examples of different DELIMITED BY options 01 CSV-RECORD PIC X(50) VALUE "Smith,42,Active,12/15/2022". 01 DATA-ITEMS. 05 NAME-FIELD PIC X(15) VALUE SPACES. 05 AGE-FIELD PIC X(5) VALUE SPACES. 05 STATUS-FIELD PIC X(10) VALUE SPACES. 05 DATE-FIELD PIC X(15) VALUE SPACES. 01 PHONE-NUMBER PIC X(20) VALUE "(555) 123-4567". 01 PHONE-PARTS. 05 AREA-CODE PIC X(5) VALUE SPACES. 05 PREFIX PIC X(5) VALUE SPACES. 05 LINE-NUMBER PIC X(5) VALUE SPACES. * Basic delimiter UNSTRING CSV-RECORD DELIMITED BY "," INTO NAME-FIELD AGE-FIELD STATUS-FIELD DATE-FIELD END-UNSTRING * Multiple delimiters with OR UNSTRING PHONE-NUMBER DELIMITED BY "(" OR ")" OR " " OR "-" INTO AREA-CODE PREFIX LINE-NUMBER END-UNSTRING * Using the ALL option 01 TEXT-WITH-SPACES PIC X(30) VALUE "This has multiple spaces". 01 WORD-ARRAY OCCURS 5 TIMES PIC X(10). UNSTRING TEXT-WITH-SPACES DELIMITED BY ALL SPACE INTO WORD-ARRAY(1) WORD-ARRAY(2) WORD-ARRAY(3) WORD-ARRAY(4) END-UNSTRING * Results: * WORD-ARRAY(1): "This" * WORD-ARRAY(2): "has" * WORD-ARRAY(3): "multiple" * WORD-ARRAY(4): "spaces"
UNSTRING provides several additional options for capturing more information about the parsing process.
123456789101112131415161718192021222324252627282930313233* Example with COUNT IN, DELIMITER IN, and TALLYING 01 RECORD-TEXT PIC X(50) VALUE "Smith:42:Active:12/15/2022". 01 FIELD-COUNTS. 05 NAME-COUNT PIC 99 VALUE ZERO. 05 AGE-COUNT PIC 99 VALUE ZERO. 05 STATUS-COUNT PIC 99 VALUE ZERO. 05 DATE-COUNT PIC 99 VALUE ZERO. 01 FIELD-DELIMITERS. 05 NAME-DELIM PIC X VALUE SPACE. 05 AGE-DELIM PIC X VALUE SPACE. 05 STATUS-DELIM PIC X VALUE SPACE. 01 TOTAL-FIELDS PIC 99 VALUE ZERO. 01 DATA-FIELDS. 05 NAME-FIELD PIC X(15) VALUE SPACES. 05 AGE-FIELD PIC X(5) VALUE SPACES. 05 STATUS-FIELD PIC X(10) VALUE SPACES. 05 DATE-FIELD PIC X(15) VALUE SPACES. UNSTRING RECORD-TEXT DELIMITED BY ":" INTO NAME-FIELD DELIMITER IN NAME-DELIM COUNT IN NAME-COUNT AGE-FIELD DELIMITER IN AGE-DELIM COUNT IN AGE-COUNT STATUS-FIELD DELIMITER IN STATUS-DELIM COUNT IN STATUS-COUNT DATE-FIELD COUNT IN DATE-COUNT TALLYING IN TOTAL-FIELDS END-UNSTRING DISPLAY "Fields processed: " TOTAL-FIELDS DISPLAY "Name: " NAME-FIELD " (Length: " NAME-COUNT ")" DISPLAY "Age: " AGE-FIELD " (Length: " AGE-COUNT ")" DISPLAY "Status: " STATUS-FIELD " (Length: " STATUS-COUNT ")" DISPLAY "Date: " DATE-FIELD " (Length: " DATE-COUNT ")" DISPLAY "Delimiters: '" NAME-DELIM "', '" AGE-DELIM "', '" STATUS-DELIM "'"
Key features demonstrated:
The WITH POINTER clause in UNSTRING allows you to control where parsing begins in the source string and tracks the position after parsing is complete.
1234567891011121314151617181920212223242526272829303132333435363738394041* Example using the WITH POINTER clause 01 COMPLEX-DATA PIC X(50) VALUE "Header:Smith,Jones,Brown:Footer". 01 POSITION-PTR PIC 99 VALUE 1. 01 NAME-LIST. 05 NAME1 PIC X(10) VALUE SPACES. 05 NAME2 PIC X(10) VALUE SPACES. 05 NAME3 PIC X(10) VALUE SPACES. 01 HEADER-FIELD PIC X(10) VALUE SPACES. 01 FOOTER-FIELD PIC X(10) VALUE SPACES. * Extract the header UNSTRING COMPLEX-DATA DELIMITED BY ":" INTO HEADER-FIELD WITH POINTER POSITION-PTR END-UNSTRING DISPLAY "Header: " HEADER-FIELD DISPLAY "Current position: " POSITION-PTR * Extract the name list UNSTRING COMPLEX-DATA DELIMITED BY "," OR ":" INTO NAME1 NAME2 NAME3 WITH POINTER POSITION-PTR END-UNSTRING DISPLAY "Names: " NAME1 ", " NAME2 ", " NAME3 DISPLAY "Current position: " POSITION-PTR * Extract the footer UNSTRING COMPLEX-DATA DELIMITED BY SIZE INTO FOOTER-FIELD WITH POINTER POSITION-PTR END-UNSTRING DISPLAY "Footer: " FOOTER-FIELD DISPLAY "Final position: " POSITION-PTR
Overflow handling is crucial in UNSTRING operations to manage situations where there are more substrings in the source field than there are receiving fields to hold them.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253* Example of overflow handling in UNSTRING 01 COMMA-LIST PIC X(50) VALUE "Apple,Orange,Banana,Grape,Peach". 01 FRUIT-ARRAY. 05 FRUIT1 PIC X(10) VALUE SPACES. 05 FRUIT2 PIC X(10) VALUE SPACES. 05 FRUIT3 PIC X(10) VALUE SPACES. 01 OVERFLOW-FLAG PIC X VALUE "N". * Without overflow handling UNSTRING COMMA-LIST DELIMITED BY "," INTO FRUIT1 FRUIT2 FRUIT3 END-UNSTRING DISPLAY "Without overflow handling:" DISPLAY "Fruit1: " FRUIT1 DISPLAY "Fruit2: " FRUIT2 DISPLAY "Fruit3: " FRUIT3 * Note: Grape and Peach are lost without warning * With overflow handling MOVE "N" TO OVERFLOW-FLAG MOVE SPACES TO FRUIT1, FRUIT2, FRUIT3 UNSTRING COMMA-LIST DELIMITED BY "," INTO FRUIT1 FRUIT2 FRUIT3 ON OVERFLOW MOVE "Y" TO OVERFLOW-FLAG DISPLAY "Warning: Not all data was processed" END-UNSTRING DISPLAY "With overflow handling:" DISPLAY "Fruit1: " FRUIT1 DISPLAY "Fruit2: " FRUIT2 DISPLAY "Fruit3: " FRUIT3 DISPLAY "Overflow occurred: " OVERFLOW-FLAG * Using NOT ON OVERFLOW UNSTRING "A,B" DELIMITED BY "," INTO FRUIT1 FRUIT2 FRUIT3 ON OVERFLOW DISPLAY "Overflow occurred (not expected)" NOT ON OVERFLOW DISPLAY "All data was processed without overflow" END-UNSTRING
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566* Parsing CSV data 01 CSV-RECORD PIC X(100) VALUE "1234,Smith,John,42,Sales,65000". 01 CSV-FIELDS. 05 ID-FIELD PIC X(10) VALUE SPACES. 05 LAST-NAME PIC X(15) VALUE SPACES. 05 FIRST-NAME PIC X(15) VALUE SPACES. 05 AGE PIC X(5) VALUE SPACES. 05 DEPT PIC X(15) VALUE SPACES. 05 SALARY PIC X(10) VALUE SPACES. UNSTRING CSV-RECORD DELIMITED BY "," INTO ID-FIELD LAST-NAME FIRST-NAME AGE DEPT SALARY END-UNSTRING * Parsing a date/time string 01 DATE-TIME-STAMP PIC X(20) VALUE "2023-05-15 14:30:45". 01 DATE-PARTS. 05 YEAR-PART PIC X(4) VALUE SPACES. 05 MONTH-PART PIC X(2) VALUE SPACES. 05 DAY-PART PIC X(2) VALUE SPACES. 01 TIME-PARTS. 05 HOUR-PART PIC X(2) VALUE SPACES. 05 MINUTE-PART PIC X(2) VALUE SPACES. 05 SECOND-PART PIC X(2) VALUE SPACES. 01 WORK-PTR PIC 99 VALUE 1. * First parse the date portion UNSTRING DATE-TIME-STAMP DELIMITED BY "-" OR " " INTO YEAR-PART MONTH-PART DAY-PART WITH POINTER WORK-PTR END-UNSTRING * Then parse the time portion UNSTRING DATE-TIME-STAMP DELIMITED BY ":" INTO HOUR-PART MINUTE-PART SECOND-PART WITH POINTER WORK-PTR END-UNSTRING * Parsing a fixed-position report line 01 REPORT-LINE PIC X(50) VALUE "P1234 Deluxe Widget 24.99 10 249.90". 01 PRODUCT-DETAILS. 05 PROD-ID PIC X(8) VALUE SPACES. 05 PROD-NAME PIC X(20) VALUE SPACES. 05 UNIT-PRICE PIC X(8) VALUE SPACES. 05 QUANTITY PIC X(4) VALUE SPACES. 05 TOTAL-PRICE PIC X(8) VALUE SPACES. UNSTRING REPORT-LINE INTO PROD-ID PROD-NAME UNIT-PRICE QUANTITY TOTAL-PRICE END-UNSTRING
These examples demonstrate practical applications of the UNSTRING statement, including:
STRING and UNSTRING are complementary operations for string manipulation in COBOL. Understanding their similarities and differences helps in choosing the right tool for the job.
Feature | STRING | UNSTRING |
---|---|---|
Primary Purpose | Concatenate multiple fields into one | Split one field into multiple fields |
Direction | Many-to-one | One-to-many |
Delimiter Handling | DELIMITED BY controls how much of each sending field is used | DELIMITED BY specifies separators between substrings |
Position Control | WITH POINTER | WITH POINTER |
Overflow Condition | Receiving field too small | More substrings than receiving fields |
Counting | No direct counting option | TALLYING IN counts fields processed |
Delimiter Capture | Not available | DELIMITER IN captures delimiters |
Length Capture | Not available | COUNT IN captures substring lengths |
Special Features | SIZE option for full field usage | ALL option for consecutive delimiters |
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253* Example of using STRING and UNSTRING together IDENTIFICATION DIVISION. PROGRAM-ID. STRINGUNSTRING. DATA DIVISION. WORKING-STORAGE SECTION. 01 EMPLOYEE-DETAILS. 05 EMP-ID PIC X(5) VALUE "12345". 05 EMP-NAME PIC X(20) VALUE "Smith, John". 05 EMP-DEPT PIC X(10) VALUE "IT". 05 EMP-SALARY PIC 9(6) VALUE 65000. 01 SALARY-DISPLAY PIC $ZZ,ZZ9. 01 COMBINED-RECORD PIC X(50) VALUE SPACES. 01 DELIMITER PIC X VALUE "|". 01 PARSED-FIELDS. 05 ID-FIELD PIC X(5) VALUE SPACES. 05 NAME-FIELD PIC X(20) VALUE SPACES. 05 DEPT-FIELD PIC X(10) VALUE SPACES. 05 SALARY-FIELD PIC X(10) VALUE SPACES. PROCEDURE DIVISION. MAIN-PARA. * Format the salary for display MOVE EMP-SALARY TO SALARY-DISPLAY * STRING - Combine fields into a delimited record STRING EMP-ID DELIMITED BY SIZE DELIMITER DELIMITED BY SIZE EMP-NAME DELIMITED BY SIZE DELIMITER DELIMITED BY SIZE EMP-DEPT DELIMITED BY SIZE DELIMITER DELIMITED BY SIZE SALARY-DISPLAY DELIMITED BY SIZE INTO COMBINED-RECORD END-STRING DISPLAY "Combined record: " COMBINED-RECORD * UNSTRING - Parse the record back into individual fields UNSTRING COMBINED-RECORD DELIMITED BY "|" INTO ID-FIELD NAME-FIELD DEPT-FIELD SALARY-FIELD END-UNSTRING DISPLAY "Parsed ID: " ID-FIELD DISPLAY "Parsed Name: " NAME-FIELD DISPLAY "Parsed Dept: " DEPT-FIELD DISPLAY "Parsed Salary: " SALARY-FIELD STOP RUN.
This example demonstrates a common workflow:
1. What is the primary purpose of the STRING statement in COBOL?
2. What is the function of the DELIMITED BY phrase in the STRING statement?
3. What happens when you include the POINTER phrase in the STRING statement?
4. What is the primary purpose of the UNSTRING statement?
5. How is the TALLYING phrase used in the UNSTRING statement?
Detailed usage of the STRING statement for concatenation.
Using UNSTRING to parse strings into separate fields.
Counting and replacing characters in strings.
Accessing parts of strings using reference modification.
Understanding delimiter handling in STRING and UNSTRING.