MainframeMaster
MainframeMaster

COBOL Tutorial

Progress0 of 0 lessons

COBOL Reference Modification

Reference modification in COBOL allows you to access a substring (portion) of a data item by specifying the starting position and length. It provides a powerful way to extract specific parts of fields, parse fixed-format data, manipulate strings, and access portions of records without using intermediate fields or complex MOVE statements. Understanding reference modification is essential for efficient data processing and string manipulation in COBOL programs.

What is Reference Modification?

Reference modification lets you access a substring of a data item using position-based syntax. Instead of working with the entire field, you can specify exactly which characters you want to access. This is similar to array slicing in other programming languages, but for character strings in COBOL.

Reference modification is useful for:

  • Extracting date components: Getting year, month, day from formatted dates
  • Parsing fixed-format records: Accessing specific fields at known positions
  • String manipulation: Working with portions of text fields
  • Data validation: Checking specific positions for expected values
  • Key extraction: Getting parts of composite keys
  • Formatting: Building output from parts of input fields

Basic Syntax

The syntax for reference modification is:

cobol
1
data-item(start-position:length)

Where:

  • data-item: The field you want to access a portion of
  • start-position: The character position where the substring begins (1-based, so 1 is the first character)
  • length: The number of characters to include in the substring

Both start-position and length can be:

  • Numeric literals (like 5, 10)
  • Numeric data items (variables containing the position/length)
  • Arithmetic expressions (like START-POS + 1)

Basic Example

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
WORKING-STORAGE SECTION. 01 CUSTOMER-NAME PIC X(30) VALUE 'JOHN SMITH'. 01 FIRST-NAME PIC X(10). 01 LAST-NAME PIC X(20). PROCEDURE DIVISION. MAIN-PARA. *> Extract first 4 characters (first name) MOVE CUSTOMER-NAME(1:4) TO FIRST-NAME DISPLAY 'First Name: ' FIRST-NAME *> Output: First Name: JOHN *> Extract characters 6-10 (last name starts at position 6) MOVE CUSTOMER-NAME(6:5) TO LAST-NAME DISPLAY 'Last Name: ' LAST-NAME *> Output: Last Name: SMITH STOP RUN.

In this example:

  • CUSTOMER-NAME(1:4) accesses the first 4 characters: "JOHN"
  • CUSTOMER-NAME(6:5) accesses 5 characters starting at position 6: "SMITH"

Extracting Substrings

The most common use of reference modification is extracting substrings from fields. This is especially useful for parsing fixed-format data.

Date Component Extraction

A very common use case is extracting year, month, and day from a date stored as YYYYMMDD:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
WORKING-STORAGE SECTION. 01 DATE-FIELD PIC 9(8) VALUE 20240115. 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). 01 YEAR-MONTH PIC 9(6). PROCEDURE DIVISION. EXTRACT-DATE-COMPONENTS. *> Extract year (positions 1-4) MOVE DATE-FIELD(1:4) TO YEAR *> Result: 2024 *> Extract month (positions 5-6) MOVE DATE-FIELD(5:2) TO MONTH *> Result: 01 *> Extract day (positions 7-8) MOVE DATE-FIELD(7:2) TO DAY *> Result: 15 *> Extract year and month together (positions 1-6) MOVE DATE-FIELD(1:6) TO YEAR-MONTH *> Result: 202401 DISPLAY 'Date: ' YEAR '/' MONTH '/' DAY *> Output: Date: 2024/01/15 STOP RUN.

This technique is extremely useful because:

  • No intermediate fields needed: Extract directly without temporary storage
  • Efficient: Direct access to the portion you need
  • Clear intent: The position and length make the extraction obvious

Parsing Fixed-Format Records

Reference modification is ideal for parsing fixed-format records where fields are at known positions:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
WORKING-STORAGE SECTION. 01 INPUT-RECORD PIC X(80). 01 RECORD-TYPE PIC X(2). 01 CUSTOMER-ID PIC X(10). 01 TRANSACTION-AMOUNT PIC X(12). 01 TRANSACTION-DATE PIC X(8). PROCEDURE DIVISION. PARSE-FIXED-RECORD. *> Assume record format: *> Positions 1-2: Record type *> Positions 3-12: Customer ID *> Positions 13-24: Transaction amount *> Positions 25-32: Transaction date MOVE '01CUST12345 5000.00 20240115' TO INPUT-RECORD MOVE INPUT-RECORD(1:2) TO RECORD-TYPE *> Extracts: "01" MOVE INPUT-RECORD(3:10) TO CUSTOMER-ID *> Extracts: "CUST12345 " MOVE INPUT-RECORD(13:12) TO TRANSACTION-AMOUNT *> Extracts: " 5000.00 " MOVE INPUT-RECORD(25:8) TO TRANSACTION-DATE *> Extracts: "20240115" DISPLAY 'Type: ' RECORD-TYPE DISPLAY 'Customer: ' CUSTOMER-ID DISPLAY 'Amount: ' TRANSACTION-AMOUNT DISPLAY 'Date: ' TRANSACTION-DATE STOP RUN.

Using Variables for Positions

You can use variables for start position and length, making reference modification dynamic:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
WORKING-STORAGE SECTION. 01 SOURCE-FIELD PIC X(50) VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. 01 START-POS PIC 9(2) VALUE 5. 01 EXTRACT-LENGTH PIC 9(2) VALUE 10. 01 EXTRACTED-PORTION PIC X(50). PROCEDURE DIVISION. DYNAMIC-EXTRACTION. *> Extract using variables MOVE SOURCE-FIELD(START-POS:EXTRACT-LENGTH) TO EXTRACTED-PORTION *> Extracts 10 characters starting at position 5: "EFGHIJKLMN" DISPLAY 'Extracted: ' EXTRACTED-PORTION *> Change position and extract again MOVE 10 TO START-POS MOVE 5 TO EXTRACT-LENGTH MOVE SOURCE-FIELD(START-POS:EXTRACT-LENGTH) TO EXTRACTED-PORTION *> Extracts 5 characters starting at position 10: "JKLMN" DISPLAY 'Extracted: ' EXTRACTED-PORTION STOP RUN.

Using variables allows you to:

  • Calculate positions dynamically: Based on data or calculations
  • Loop through fields: Extract different portions in a loop
  • Handle variable formats: Adjust positions based on record type

Omitting the Length

You can omit the length to get all characters from the start position to the end of the field:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
WORKING-STORAGE SECTION. 01 FULL-NAME PIC X(30) VALUE 'JOHN SMITH'. 01 LAST-PART PIC X(30). PROCEDURE DIVISION. EXTRACT-TO-END. *> Get all characters from position 6 to the end MOVE FULL-NAME(6:) TO LAST-PART *> Result: "SMITH" (all characters from position 6 onward) DISPLAY 'Last Part: ' LAST-PART STOP RUN.

Omitting the length is useful when you want everything from a certain position to the end, without needing to calculate the remaining length.

Using Reference Modification in Comparisons

You can use reference modification directly in IF statements and other comparisons:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
WORKING-STORAGE SECTION. 01 CUSTOMER-ID PIC X(10) VALUE 'CUST123456'. 01 RECORD-TYPE PIC X(2). PROCEDURE DIVISION. VALIDATE-WITH-REF-MOD. *> Check if customer ID starts with "CUST" IF CUSTOMER-ID(1:4) = 'CUST' DISPLAY 'Valid customer ID format' ELSE DISPLAY 'Invalid customer ID format' END-IF *> Check the first two characters IF CUSTOMER-ID(1:2) = 'CU' DISPLAY 'Starts with CU' END-IF *> Extract and use in condition MOVE CUSTOMER-ID(1:2) TO RECORD-TYPE IF RECORD-TYPE = 'CU' DISPLAY 'Customer record type' END-IF STOP RUN.

This allows you to validate data formats, check prefixes or suffixes, and make decisions based on specific portions of fields without extracting to intermediate variables first.

Common Use Cases

1. Extracting Date Components

cobol
1
2
3
4
5
6
7
8
9
10
11
WORKING-STORAGE SECTION. 01 DATE-YYYYMMDD PIC 9(8) VALUE 20240115. 01 YEAR PIC 9(4). 01 MONTH PIC 9(2). 01 DAY PIC 9(2). PROCEDURE DIVISION. EXTRACT-DATE. MOVE DATE-YYYYMMDD(1:4) TO YEAR *> 2024 MOVE DATE-YYYYMMDD(5:2) TO MONTH *> 01 MOVE DATE-YYYYMMDD(7:2) TO DAY *> 15.

2. Parsing Account Numbers

cobol
1
2
3
4
5
6
7
8
9
10
11
WORKING-STORAGE SECTION. 01 ACCOUNT-NUMBER PIC X(12) VALUE '123456789012'. 01 BRANCH-CODE PIC X(4). 01 ACCOUNT-SEQUENCE PIC X(8). PROCEDURE DIVISION. PARSE-ACCOUNT. *> First 4 digits are branch code MOVE ACCOUNT-NUMBER(1:4) TO BRANCH-CODE *> Last 8 digits are account sequence MOVE ACCOUNT-NUMBER(5:8) TO ACCOUNT-SEQUENCE.

3. Extracting Key Components

cobol
1
2
3
4
5
6
7
8
9
10
11
WORKING-STORAGE SECTION. 01 COMPOSITE-KEY PIC X(20) VALUE 'REGION01DEPT05EMP123'. 01 REGION-CODE PIC X(8). 01 DEPARTMENT-CODE PIC X(6). 01 EMPLOYEE-NUMBER PIC X(6). PROCEDURE DIVISION. EXTRACT-KEY-COMPONENTS. MOVE COMPOSITE-KEY(1:8) TO REGION-CODE *> "REGION01" MOVE COMPOSITE-KEY(9:6) TO DEPARTMENT-CODE *> "DEPT05" MOVE COMPOSITE-KEY(15:6) TO EMPLOYEE-NUMBER *> "EMP123".

4. Validating Formats

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
WORKING-STORAGE SECTION. 01 TRANSACTION-CODE PIC X(10) VALUE 'TXN1234567'. PROCEDURE DIVISION. VALIDATE-FORMAT. *> Check if it starts with "TXN" IF TRANSACTION-CODE(1:3) = 'TXN' DISPLAY 'Valid transaction code prefix' END-IF *> Check if positions 4-6 are numeric IF TRANSACTION-CODE(4:3) IS NUMERIC DISPLAY 'Numeric sequence found' END-IF.

Reference Modification vs Other Techniques

Understanding when to use reference modification versus other string manipulation techniques:

Reference Modification vs Other String Techniques
TechniqueBest UseExample
Reference ModificationExtracting known positions, simple substring accessDATE-FIELD(1:4) to get year
STRINGConcatenating multiple fields into oneSTRING A DELIMITED BY SIZE B INTO RESULT
UNSTRINGParsing delimited data, splitting on separatorsUNSTRING FIELD DELIMITED BY "," INTO PART1 PART2
MOVE with editingFormatting entire fieldsMOVE AMOUNT TO FORMATTED-AMOUNT (with PIC editing)

Limitations and Considerations

Important limitations and considerations when using reference modification:

1. Position Validation

Always validate positions to avoid runtime errors:

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
WORKING-STORAGE SECTION. 01 SOURCE-FIELD PIC X(20) VALUE 'ABCDEFGHIJ'. 01 START-POS PIC 9(2). 01 EXTRACT-LENGTH PIC 9(2). PROCEDURE DIVISION. SAFE-EXTRACTION. MOVE 15 TO START-POS MOVE 10 TO EXTRACT-LENGTH *> Validate before using IF START-POS > 0 AND START-POS <= 20 AND EXTRACT-LENGTH > 0 AND (START-POS + EXTRACT-LENGTH - 1) <= 20 MOVE SOURCE-FIELD(START-POS:EXTRACT-LENGTH) TO RESULT-FIELD ELSE DISPLAY 'ERROR: Invalid position or length' END-IF.

2. Read-Only Access

Reference modification provides read-only access. You cannot modify part of a field using reference modification on the left side of MOVE. To modify a portion, you must:

  • Move the entire field to a work area
  • Modify the portion you want
  • Move the work area back to the original field

3. Performance Considerations

While reference modification is efficient, excessive use in loops or with large fields may impact performance. Consider the trade-off between clarity and performance for your specific use case.

Advanced Examples

Example 1: Building Formatted Output

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
WORKING-STORAGE SECTION. 01 DATE-INPUT PIC 9(8) VALUE 20240115. 01 FORMATTED-DATE PIC X(10). PROCEDURE DIVISION. BUILD-FORMATTED-DATE. *> Build formatted date: MM/DD/YYYY STRING DATE-INPUT(5:2) DELIMITED BY SIZE '/' DELIMITED BY SIZE DATE-INPUT(7:2) DELIMITED BY SIZE '/' DELIMITED BY SIZE DATE-INPUT(1:4) DELIMITED BY SIZE INTO FORMATTED-DATE END-STRING *> Result: "01/15/2024" DISPLAY 'Formatted Date: ' FORMATTED-DATE.

Example 2: Conditional Extraction

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
WORKING-STORAGE SECTION. 01 RECORD-TYPE PIC X(2). 01 INPUT-RECORD PIC X(80). 01 EXTRACTED-FIELD PIC X(20). PROCEDURE DIVISION. CONDITIONAL-EXTRACT. *> Extract different fields based on record type MOVE INPUT-RECORD(1:2) TO RECORD-TYPE IF RECORD-TYPE = '01' *> Type 01: Extract positions 10-29 MOVE INPUT-RECORD(10:20) TO EXTRACTED-FIELD ELSE IF RECORD-TYPE = '02' *> Type 02: Extract positions 15-34 MOVE INPUT-RECORD(15:20) TO EXTRACTED-FIELD ELSE *> Default: Extract positions 5-24 MOVE INPUT-RECORD(5:20) TO EXTRACTED-FIELD END-IF END-IF.

Best Practices

Follow these best practices when using reference modification:

  • Validate positions: Always check that positions and lengths are within bounds
  • Use constants: Define position constants for maintainability (e.g., 01 DATE-YEAR-START PIC 9 VALUE 1)
  • Document positions: Comment the record layout when using fixed positions
  • Consider readability: Sometimes extracting to a named field is clearer than inline reference modification
  • Handle edge cases: Consider what happens with empty fields or invalid positions
  • Test thoroughly: Test with various data lengths and positions
  • Use for known formats: Reference modification is best for fixed-format data

Explain Like I'm 5: Reference Modification

Think of reference modification like cutting a piece of cake:

  • The whole cake is like your data field (CUSTOMER-NAME)
  • Starting position is like where you start cutting (position 1 is the first slice)
  • Length is like how many slices you want (how many characters)
  • The result is your piece of cake (the substring you extracted)

So CUSTOMER-NAME(1:5) is like saying "give me 5 slices starting from the first slice" - you get the first 5 characters! And just like you can't put cake back once it's cut, reference modification is read-only - you can look at the piece, but you can't change the original cake by changing the piece.

Practice Exercises

Complete these exercises to reinforce your understanding:

Exercise 1: Date Extraction

Create a program that reads a date in YYYYMMDD format and uses reference modification to extract and display the year, month, and day separately.

Exercise 2: Account Number Parsing

Create a program that parses a 12-character account number where positions 1-4 are branch code, 5-8 are account type, and 9-12 are sequence number. Use reference modification to extract each component.

Exercise 3: Format Validation

Create a program that validates transaction codes. The code should start with "TXN" (positions 1-3), have numeric characters in positions 4-7, and end with a check digit in position 8. Use reference modification to check each part.

Exercise 4: Dynamic Extraction

Create a program that uses variables for start position and length. Allow the user to specify which portion of a field to extract, then use reference modification with those variables.

Exercise 5: Building Output

Create a program that reads a date in YYYYMMDD format and uses reference modification to extract components, then builds a formatted date string in DD/MM/YYYY format using STRING.

Test Your Knowledge

1. What is the syntax for COBOL reference modification?

  • data-item[start:length]
  • data-item(start-position:length)
  • SUBSTRING(data-item, start, length)
  • data-item.SUBSTR(start, length)

2. What does CUSTOMER-NAME(1:10) access?

  • The last 10 characters
  • The first 10 characters starting at position 1
  • Characters 10 through 20
  • All characters except the first 10

3. Can you modify a field using reference modification on the left side of MOVE?

  • Yes, always
  • No, reference modification is read-only
  • Only for numeric fields
  • Only in certain COBOL versions

4. What is a common use of reference modification?

  • Concatenating strings
  • Extracting date components from formatted dates
  • Sorting data
  • Opening files

5. How do you get all characters from position 5 to the end?

  • FIELD(5:END)
  • FIELD(5:)
  • FIELD(5:999)
  • FIELD(5:-1)

6. What happens if the start position exceeds the field length?

  • It wraps around
  • A runtime error occurs
  • It returns empty string
  • It returns the last character

Related Concepts

Related Pages