® IBM Software Group Enterprise COBOL Education Using Rational Developer for System Z Intermediate COBOL Record and Table Handling Patterns Jon Sayles, IBM Software Group, Rational EcoSystems Team © 2006 IBM Corporation IBM Trademarks and Copyrights © Copyright IBM Corporation 2007,2008. All rights reserved. The information contained in these materials is provided for informational purposes only, and is provided AS IS without warranty of any kind, express or implied. IBM shall not be responsible for any damages arising out of the use of, or otherwise related to, these materials. Nothing contained in these materials is intended to, nor shall have the effect of, creating any warranties or representations from IBM or its suppliers or licensors, or altering the terms and conditions of the applicable license agreement governing the use of IBM software. References in these materials to IBM products, programs, or services do not imply that they will be available in all countries in which IBM operates. This information is based on current IBM product plans and strategy, which are subject to change by IBM without notice. Product release dates and/or capabilities referenced in these materials may change at any time at IBM’s sole discretion based on market opportunities or other factors, and are not intended to be a commitment to future product or feature availability in any way. IBM, the IBM logo, the on-demand business logo, Rational, the Rational logo, and other IBM Rational products and services are trademarks or registered trademarks of the International Business Machines Corporation, in the United States, other countries or both. Other company, product, or service names may be trademarks or service marks of others. 2 Course Contributing Authors Thanks to the following individuals, for assisting with this course: David Myers/IBM 3 Purpose of This Document Course Name: COBOL Foundation Training - with RDz Course Description: Learn the COBOL language, RDz and learn z/OS terms, concepts and development skills in this course. Pre-requisites: Some experience in a 3rd or 4th Generation Language is expected. SQL is also recommended. Course Length: 10 days Topics (Agenda) Getting Started - installing and configuring RDz - and the course materials, and using Eclipse to edit COBOL COBOL General Language Rules Basic COBOL Statements Additional record and table handling Debugging Programs - Note: Deep dive on using RDz for common COBOL programming errors (001, 0C4, 0C7, infinite loops, fall-thru, etc.) Input/Output and Report Writing Patterns COBOL Subprograms and the Linkage Section Structured Programming Concepts, professional COBOL development practices and Coding Patterns Advanced Character Manipulation, COBOL Intrinsic Functions, Date and Time coding patterns, and Language Environment calls OS/390 Concepts and JCL - Compile/Link & Run Procs on the mainframe Indexed file Coding Patterns Sort/Merge, Sequential File Match/Merge and Master File Update Coding Patterns Accessing DB2 Data and DB2 Stored Procedures COBOL in the Real World: – CICS - lecture only – IMS (DL/I and TM) - ditto – Batch processing - ditto – Java calling COBOL – COBOL and XML Statements – SOA and COBOL - creating and calling Web Services – Web 2.0 using Rich UI 4 Course Details Audience This course is designed for application developers who have programmed in some language before, and who wish to learn COBOL. Prerequisites This course assumes that the student has the basic knowledge of IS technologies, data processing, software and have programmed for at least two or more years in a language such as: Java, VB, RPG, PL/1, Pascal, or some 4th Generation Language or tool. Knowledge of SQL (Structured Query Language) for database access is assumed as well. Basic PC and mouse-driven development skills is also assumed. Finally, it is assumed that you have been following along in this course, and have successfully completed the learning modules in sequence. Or have the equivalent COBOL background obtained through some other form of COBOL study or on-the-job work. 5 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 6 COBOL Records – Review COBOL records are hierarchical structures that allow you to organize ("model") sophisticated real-world complex data Records have a 01 level number definition Coded beginning in the "A" margin Typically with no PIC clause 01 Employee-Data. And records continue with one-to-many elementary items – some of which may be "group" data items (with no PIC clause) Here's an example shown in COBOL and graphically (with data) 01 Employee-Data. 05 Name. 10 Last-Name 10 Mid-Init 10 First-Name 05 Phone. 10 Area-Code 10 Phone-Number Data 10-level 05-level J o n e Last-Name PIC X(10). PIC X(01). PIC X(10). PIC 9(03) PIC 9(07) s b b b b b K R o b e r t b b M First-Name Name b b 2 0 AreaCode 1 4 5 6 Employee-Data 7 2 3 Phone-Number Phone 01-level 3 1 REDEFINED Fields In many of the COBOL applications you will work in, you will encounter situations where fields in records are REDEFINED (the actual COBOL keyword is REDEFINES) – with different PIC clauses. REDEFINES means that the same area of storage in the DATA DIVISION can be referenced in two or different ways. 01 Employee-Data. Here's an example: 05 Emp-Street-Addr. Assume an HR application stores employee mailing addresses As up-to three lines of street-address, or a P.O. Box 10 10 10 05 Street-Line-1 Street-Line-2 Street-Line-3 PIC X(10). PIC X(10). PIC X(11) Emp-Rural-Addr REDEFINES Emp-Street-Addr. 10 Postal-Box PIC 9(06) 10 Filler PIC 9(25) Two records from the employee external file in succession: Rec 1 0 0 1 b #1 Street-Line-1 S Rec A 3 4 T #2 Postal-Box 7 9 O U T H M A I N b S T R E T Street-Line-1 b b b b b b b b A P T . b 5 6 3 2 b b b b b b b b Street-Line-1 b b b b Filler Employee-Data Why REDEFINE fields? See Slide Notes. 8 b b b b b b b Defining and Using REDEFINED Fields 05 Name. 10 FIRST-NAME 10 MID-INIT 10 LAST-NAME 05 Company-Name REDEFINES Name 01 DATE-TABLE. 05 DATEVALS PIC X(30) VALUE "312831303130313130313031". 05 Month-Days REDEFINES DATEVALS PIC 9(2) The level numbers can not be: 88, 66, 01 (in the FILE SECTION) – but you can REDEFINE an 01 record in WORKING-STORAGE Immediately following the field –with no higher level numbers between (higher in the COBOL hierarchy) The data description entry for other-data-item cannot contain an OCCURS clause The redefining field should (does not have to, but should) have the same number of characters as the Redefined field You can have multiple redefinitions of the same field's character positions. However, they must all refer to other-data-item, the data-name that originally defined the area. The redefining entries cannot contain VALUE clauses except in condition-name entries. 01 How to tell which field to reference: (The redefining or the redefined) OCCURS 12. Language Rules – How to declare or REDEFINE a field: You redefine a field: At the same level number PIC X(10). PIC X(01). PIC X(10). PIC X(21). Typically your record will have a flag or some sort of indicator variable that distinguishes the record types. Usually this is one-byte "flag" – PIC X field that carries a value which describes the data that follows See the example on the right Business-Partner-Record. 05 Record-Type PIC X(01). 88 Individual-BP Value "I". 88 Company-BP Value "C". 05 Name. 10 FIRST-NAME PIC X(10). 10 MID-INIT PIC X(01). 10 LAST-NAME PIC X(10). 05 Company REDEFINES Name PIC X(21). … PROCEDURE DIVISION. … READ INFILE INTO Business-Partner-Record. If Individual-BP … use Name definition Else If Company-BP … use Company definition 9 REDEFINED Records In the WORKING-STORAGE SECTION (not in the FILE SECTION) you may redefine at the 01-record level. This was common practice in older systems that were memory or storage-constrained. Typically you might have (at least) 3 different records read: Header-Rec: With Job run-date information, Company Name, etc. Detail-Rec: With the base information to be processed Note that within the detail record, you might very well find additional REDEFINE fields Trailer-Rec: With more balancing total amounts, etc Here's an example H01/01/2008|Acme Motor Corporation|… D…………………………|……|…|…|……|………………|…|……|…… D…………………………|……|…|…|……|………………|…|……|…… … T0908432|984320432|…………………………………………… And to process: READ IN-FILE INTO HEADER-REC. … IF Rec-Type = "H" … Perform Header Record Processing ELSE IF Rec-Type = "D" … Perform Detail Record Processing Else … Perform Trailer Record Processing 10 WORKING-STORAGE SECTION. … 01 Header-Rec. 05 Rec-type PIC X(01). 05 Date-In PIC X(10). 05 Company-Name-In PIC X(30). 05 FILLER PIC X(269). 01 Detail-Rec REDEFINES Header-Rec. 05 Field-1 PIC X(01). 05 Field-2 PIC X(10). 05 Field-3 PIC X(30). 05 Field-4 PIC X(10). 05 Field-5 PIC X(30). … 01 Trailer-Rec REDEFINES Detail-Rec. 05 Rec-type PIC X(01). 05 In-Rec-Count PIC X(10). 05 In-Rec-Trial-Balance PIC X(30). 05 Filler PIC X(269). … Lab Assignment From the course workshop documents, do the following labs: 1. Data Representation and assignment (MOVE statement) Lab 2. Open ended workshop 11 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 12 Topic Objectives By the end of this unit you should be able to: Describe the COBOL OCCURS clause and code a syntactically correct example Describe the differences between a subscript and table index Create COBOL one-dimension table, by redefining values in Working-Storage Initialize and load data in a COBOL table Refer to specific table row/field table occurrences in the Procedure Division 13 COBOL Tables – Overview Like most programming languages, COBOL can group variables of the same type in internal program tables. COBOL supports the following kinds of table structures: 1. Single COBOL field tables 2. Fixed-length Structure field tables – the most common format 3. Variable-length tables – where the number of table occurrences is not known until run-time Fixed-Length COBOL Structure Table Three occurrences of two fields … From this example: Sample-Table-One is a group data item Table-Column is a group data item that is repeated three times You can conceptualize fields with an OCCURS clause as: – Blocks of contiguous storage – if you visualize the data from left to right – Rows – if you're visualizing the data in storage vertically Table-Item-1 and Table-Item-2 are elementary data fields – that are repeated three times, as they are child variables of Table-Column 14 COBOL Tables – Overview General information on COBOL tables: Are one(1)-based in subscripts - not zero-based The value within the parenthesis must be: > 0 and <= the table's OCCURS limit Attempts to access COBOL table data beyond its internal size results in a run-time error: S0C4 – index or array out of bounds Table rows (or columns) are known as "occurrences" Tables an have multiple dimensions Up to seven levels of table OCCURS nested within OCCURS in modern COBOL compilers Older COBOL only supported three levels – (Op-Ed) In standard business programming, tables > three levels deep are rare A COBOL table of 3 dimensions You can use special index datatype values to reference table row data, or you can use subscripts – which are numeric integer variables and values 15 Why COBOL Tables? There are generally two reasons for tables in any language, including COBOL: 1. To simplify repetitive processing patterns and organize related repetitive data 2. To handle design issues that require dynamic, run-time-sized structures Example: You want to process quarterly historical data – going back n years, your options are: Static COBOL Table Separate COBOL Variable WORKING-STORAGE SECTION. … 01 Quarterly-Data. 03 QRTRLY-Table OCCURS 20 TIMES INDEXED BY QTRLY-INDEX. 05 Q-Identifier PIC X(6). 05 Q-Value PIC 9(7)V99. … WORKING-STORAGE SECTION. Declarations … 01 Quarterly-Data. 05 Q12001 PIC 9(7)V99. 05 Q22001 PIC 9(7)V99. 05 Q32001 PIC 9(7)V99. 05 Q42001 PIC 9(7)V99. 05 Q22002 PIC 9(7)V99. 05 Q22002 PIC 9(7)V99. 05 Q22002 PIC 9(7)V99. 05 Q12003 PIC 9(7)V99. 05 Q22003 PIC 9(7)V99. 05 Q32003 PIC 9(7)V99. 05 Q42003 PIC 9(7)V99. 05 Q12004 PIC 9(7)V99. 05 Q22004 PIC 9(7)V99. 05 Q32004 PIC 9(7)V99. 05 Q42004 PIC 9(7)V99. 05 Q12005 PIC 9(7)V99. 05 Q22005 PIC 9(7)V99. 05 Q32005 PIC 9(7)V99. 05 Q42005 PIC 9(7)V99. 05 Q12006 PIC 9(7)V99. 05 Q22006 PIC 9(7)V99. … * Consider the math to total the above * …and worse? The quarterly maintenance * to the data and computations and routines Dynamically-sized COBOL Table WORKING-STORAGE SECTION. … 01 Quarterly-Data. 03 NBR-YEARS PIC S9(4) COMP. 03 QRTRLY-Table OCCURS 0 TO 40 TIMES DEPENDING ON NBR-YEARS INDEXED BY QTRLY-INDEX. 05 Q-Identifier PIC X(6). 05 Q-Value PIC 9(7)V99. … 16 What can you do with COBOL Tables? There are four basic categories of things to learn about COBOL tables: 1. Define COBOL tables Most of the time in WORKING-STORAGE Specific syntax examples follow 2. Load COBOL tables From files or databases Programmatically from within the PROCEDURE DIVISION 3. Initialize and re-initialize COBOL tables 4. Process COBOL tables – including: Using the values procedurally in business logic computations and data manipulation Searching the tables for matching values in the PROCEDURE DIVISION – upcoming section 17 Define One-Dimension COBOL Tables – Syntax To define a table: Give the table a group name, then define a subordinate item (the table element) to be repeated n times. 01 table-name. 05 element-name OCCURS n TIMES. . . . (subordinate items of the table element) In the example above – table-name is the name of an alphanumeric group item – There would (typically) be one-to-many subordinate items (fields at level 10 or higher) within a structure The table element definition (which includes the OCCURS clause) is subordinate to the group item that contains the table. OCCURS – Can appear on level: 02 49 – Cannot appear on levels: 01 or 77 Optional clause: INDEXED BY <idxName>. – If you declare a COBOL table and include the INDEXED BY clause, the COBOL compiler will create an internal subscript you will use to reference table occurrences – Using INDEXED BY can be substantially more efficient than using subscripts – particularly for large tables (> 1,000 rows) 18 Define One-Dimension COBOL Tables – Examples WORKING-STORAGE SECTION. 01 Territory-Totals. 05 Territory-Sales-Totals PIC 9(7)V99 OCCURS 4 INDEXED BY TERR-IDX. 01 Item-Table. 05 Items-Group OCCURS 30. 10 Item-Number PIC 99V99 COMP. 10 Item-Name PIC X(30). 10 Item-Price PIC 9(05)V99 COMP-3. 10 Item-Tax PIC V99. 01 SALES-TABLE. 05 REGION OCCURS 4 TIMES. 10 Q1-SALES PIC 9(5)V99 10 Q2-SALES PIC 9(5)V99 10 Q3-SALES PIC 9(5)V99 10 Q4-SALES PIC 9(5)V99 VALUE VALUE VALUE VALUE ZEROES. ZEROES. ZEROES. ZEROES. … PROCEDURE DIVISION. INITIALIZE SALES-TABLE. SET TERR-IDX TO 1. WORKING-STORAGE SECTION. 01 WEEK-DAY-VALUES. 05 FILLER PIC X(09) 05 FILLER PIC X(09) 05 FILLER PIC X(09) 05 FILLER PIC X(09) 05 FILLER PIC X(09) 05 FILLER PIC X(09) 05 FILLER PIC X(09) Examples of one-dimension COBOL table loaded by REDEFINE-ing hard-coded variable values VALUE VALUE VALUE VALUE VALUE VALUE VALUE "SUNDAY ". "MONDAY ". "TUESDAY ". "WEDNESDAY". "THURSDAY ". "FRIDAY ". "SATUDAY ". 01 Weekday-Table REDEFINES WEEK-DAY-VALUES. 05 WS-Day-of-Week PIC X(09) OCCURS 7 TIMES. 19 Load Tables Using Initialize – Syntax You can load a table: – Programmatically (from screen, file or database values) – next topic – REDEFINE constant field values with an OCCURS (previous slides) – Using Initialize – see example below – Using the VALUE clause on elementary field definitions. Initialize examples, to move the value 3 into each of the elementary numeric data items in a table called TABLE-ONE, shown below, you can code the following statement: INITIALIZE TABLE-ONE REPLACING NUMERIC DATA BY 3. To move the character 'X' into each of the elementary alphanumeric data items in TABLE-ONE, you can code the following statement: INITIALIZE TABLE-ONE REPLACING ALPHANUMERIC DATA BY "X". When you use the INITIALIZE statement to initialize a table, the table is processed as a group item (that is, with group semantics); elementary data items within the group are recognized and processed. You can use the REPLACING phrase of the INITIALIZE statement similarly to initialize all of the elementary fields with these datatypes in a table: ALPHABETIC, DBCS, ALPHANUMERIC-EDITED, NATIONAL-EDITED, NUMERIC-EDITED The INITIALIZE statement cannot assign values to a variable-length table A table that was defined using OCCURS DEPENDING ON 20 Load Tables Using INITIALIZE – Example Consider the following table declaration: 01 TABLE-ONE. 02 Trans-out Occurs 20. 05 Trans-code PIC 05 Part-number PIC 05 Trans-qty PIC 05 Price-fields. 10 Unit-price PIC 10 Discount PIC 10 Sales-Price PIC .... PROCEDURE DIVISION. .... X Value "R". XX Value "13". 99 Value 10. Note – VALUE clauses initially load the table with specific variable data 99V Value 50. 99V Value 25. 999 Value 375 INITIALIZE TABLE-ONE Replacing Numeric Data By 3 Alphanumeric Data By "X". The table below shows the content that each of the twenty 12-byte elements Trans-out(n) has before execution and after execution of the INITIALIZE statement shown above: 21 Load Tables Dynamically If the initial values of your table are different with each execution of your program, you can define the table without initial values. You can read the changed values into the table before your program refers to the table – at the beginning of the PROCEDURE DIVISION Use the PERFORM statement and either subscripting or indexing. When reading data to load your table, test to make sure that the data does not exceed the space allocated for the table (defined by OCCURS) WORKING-STORAGE SECTION. … 77 PROJECT-INDEX PIC S9(4) COMP. 77 TABLE-MAX PIC S9(4) COMP VALUE 20. 77 SW-END-OF-FILE PIC X(01) VALUE SPACES. 88 END-OF-FILE VALUE 'Y'. 01 EMP-PROJECT-TABLE. 05 EMP-PROJECT-ITEM OCCURS 20 TIMES. 10 EMP-PROJECT PIC X(4). 10 EMP-NAME PIC X(15). … PROCEDURE DIVISION. … READ INPUT-FILE AT END MOVE 'Y' TO SW-END-OF-FILE. INITIALIZE EMP-PROJECT-TABLE. PERFORM VARYING PROJECT-INDEX FROM 1 BY 1 UNTIL PROJECT-INDEX = TABLE-MAX OR END-OF-FILE MOVE INPUT-REC-PROJECT TO EMP-PROJECT (PROJECT-INDEX) MOVE INPUT-REC-NAME TO EMP-NAME (PROJECT-INDEX) READ INPUT-FILE AT END MOVE 'Y' TO SW-END-OF-FILE END-PERFORM. Use a named value (rather than a literal) for the item count. If you end up making the table bigger, you need to change only one value, instead of all references to a literal … What's the deal with Perform Varying? This optional PERFORM statement clause manipulates a named subscript (or index), and increments it: • Starting at the FROM value • Up (or down!) the BY value • Ending when the UNTIL condition tests true You will use the PERFORM VARYING pattern quite a bit – in custom table loading and manipulation 22 Referring to Values in a One-Dimension COBOL Table - Considerations The lowest possible subscript or index value is 1, which references the first occurrence of a table element. In a one-dimensional table, the subscript/index corresponds to the row number. You can use a literal or a data-name as a subscript. If a data item that has a literal subscript is of fixed length, the compiler resolves the location of the data item. When you use a data-name as a variable subscript, you must describe the data-name as an elementary numeric integer. If you have defined the COBOL table with INDEXED BY <indexName> - you will use the indexName as the subscript You can increment or decrement an index, or literal or variable subscript by a specified integer amount. For example: TABLE-COLUMN (SUB1 - 1, SUB2 + 3) You can change part of a table element rather than the whole element. To do so, refer to the character position and length of the substring to be changed. For example: 01 ANY-TABLE. 05 TABLE-ELEMENT PIC X(10) OCCURS 3 TIMES VALUE "ABCDEFGHIJ" .... MOVE "??" TO TABLE-ELEMENT (1) (3 : 2). The MOVE statement in the example above moves the string '??' into table element number 1, beginning at character position 3, for a length of 2 characters. We will cover reference modification (3 : 2) later in this course 23 Rules for Subscripts and Indexes Each subscript/index must be either A positive integer A data name which represents a positive integer A simple expression which evaluates to a positive integer The subscript/index must contain a value between 1 and the number of elements in the table/array inclusive. When more than one subscript/index is used they must be separated from one another by commas. One subscript/index must be specified for each dimension of the table. 1 subscript/index for a one dimension table 2 subscripts/indices for a two dimension table 3 subscripts/indices for a three dimension table … Subscripts and indexes must be enclosed in parentheses/brackets Indexes are manipulated using the COBOL SET keyword: SET QTY-IDX TO 1. SET QTY-IDX UP BY 1. SET QTY-IDX DOWN BY 1. 24 01 Error-Flag-Table 88 No-Errors 05 Type-Error 05 Shift-Error 05 Home-Code-Error 05 Work-Code-Error 05 Name-Error 05 Initials-Error 05 Duplicate-Error 05 Not-Found-Error 01 Putting it All Together – a complete example Value Spaces. Value Spaces. PIC X. PIC X. PIC X. PIC X. PIC X. PIC X. PIC X. PIC X. Filler Redefines Error-Flag-Table. 05 Error-Flag Occurs 8 Times 77 ERROR-ON PIC X Value "E". Indexed By Flag-Index PIC X. *********************************************************** 01 Error-Message-Table. 05 Filler PIC X(25) Value "Transaction Type Invalid". 05 Filler PIC X(25) Value "Shift Code Invalid". 05 Filler PIC X(25) Value "Home Location Code Inval.". 05 Filler PIC X(25) Value "Work Location Code Inval.". 05 Filler PIC X(25) Value "Last Name - Blanks". 05 Filler PIC X(25) Value "Initials - Blanks". 05 Filler PIC X(25) Value "Duplicate Record Found". 05 Filler PIC X(25) Value "Commuter Record Not Found". 01 Filler Redefines Error-Message-Table. 05 Error-Message Occurs 8 Times Indexed By Message-Index PIC X(25). PROCEDURE DIVISION. . . . Perform Varying Sub From 1 By 1 Until No-Errors If Error-Flag (Sub) = Error-On Move Space To Error-Flag (Sub) Move Error-Message (Sub) To Print-Message Perform 260-Print-Report 25 End-If End-Perform . . . Referring to a One-Dimension COBOL Table in the Procedure Division From the course workshop documents, do the following labs: 1. Data Representation and assignment (MOVE statement) Lab 2. Open ended workshop 26 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 27 Topic Objectives By the end of this unit you should be able to: Describe the COBOL OCCURS clause and code a syntactically correct example for a twodimension table Create COBOL two-dimension tables, by redefining values in Working-Storage Initialize and load data in a two-dimension COBOL table Refer to specific table row/field table occurrences in the Procedure Division of two dim tables 28 Multiple Dimension COBOL Tables Many organizational patterns for data require the use of multi-dimensional arrays to model information accurately. Consider the following: One week of 7 days of many hours Historical data Years – Months – Weeks - Days Accounting period data Months – Weeks Weeks – Days University data Classes – Students Corporate data Territories – Accounts Projects – Employees Locations – Divisions Geographic data States – Cities One month of 4 weeks of 7 days 29 Two Dimension COBOL Table – Visual Example To create a COBOL data structure that is a two-dimension array simply define an OCCURS within an OCCURS variable definition From the snapshot visual-example note: SAMPLE-TABLE-TWO – is the highest group data item TABLE-ROW – is the outer occurring group TABLE-COLUMN – is the inner occurring group. It contains two elementary fields: TABLE-ITEM-1 – elementary field data TABLE-ITEM-2 – elementary field data You may have elementary or group data-items at any level within the two-dim table. 30 Multi-Dimension COBOL Tables – Additional Examples 01 GENERIC-TWO-DIMENSION-TABLE-STRUCTURE. 05 DIM-FIRST-LEVEL OCCURS 100 TIMES. 10 FIRST-LEVEL-ELEMENTARY-DATA PIC 10 DIM-2ND-LEVEL OCCURS 100 TIMES. 20 ELEMENTARY-ITEMS-2ND-LEVEL. 30 ELEMENTARY-1 PIC 30 ELEMENTARY-2 PIC 30 ELEMENTARY-3 PIC X(20) X(10). X(07). X(16). 01 STUDENT-GRADES. 05 CLASSES-TAKEN OCCURS 20 TIMES. 10 CLASS-DETAILS OCCURS 10 TIMES. 20 CLASS-NBR PIC X(10). 20 GRADE-VAL PIC X(2). 01 COMPANY-ORG-THREE-DIM-TABLE. 05 COMPANY-LOCATION OCCURS 4 TIMES. 10 LOCATION-ID PIC 10 TERRITORY-TABLE OCCURS 13 TIMES. 20 TERRITORY-NAME PIC 20 TERRITORY-REP OCCURS 4 TIMES. 30 PRIVATE-DATA. 40 ADDRESS PIC 40 CURRENT-ASSIGNMENT PIC 31 Try to draw a mentalimage of how the data is organized in these tables. This is important, if you are going to be able to code business logic that processes information organized in nested OCCURS data structures. X(05). X(20). X(20). X(60). Three-dimension COBOL table Loading and Referring to a Multi-Dimension COBOL Table As in a single-dimension COBOL table, you can load a Two-or-Three-Dimension table: – Programmatically (from screen, file or database values) – REDEFINE constant field values with an OCCURS (previous slides) – Using Initialize – see example below – Using the VALUE clause on elementary field definitions. The syntax and rules are the same for all-of-the-above methods: Examples, INITIALIZE TABLE-ONE REPLACING NUMERIC DATA BY 3. INITIALIZE TABLE-ONE REPLACING ALPHANUMERIC DATA BY "X". For loading a table programmatically, you will nest PERFORM statements within PERFORM statements (see next slide) Note also that nesting PERFORM statements is far & away the most common and flexible method of dynamically loading a table The rules for referring to multi-dimension COBOL tables are the same as singledimension OCCURS tables – and described on the next slide 32 Processing Multi-Dimension COBOL Tables WORKING-STORAGE SECTION. 77 TABLE-MAX PIC S9(4) COMP VALUE 100. 77 SW-END-OF-FILE PIC X(01) VALUE SPACES. 88 END-OF-FILE VALUE 'Y'. Note the following: 01 GENERIC-TWO-DIMENSION-TABLE-STRUCTURE. 05 DIM-FIRST-LEVEL OCCURS 100 TIMES INDEXED BY DIM-1-IDX. 10 FIRST-LEVEL-ELEMENTARY-DATA PIC X(20) 10 DIM-2ND-LEVEL OCCURS 100 TIMES INDEXED BY DIM-2-IDX. 20 ELEMENTARY-ITEMS-2ND-LEVEL. 30 ELEMENTARY-1 PIC X(10). 30 ELEMENTARY-2 PIC X(07). 30 ELEMENTARY-3 PIC X(16). … The PERFORM procedure nesting that mirrors the table structure nesting. You reference elementary data in the outer table dimension with a single subscript or index FIRST-LEVEL-ELEMENTARY-DATA (DIM-1-IDX) You reference elementary data in the inner table with multiple subscripts or indices, separated by commas ELEMENTARY-2 (DIM-1-IDX, DIM-2-IDX) Not shown – you could also refer to group level data at any level inside the table (with the appropriate indices) PROCEDURE DIVISION. … READ INPUT-FILE AT END MOVE 'Y' TO SW-END-OF-FILE. INITIALIZE EMP-PROJECT-TABLE. … PERFORM VARYING DIM-1-IDX FROM 1 BY 1 UNTIL DIM-1-IDX = TABLE-MAX OR END-OF-FILE MOVE INPUT-REC-PROJECT TO FIRST-LEVEL-ELEMENTARY-DATA (DIM-1-IDX) PERFORM VARYING DIM-2-IDX FROM 1 BY 1 UNTIL DIM-2-IDX = TABLE-MAX MOVE INPUT-REC-DATA-1(DIM-1-IDX, DIM-2-IDX) TO ELEMENTARY-1 (DIM-1-IDX, DIM-2-IDX) MOVE INPUT-REC-DATA-2(DIM-1-IDX, DIM-2-IDX) TO ELEMENTARY-2 (DIM-1-IDX, DIM-2-IDX) MOVE INPUT-REC-DATA-3(DIM-1-IDX, DIM-2-IDX) TO ELEMENTARY-3 (DIM-1-IDX, DIM-2-IDX) … READ INPUT-FILE AT END MOVE 'Y' TO SW-END-OF-FILE END-PERFORM. 33 Lab Assignment From the course workshop documents, do the following labs: 1. Data Representation and assignment (MOVE statement) Lab 2. Open ended workshop 34 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 35 Topic Objectives By the end of this unit you should be able to: Describe the concept behind COBOL variable-length OCCURS clause and code a syntactically correct example for variable length (Occurs Depending On) tables Create COBOL variable-length tables Initialize and load data in variable length COBOL table Refer to specific table row/field table occurrences in the PROCEDURE DIVISION – for variable length COBOL table data 36 OCCURS DEPENDING ON – Overview COBOL permits table definitions that occur an unknown-until-run-time – or variable number of times The exact number of table-row occurrences depends on the value in some other field in (typically) WORKING STORAGE. For example – here is a purchase-order record: 01 PURCHASE-ORDER. 05 NAME-ADDR-INFO PIC X(100). 05 LINE-ITEM-OCCURRENCES PIC 999. … 05 LINE-ITEMS-TABLE OCCURS 0 TO 100 TIMES DEPENDING ON LINE-ITEM-OCCURENCES. 10 ITEM-ID PIC 9999. 10 ITEM-NAME PIC X(30). 10 ITEM-DESCRIP PIC X(30). 10 ITEM-UNIT-PRICE PIC S9(7)V99. … Notes: The table LINE-ITEMS-TABLE contains four fields (Item-ID, Item-Name, Item-Description, Item-Unit-Price) which make up one line on a Purchase Order. Each Purchase Order can have from 0 to 100 line items. The actual number of line items for any given Purchase Order is read from a file, and given by the value of the field LINE-ITEM-OCCURRENCES. 37 COBOL Records – Considerations and Usage If you do not know before run-time how many times a table element occurs, define a variablelength table. To do so, use the OCCURS DEPENDING ON clause. X OCCURS 1 TO 10 TIMES DEPENDING ON Y In the example above, X is called the ODO subject Y is called the ODO object. Two factors affect the successful manipulation of variable-length records: 1. Correct calculation of record lengths T The length of the variable portions of a group item is the product of the – Object of the DEPENDING ON phrase plus the – Length of the subject of the OCCURS clause. In the example above, if X is a field or group of length 50 bytes, and Y is equal to 9 (based on the run-time value of the field name Y), the total length of the table is 450 bytes 2. Conformance of the data in the object of the OCCURS DEPENDING ON clause to its PICTURE clause If the content of the ODO object does not match its PICTURE clause, the program could terminate abnormally. You must ensure that the ODO object correctly specifies the current number of occurrences of table elements. 38 COBOL Records – Moving ODO fields – as Sending and Receiving Fields The following example shows a group item (REC-1) that contains both the subject and object of the OCCURS DEPENDING ON clause. The way the length of the group item is determined depends on whether it is sending or receiving data. WORKING-STORAGE SECTION. 01 MAIN-AREA. 03 REC-1. 05 FIELD-1 PIC 9. 05 FIELD-2 OCCURS 1 TO 5 TIMES DEPENDING ON FIELD-1 PIC X(05). 01 REC-2. 03 REC-2-DATA PIC X(50). If you want to move REC-1 (the sending item in this case) to REC-2, the length of REC-1 is determined immediately before the move, using the current value in FIELD-1. If the content of FIELD-1 conforms to its PICTURE clause (that is, if FIELD-1 contains a zoned decimal item), the move can proceed based on the actual length of REC-1. Otherwise, the result is unpredictable. You must ensure that the ODO object has the correct value before you initiate the move. When you do a move to REC-1 (the receiving item in this case), the length of REC-1 is determined using the maximum number of occurrences. In this example, five occurrences of FIELD-2, plus FIELD-1, yields a length of 26 bytes. In this case, you do not need to set the ODO object (FIELD-1) before referencing REC-1 as a receiving item. However, the sending field's ODO object (not shown) must be set to a valid numeric value between 1 and 5 for the ODO object of the receiving field to be validly set by the move. 39 OCCURS DEPENDING ON – Examples 01 Client-Transactions. 05 Client-Name PIC X(30). 05 Client-SS-Number PIC 9(9). 05 Number-of-Transactions PIC 99 COMP-3. 05 Transaction-History OCCURS 0 TO 50 TIMES DEPENDING ON Number-of-Transactions INDEXED BY Trans-IDX. 10 Transaction-Date. 15 Transaction-DAY PIC 99. 15 Transaction-MONTH PIC 99. 15 Transaction-YEAR PIC 9(4). 10 Transaction-Description PIC X(300). 10 Transaction-Type PIC 99. FILE SECTION. FD LOC-INPUT-FILE. 01 LOC-REC. 05 LOCATION-ID PIC X(02). 05 LOCATION-NAME PIC X(20). 05 LOCATION DESCRIPTION PIC X(58). WORKING-STORAGE SECTION. 01 FLAGS. 05 LOC-EOF-SW PIC X(01) VALUE SPACE. 88 LOCATION-EOF VALUE "F". 01 TABLE-HANDLING-VALUES. 05 LOC-TAB-LTH PIC 9(3) VALUE ZERO. 05 LOC-TAB-MAX PIC 9(3) VALUE 100. 01 LOC-TABLE-WS. 05 LOC-CODE OCCURS 1 TO 10 TIMES DEPENDING ON LOC-TABLE-LTH PIC X(80). 40 Example: Occurs Depending On – Definition and Loading From a File Read a record from a file. The record contains: The data for the ODO table The number of occurrences in the ODO table Perform a routine that moves the data from the file into the ODO table row until the max table-length (in number of occurrences for the new row as recorded in the record) is hit Read the next file/record 41 Complex OCCURS DEPENDING ON Complex ODO is supported as an extension to Standard COBOL 85. Several types of complex OCCURS DEPENDING ON (complex ODO) are possible. The basic forms of complex ODO permitted by the compiler are as follows: 1. Variably located item or group: A data item described by an OCCURS clause with the DEPENDING ON phrase is followed by a non-subordinate elementary or group data item. 2. Variably located table: A data item described by an OCCURS clause with the DEPENDING ON phrase is followed by a non-subordinate data item described by an OCCURS clause. 3. Table that has variable-length elements: A data item described by an OCCURS clause contains a subordinate data item described by an OCCURS clause with the DEPENDING ON phrase. 4. Index name for a table that has variable-length elements. 5. Element of a table that has variable-length elements. 42 Example: Complex ODO - Definition 01 FIELD-A. 02 COUNTER-1 PIC S99. 02 COUNTER-2 PIC S99. 02 TABLE-1. 03 RECORD-1 OCCURS 1 TO 5 TIMES DEPENDING ON COUNTER-1 PIC X(3). 02 EMPLOYEE-NUMBER PIC X(5). (1) 02 TABLE-2 OCCURS 5 TIMES (2)(3) INDEXED BY INDX. (4) 03 TABLE-ITEM PIC 99. (5) 03 RECORD-2 OCCURS 1 TO 3 TIMES DEPENDING ON COUNTER-2. 04 DATA-NUM PIC S99. In this example, COUNTER-1 is an ODO object, that is, it is the object of the DEPENDING ON clause of RECORD-1. RECORD-1 is said to be an ODO subject. Similarly, COUNTER-2 is the ODO object of the corresponding ODO subject, RECORD-2. The types of complex ODO occurrences shown in the example above are as follows: (1) - A variably located item: EMPLOYEE-NUMBER is a data item that follows, but is not subordinate to, a variable-length table in the same level-01 record. (2) - A variably located table: TABLE-2 is a table that follows, but is not subordinate to, a variable-length table in the same level-01 record. (3) - A table with variable-length elements: TABLE-2 is a table that contains a subordinate data item, RECORD-2, whose number of occurrences varies depending on the content of its ODO object. (4) - An index-name, INDX, for a table that has variable-length elements. (5) - An element, TABLE-ITEM, of a table that has variable-length elements. 43 Lab Assignment From the course workshop documents, do the following labs: 1. Data Representation and assignment (MOVE statement) Lab 2. Open ended workshop 44 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 45 Topic Objectives By the end of this unit you should be able to: Describe the COBOL SEARCH, SEARCH ALL and PERFORM VARYING processing for doing table searches Code a syntactically correct SEARCH and SEARCH ALL statement Describe the requirements for SEARCH ALL Define COBOL performance trade-offs with the above three methods of table searches 46 Searching COBOL Tables There are three ways to search through COBOL tables for values you want to find: 1. Perform Varying You've already seen this – essentially you manipulate an index or subscript within an inline PERFORM, or paragraph PERFORM 2. Sequential SEARCH COBOL has a reserved word (SEARCH) that automatically will search through a table starting from a pre-determined element, and going until: – SEARCH finds a match – The code hits an end-of-table condition 3. Binary SEARCH ALL COBOL also has a reserved phrase: SEARCH ALL that does a binary search through a COBOL table, until: – SEARCH ALL finds a match – The code hits an end-of table condition Details on SEARCH ALL upcoming… All three search coding idioms can accomplish the same technical result – finding data in table, but all three are very different in: Syntax Data pre-req's Run-time performance (efficiency) 47 Searching COBOL Tables – Side-by-Side Syntax View 77 01 01 State Table Data Alabama State-Search-Data PIC X(20). States-Table-Seq. 05 State-Name OCCURS 50 TIMES INDEXED BY St-Idx-Seq PIC X(20). States-Table-Bin. 05 State-Name-Bin OCCURS 50 TIMES Ascending key is State-Name-Bin INDEXED BY St-Idx-Bin PIC X(20). *** Option 2. SEQUENTIAL SEARCH **** Set St-Idx-Seq to 1. SEARCH States-Table Varing St-Idx-Seq At End … When State-Search-Data = State-Name(St-Idx-Seq) … American Samoa Arizona Arkansas California Colorado Connecticut Delaware District of Columbia SEARCH OPERATION … Procedure Division. … *** Option 1. PERFORM VARYING **** PERFORM VARYING St-idx-Seq from 1 by 1 Until St-idx > 50 If State-Search-Data = State-Name (St-Idx-Seq) … Alaska Florida Georgia Guam Hawaii Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine *** Option 3. BINARY SEARCH ALL **** SEARCH ALL States-Table At End … When State-Name(St-Idx-Bin) = State-Search-Data … 48 Maryland Massachusetts Michigan … Serial Search – Rules and Conditions Alabama Use the SEARCH statement to do a serial (sequential) search beginning at the current index setting. To modify the index setting before searching, use the SET statement. Alaska Other considerations: California The conditions in the WHEN phrase are evaluated in the order in which they appear: If none of the conditions is satisfied, the index is increased to correspond to the next table element, and the WHEN conditions are evaluated again. If one of the WHEN conditions is satisfied, the search ends. The index remains pointing to the table element that satisfied the condition. If the entire table has been searched and no conditions were met, the AT END imperative statement is executed if there is one. If you did not code AT END, control passes to the next statement in the program. You can reference only one level of a table (a table element) with each SEARCH statement. To search multiple levels of a table, use nested SEARCH statements. Colorado See Notes – on Performance Coding Considerations Arizona Arkansas Connecticut SEARCH OPERATION Delimit each nested SEARCH statement with END-SEARCH. American Samoa Delaware District of Columbia Florida Georgia Guam Hawaii Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine Maryland Massachusetts Michigan … 49 Sequential SEARCH – Simple Example 01 SALES-TAX. 05 FILLER 05 FILLER 05 FILLER 05 FILLER 05 FILLER PIC PIC PIC PIC PIC X(21) X(21) X(21) X(21) X(21) VALUE VALUE VALUE VALUE VALUE '280000005463968869950'. '329650006543603457350'. '557450007573101219150'. '7269000087652800363750'. '902650005431500000001'. 01 SALES-TAX-TABLE REDEFINES SALES-TAX. 05 SALES-TAX-ITEM OCCURS 5 TIMES INDEXED BY TX-IDX. 10 SALES-TAX-L-RANGE PIC 9(6)V9(2). 10 SALES-TAX-RATE PIC V9(6). 10 SALES-TAX-H-RANGE PIC 9(5)V9(2). PROCEDURE DIVISION. SEARCH ALL SALES-TAX-ITEM AT END PERFORM 700-INVALID-TAX-ID WHEN SALES-TAX-L-RANGE (TX-IDX) > IN-ITEM-TAX-ID PERFORM 200-COMPUTE-WITH-TAX-TOTALS. 50 Serial Search – Complex Example The following example shows how you might find a particular string in the innermost table of a threedimensional table. Each dimension of the table has its own index Set to 1, 4, and 1, respectively The innermost table TABLE-ENTRY3 has an ascending key 51 Binary Search (SEARCH ALL) – Rules and Conditions Alabama Alaska With SEARCH ALL to do a binary search, you do not need to set the index before you begin. Table-Rows OCCURS 50 Times ASCENDING KEY IS Key-Field Indexed by T-IDX In the WHEN phrase of the SEARCH ALL statement, you can test any key that is named in the ASCENDING or DESCENDING KEY phrases for the table The key portion of the comparison must follow after WHEN (see example below) You must test all preceding keys. The test must be an equal-to condition, and the WHEN phrase must specify either a key (subscripted by the first index-name associated with the table) or a condition-name (88 level) that is associated with the key. The WHEN condition can be a compound condition that is formed from simple conditions that use AND as the only logical connective. Each key and its object of comparison must be compatible according to the rules for comparison of data items. Arizona Arkansas California Colorado Connecticut Delaware SEARCH OPERATION The index is always the one that is associated with the first index-name in the OCCURS clause. The index varies during execution to maximize the search efficiency. To use the SEARCH ALL statement to search a table, the table must specify the ASCENDING or DESCENDING KEY phrases of the OCCURS clause, or both, and must already be ordered on the key or keys that are specified in the ASCENDING and DESCENDING KEY phrases: American Samoa District of Columbia Florida Georgia Guam Hawaii Idaho Illinois Indiana Iowa Kansas Kentucky Louisiana Maine Maryland Massachusetts Michigan … 52 See Notes Binary SEARCH ALL – Simple Example 01 SALES-TAX. 05 FILLER PIC 05 FILLER PIC 05 FILLER PIC 05 FILLER PIC 05 FILLER PIC X(18) X(18) X(18) X(18) X(18) VALUE VALUE VALUE VALUE VALUE '280000003968869950'. '329650003603457350'. '557450003101219150'. '726900002800363750'. '902650001500000000'. 01 SALES-TAX-TABLE REDEFINES SALES-TAX. 05 SALES-TAX-ITEM OCCURS 5 TIMES ASCENDING KEY IS SALES-TAX-L-RANGE INDEXED BY TX-IDX. 10 SALES-TAX-L-RANGE PIC 9(6)V9(2). 10 SALES-TAX-RATE PIC V9(3). 10 SALES-TAX-H-RANGE PIC 9(5)V9(2). PROCEDURE DIVISION. SEARCH ALL SALES-TAX-ITEM AT END PERFORM 700-INVALID-TAX-ID WHEN SALES-TAX-L-RANGE (TX-IDX) = IN-ITEM-TAX-ID PERFORM 200-COMPUTE-WITH-TAX-TOTALS. 53 Binary SEARCH ALL – Multi-Column Key Example The following example The following example shows how you can code a binary search of a table. Suppose you define a table that contains 90 elements of 40 bytes each, and three keys. The primary and secondary keys (KEY-1 and KEY-2) are in ascending order, but the least significant key (KEY-3) is in descending order: If an entry is found in which each of the three keys is equal to the value to which it is compared (VALUE-1, VALUE-2, and VALUE-3, respectively) PART-1 of that entry is moved to OUTPUT-AREA. If no matching key is found in the entries in TABLE-A, the NOENTRY routine is performed. 54 Performance Considerations – COBOL Table Processing From: http://www-949.ibm.com/software/rational/cafe/thread/2200?tstart=0 Of the three table search options: PERFORM Loops are the slowest option SEARCH ALL is fastest, but only for tables > 50-some elements (interesting) SEARCH (sequentially) is faster than SEARCH ALL for small tables, and considerably slower for very large tables A Perform loop (especially an inline one) may well be FASTER than some SEARCH statements. This probably depends on what you are varying. SEARCH ALL beats SEARCH (sequential) but SEARCH ALL does require your table to be sorted (already). SEARCH ALL only permits WHEN conditions that test for equality If your "input" isn't sorted (or however you build the table), then you need to consider the overhead to sort it before deciding whether to do a sequential SEARCH or a SEARCH ALL. If you search a large table many times, then doing the sort is probably a good idea. IBM provides a "nifty" way to do this - if you aren't familiar with the technique. Check out: Http://publibfp.boulder.ibm.com/cgi-bin/bookmgr/BOOKS/igy3pg40/1.12.10.2 55 Unit Additional Record and COBOL Table Handling Facilities Topics: Additional Record Concepts COBOL Tables – Definition and Language Concepts Multi-Dimension COBOL Tables Variable Length COBOL Tables Searching COBOL Tables Processing COBOL Tables With Intrinsic Functions 56 Processing Table Items Using Intrinsic Functions – Overview You can use intrinsic functions to process alphabetic, alphanumeric, national, or numeric table items. You can process DBCS data items only with the NATIONAL-OF intrinsic function. The data descriptions of the table items must be compatible with the requirements for the function arguments. Use a subscript or index to reference an individual data item as a function argument. For example, assuming that Table-One is a 3 x 3 array of numeric items, you can find the square root of the middle element by using this statement: Compute X = Function Sqrt(Table-One(2,2)) You might often need to iteratively process the data in tables. For intrinsic functions that accept multiple arguments, you can use the subscript ALL to reference all the items in the table or in a single dimension of the table. The iteration is handled automatically, which can make your code shorter and simpler. You can mix scalars and array arguments for functions that accept multiple arguments: Compute Table-Median = Function Median(Arg1 Table-One(ALL)) 57 Processing Table Items Using Intrinsic Functions – Example These examples show how you can apply an intrinsic function to some or all of the elements in a table by using the ALL subscript. Assuming that Table-Two is a 2 x 3 x 2 array, the following statement adds the values in elements Table-Two(1,3,1) Table-Two(1,3,2) Table-Two(2,3,1) Table-Two(2,3,2) Compute Table-Sum = FUNCTION SUM (Table-Two(ALL, 3, ALL)) The following example computes various salary values for all the employees whose salaries are encoded in Employee-Table: 01 Employee-Table. 05 Emp-Count Pic s9(4) usage binary. 05 Emp-Record Occurs 1 to 500 times depending on Emp-Count. 10 Emp-Name Pic x(20). 10 Emp-Idme Pic 9(9). 10 Emp-Salary Pic 9(7)v99. . . . … Procedure Division. … Compute Max-Salary = Function Max(Emp-Salary(ALL)) Compute I = Function Ord-Max(Emp-Salary(ALL)) Compute Avg-Salary = Function Mean(Emp-Salary(ALL)) Compute Salary-Range = Function Range(Emp-Salary(ALL)) Compute Total-Payroll = Function Sum(Emp-Salary(ALL)) 58 Java .NET COBOL Equivalents COBOL JAVA VB.NET REDEFINE N/A N/A Single Dimension OCCURS (COBOL Tables) aVariable type = new type [n]; aVariable type = new type [n]; Multiple Dimension OCCURS (COBOL Tables) aVariable type = new type [n, n]; aVariable type = new type [n, n]; Table INITIALIZE N/A N/A Table Load with Value Clauses aVariable type = new type [n] {1, 2, 3, 4, …}; aVariable type = new type [n] {1, 2, 3, 4, …}; Table load with Perform Varying For loop – within statement block: aVariable[n] = value; For loop – within statement block: aVariable[n] = value; Search with Perform Varying For loop or do/while loop – within statement block: if ( aVariable[n] = value ) …; For loop or do/while loop – within statement block: if ( aVariable[n] = value ) …; SEARCH keyword N/A – use looping construct N/A – use looping construct SEARCH ALL " " 59