diff --git a/COBOL Programming Course #2 - Learning COBOL/COBOL Programming Course #2 - Learning COBOL.md b/COBOL Programming Course #2 - Learning COBOL/COBOL Programming Course #2 - Learning COBOL.md index 9a65edd2..19e29874 100644 --- a/COBOL Programming Course #2 - Learning COBOL/COBOL Programming Course #2 - Learning COBOL.md +++ b/COBOL Programming Course #2 - Learning COBOL/COBOL Programming Course #2 - Learning COBOL.md @@ -2773,6 +2773,77 @@ This exercise develops skills in COBOL conditional processing, program structure **Need Help?** If you encounter difficulties, you can refer to the complete solution code `CBLC1.cobol` available in VS Code Zowe Explorer or find it on [GitHub](https://github.com/openmainframeproject/cobol-programming-course/tree/master/COBOL%20Programming%20Course%20%232%20-%20Learning%20COBOL/Labs/cbl) repository. +# Case Sensitive Nature of COBOL Conditions + +COBOL syntax is not case-sensitive for keywords and identifiers, but string literal comparisons in conditional expressions ARE case-sensitive. This distinction between language syntax and data comparisons can lead to programming errors that cause issues when your program interacts with: + +- **External input data**, such as text files or database records +- **Conditional expressions** that depend on exact string matches +- **Third-party systems** that expect a specific case format + +## Why It Matters + +The most dangerous aspect of case sensitivity errors is that they often go unnoticed during initial testing. Programs **compile successfully**, **run without errors**, but **produce incorrect results**. These kinds of "silent failures" can persist in production systems for long periods, potentially resulting in: + +- Inaccurate or misleading reports +- Logic failures (e.g., skipping conditional branches) +- Reports that appear complete but miss values +- Data corruption or misrouting + +### Real-World Example + +Modern COBOL treats statements like: +`MOVE MY-NUMBER TO YOUR-NUMBER` +and +`Move my-Number to your-Number` as **equivalent** because keywords and identifiers are case-insensitive. + +However, **COBOL conditions** are case-sensitive when checking **string values**: + +`IF USA-STATE = 'new York'` = Fails, mismatch due to case + +`IF USA-STATE = 'New York'` = Succeeds, case matches + +The comparison **fails silently** COBOL won't throw an error, but the result won't be as expected. + +## Lab + +**Case Sensitivity in Data Comparison:** +Understand how case sensitivity in COBOL string comparisons can cause logical errors and learn to identify and fix these issues. + +**Scenario:** You'll investigate why a program designed to count "New York" clients returns zero when New York clients actually exist in the input data file (id.DATA). + +**Required Files:** + +- `CBL006A.cobol` - COBOL program source +- `CBL006AJ.jcl` - JCL job to compile and execute +- `id.DATA` - Input data file + +All files are available in your VS Code Zowe Explorer. + +### Instructions + +1. Open `CBL006A.cobol` from your VS Code Zowe Explorer. + + This program reads account records and counts how many clients are from `"New York"`. + +2. Submit the JCL job `CBL006AJ.jcl`. View the job output from the JOBS section. +- Confirm that no syntax or runtime errors occurred. +- Now carefully read the final line of the report. `New York Clients = 000` + + ![](Images/image071.png) + +Ask yourself: *Is this the number of New York clients you expected?* + +3. Based on your understanding, where do you think the bug lies? +- Consider the case format of both the **comparison string** and the **actual data** from the file (id.DATA). +4. Go and update the source code `CBL006A.cobol` . +- Modify the string literal in the IF condition to match the exact case format found in the data file +5. Save your changes to `CBL006A.cobol` +6. Recompile and resubmit the job `CBL006AJ.jcl` +7. Verify that the report now correctly shows: `New York Clients = 005` + +![](Images/image072.png) + \newpage # Arithmetic expressions diff --git a/COBOL Programming Course #2 - Learning COBOL/Images/image071.png b/COBOL Programming Course #2 - Learning COBOL/Images/image071.png new file mode 100644 index 00000000..d30c7a18 Binary files /dev/null and b/COBOL Programming Course #2 - Learning COBOL/Images/image071.png differ diff --git a/COBOL Programming Course #2 - Learning COBOL/Images/image072.png b/COBOL Programming Course #2 - Learning COBOL/Images/image072.png new file mode 100644 index 00000000..d41b42fb Binary files /dev/null and b/COBOL Programming Course #2 - Learning COBOL/Images/image072.png differ diff --git a/COBOL Programming Course #2 - Learning COBOL/Labs/cbl/CBL006A.cobol b/COBOL Programming Course #2 - Learning COBOL/Labs/cbl/CBL006A.cobol new file mode 100644 index 00000000..d257887f --- /dev/null +++ b/COBOL Programming Course #2 - Learning COBOL/Labs/cbl/CBL006A.cobol @@ -0,0 +1,173 @@ + *----------------------- + IDENTIFICATION DIVISION. + *----------------------- + PROGRAM-ID. CBL006A + AUTHOR. Otto B. Boolean. + *-------------------- + ENVIRONMENT DIVISION. + *-------------------- + INPUT-OUTPUT SECTION. + FILE-CONTROL. + SELECT PRINT-LINE ASSIGN TO PRTLINE. + SELECT ACCT-REC ASSIGN TO ACCTREC. + *------------- + DATA DIVISION. + *------------- + FILE SECTION. + FD PRINT-LINE RECORDING MODE F. + 01 PRINT-REC. + 05 ACCT-NO-O PIC X(8). + 05 FILLER PIC X(02) VALUE SPACES. + 05 LAST-NAME-O PIC X(20). + 05 FILLER PIC X(02) VALUE SPACES. + 05 ACCT-LIMIT-O PIC $$,$$$,$$9.99. + 05 FILLER PIC X(02) VALUE SPACES. + 05 ACCT-BALANCE-O PIC $$,$$$,$$9.99. + 05 FILLER PIC X(02) VALUE SPACES. + * + FD ACCT-REC RECORDING MODE F. + 01 ACCT-FIELDS. + 05 ACCT-NO PIC X(8). + 05 ACCT-LIMIT PIC S9(7)V99 COMP-3. + 05 ACCT-BALANCE PIC S9(7)V99 COMP-3. + 05 LAST-NAME PIC X(20). + 05 FIRST-NAME PIC X(15). + 05 CLIENT-ADDR. + 10 STREET-ADDR PIC X(25). + 10 CITY-COUNTY PIC X(20). + 10 USA-STATE PIC X(15). + 05 RESERVED PIC X(7). + 05 COMMENTS PIC X(50). + * + WORKING-STORAGE SECTION. + 01 FLAGS. + 05 LASTREC PIC X VALUE SPACE. + * + * CHANGE 1: Modified variable structure to count New York clients + * Original counted Virginia clients - now counts New York clients + 01 CLIENTS-PER-STATE. + 05 FILLER PIC X(19) VALUE + 'New York Clients = '. + 05 NEWYORK-CLIENTS PIC 9(3) VALUE ZERO. + 05 FILLER PIC X(59) VALUE SPACES. + * + 01 HEADER-1. + 05 FILLER PIC X(20) VALUE 'Financial Report for'. + 05 FILLER PIC X(60) VALUE SPACES. + * + 01 HEADER-2. + 05 FILLER PIC X(05) VALUE 'Year '. + 05 HDR-YR PIC 9(04). + 05 FILLER PIC X(02) VALUE SPACES. + 05 FILLER PIC X(06) VALUE 'Month '. + 05 HDR-MO PIC X(02). + 05 FILLER PIC X(02) VALUE SPACES. + 05 FILLER PIC X(04) VALUE 'Day '. + 05 HDR-DAY PIC X(02). + 05 FILLER PIC X(56) VALUE SPACES. + * + 01 HEADER-3. + 05 FILLER PIC X(08) VALUE 'Account '. + 05 FILLER PIC X(02) VALUE SPACES. + 05 FILLER PIC X(10) VALUE 'Last Name '. + 05 FILLER PIC X(15) VALUE SPACES. + 05 FILLER PIC X(06) VALUE 'Limit '. + 05 FILLER PIC X(06) VALUE SPACES. + 05 FILLER PIC X(08) VALUE 'Balance '. + 05 FILLER PIC X(40) VALUE SPACES. + * + 01 HEADER-4. + 05 FILLER PIC X(08) VALUE '--------'. + 05 FILLER PIC X(02) VALUE SPACES. + 05 FILLER PIC X(10) VALUE '----------'. + 05 FILLER PIC X(15) VALUE SPACES. + 05 FILLER PIC X(10) VALUE '----------'. + 05 FILLER PIC X(02) VALUE SPACES. + 05 FILLER PIC X(13) VALUE '-------------'. + 05 FILLER PIC X(40) VALUE SPACES. + * + 01 WS-CURRENT-DATE-DATA. + 05 WS-CURRENT-DATE. + 10 WS-CURRENT-YEAR PIC 9(04). + 10 WS-CURRENT-MONTH PIC 9(02). + 10 WS-CURRENT-DAY PIC 9(02). + 05 WS-CURRENT-TIME. + 10 WS-CURRENT-HOUR PIC 9(02). + 10 WS-CURRENT-MINUTE PIC 9(02). + 10 WS-CURRENT-SECOND PIC 9(02). + 10 WS-CURRENT-CENTISECOND PIC 9(02). + * This data layout is organized according to the ouput + * format of the FUNCTION CURRENT-DATE. + * + *------------------ + PROCEDURE DIVISION. + *------------------ + OPEN-FILES. + OPEN INPUT ACCT-REC. + OPEN OUTPUT PRINT-LINE. + * + WRITE-HEADERS. + MOVE FUNCTION CURRENT-DATE TO WS-CURRENT-DATE-DATA. + * The CURRENT-DATE function returns an alphanumeric value + * that represents the calendar date and time of day + * provided by the system on which the function is + * evaluated. + MOVE WS-CURRENT-YEAR TO HDR-YR. + MOVE WS-CURRENT-MONTH TO HDR-MO. + MOVE WS-CURRENT-DAY TO HDR-DAY. + WRITE PRINT-REC FROM HEADER-1. + WRITE PRINT-REC FROM HEADER-2. + MOVE SPACES TO PRINT-REC. + WRITE PRINT-REC AFTER ADVANCING 1 LINES. + WRITE PRINT-REC FROM HEADER-3. + WRITE PRINT-REC FROM HEADER-4. + MOVE SPACES TO PRINT-REC. + * + READ-NEXT-RECORD. + PERFORM READ-RECORD + PERFORM UNTIL LASTREC = 'Y' + * CHANGE 2: Updated paragraph name to reflect New York processing + * Original was IS-STATE-VIRGINIA, now IS-STATE-NEWYORK + PERFORM IS-STATE-NEWYORK + PERFORM WRITE-RECORD + PERFORM READ-RECORD + END-PERFORM + . + * + CLOSE-STOP. + WRITE PRINT-REC FROM CLIENTS-PER-STATE. + CLOSE ACCT-REC. + CLOSE PRINT-LINE. + GOBACK. + * + READ-RECORD. + READ ACCT-REC + AT END MOVE 'Y' TO LASTREC + END-READ. + * + * CHANGE 3: Updated paragraph name and logic to check for New York + * Original paragraph: IS-STATE-VIRGINIA + * - Checked for 'Virginia' state + * - Added to VIRGINIA-CLIENTS counter + * Modified paragraph: IS-STATE-NEWYORK + * - Now checks for 'New York' state + * - Adds to NEWYORK-CLIENTS counter + + IS-STATE-NEWYORK. + IF USA-STATE = 'new York' THEN + ADD 1 TO NEWYORK-CLIENTS + END-IF. + + * Boolean logic -- when the conditional expression + * USA-STATE = 'New York' is true, the program + * counts one more client from New York + * Note -- the inclusion of the word THEN is optional + * END-IF -- explicitly terminates the IF statement + * + WRITE-RECORD. + MOVE ACCT-NO TO ACCT-NO-O. + MOVE ACCT-LIMIT TO ACCT-LIMIT-O. + MOVE ACCT-BALANCE TO ACCT-BALANCE-O. + MOVE LAST-NAME TO LAST-NAME-O. + WRITE PRINT-REC. + * \ No newline at end of file diff --git a/COBOL Programming Course #2 - Learning COBOL/Labs/jcl/CBL006AJ.jcl b/COBOL Programming Course #2 - Learning COBOL/Labs/jcl/CBL006AJ.jcl new file mode 100644 index 00000000..2e42ee56 --- /dev/null +++ b/COBOL Programming Course #2 - Learning COBOL/Labs/jcl/CBL006AJ.jcl @@ -0,0 +1,21 @@ +//CBL006AJ JOB 1,NOTIFY=&SYSUID +//***************************************************/ +//* Copyright Contributors to the COBOL Programming Course +//* SPDX-License-Identifier: CC-BY-4.0 +//***************************************************/ +//COBRUN EXEC IGYWCL +//COBOL.SYSIN DD DSN=&SYSUID..CBL(CBL006A),DISP=SHR +//LKED.SYSLMOD DD DSN=&SYSUID..LOAD(CBL006A),DISP=SHR +//***************************************************/ +// IF RC = 0 THEN +//***************************************************/ +//RUN EXEC PGM=CBL006A +//STEPLIB DD DSN=&SYSUID..LOAD,DISP=SHR +//ACCTREC DD DSN=&SYSUID..DATA,DISP=SHR +//PRTLINE DD SYSOUT=*,OUTLIM=15000 +//SYSOUT DD SYSOUT=*,OUTLIM=15000 +//CEEDUMP DD DUMMY +//SYSUDUMP DD DUMMY +//***************************************************/ +// ELSE +// ENDIF