IBM Mainframe Forum Index
 
Log In
 
IBM Mainframe Forum Index Mainframe: Search IBM Mainframe Forum: FAQ Register
 

Table handling, need to search for a string


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
pullaiah.cts

New User


Joined: 02 Sep 2010
Posts: 50
Location: Pune

PostPosted: Thu Jan 26, 2012 4:31 pm
Reply with quote

Hi,

I have a table with 26 fields.

Table declaration:
Code:

10  WP-SECURITY     OCCURS 26 TIMES.     
    15  WP-TSECTA              PIC X(15).
    15  WP-NGIDN2              PIC X(12).
    15  FILLER                 PIC X(14).

01 SUBSCRIPTS COMP.                       
       05 IN-FILE-SUB              PIC S99.


I need to search for the string 'CUSIP' in each record,if CUSIP is found then we need to write it's corressponding value to o/p record.
In case,CUSIP is not found then we need to check for 'INTERNAL' and write the corressonding value to o/p value.
If both are not present then read the next record.

Program Logic:
Code:

3000-READ-CUSIP-PRICE.                             
     MOVE "N" TO ITEM-FOUND-SWITCH.               
     PERFORM 3010-SEARCH-PRICE-FLDS               
     WITH TEST AFTER                               
     VARYING IN-FILE-SUB FROM 1 BY 1               
     UNTIL ITEM-FOUND                             
     OR IN-FILE-SUB = 26.                         
     IF ITEM-FOUND                                 
     PERFORM 4000-WRITE-OUTPUT-FILE THRU 4000-EXIT.                                                   
3000-EXIT. EXIT.                                   

*SEARCHING FOR CUSIP FIELD IN I/P RECORD           
3010-SEARCH-PRICE-FLDS.                           
      IF WP-TSECTA (IN-FILE-SUB) = 'CUSIP'       
      THEN MOVE "Y" TO ITEM-FOUND-SWITCH         
      ELSE IF WP-TSECTA (IN-FILE-SUB) = 'INTERNAL'
         MOVE "Y" TO ITEM-FOUND-SWITCH           
      END-IF.


But the program us not working as expected.It's checking for both 'CUSIP' and iINTERNAL' and taking whichever exists first.
But,it should not be like that.First it should check for 'CUSIP',if not found then only it will go for 'INTERNAL'.

Can anyone please let me know what are all the changes I need to make in my coding?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Jan 26, 2012 4:39 pm
Reply with quote

Well, first you need to check for CUSIP in all entries of the table that are populated. Only if you don't find CUSIP should you check for INTERNAL. If you test for both at the same time, you will find INTERNAL on occasion when a later table entry contains CUSIP which hasn't yet been looked at.
Back to top
View user's profile Send private message
pullaiah.cts

New User


Joined: 02 Sep 2010
Posts: 50
Location: Pune

PostPosted: Thu Jan 26, 2012 5:17 pm
Reply with quote

Hi Bill,

I have made the changes as below but still facing the same problem.

Code:

* CHECKING FOR CUSIP PRICE FIELD.                   
  3000-READ-CUSIP-PRICE.                             
       MOVE "N" TO ITEM-FOUND-SWITCH.               
       PERFORM 3010-SEARCH-PRICE-FLDS               
       WITH TEST AFTER                               
       VARYING IN-FILE-SUB FROM 1 BY 1               
       UNTIL ITEM-FOUND                             
       OR IN-FILE-SUB = 26.                         
       IF ITEM-FOUND                                 
       PERFORM 4000-WRITE-OUTPUT-FILE THRU 4000-EXIT.
                                                     
  3000-EXIT. EXIT.                                   
                                                     
* SERCHING FOR CUSIP FIELD IN I/P RECORD             
  3010-SEARCH-PRICE-FLDS.                           
        IF WP-TSECTA (IN-FILE-SUB) = 'CUSIP'         
        THEN MOVE "Y" TO ITEM-FOUND-SWITCH           
        ELSE                                         
        PERFORM 3020-SEARCH-INTER-FLDS THRU 3020-EXIT.
                                                     
* SERCHING FOR INTERNAL                               
  3020-SEARCH-INTER-FLDS.                             
       MOVE "N" TO ITEM-FOUND-SWITCH.                 
       PERFORM 3030-SEARCH-INTERNAL                   
       WITH TEST AFTER                               
       VARYING IN-FILE-SUB FROM 1 BY 1               
       UNTIL ITEM-FOUND                               
       OR IN-FILE-SUB = 26.                           
                                                   
  3020-EXIT. EXIT.                                   
                                                     
* SERCHING FOR INTERNAL                               
  3030-SEARCH-INTERNAL.                       
       IF WP-TSECTA (IN-FILE-SUB) = 'INTERNAL'
       THEN MOVE "Y" TO ITEM-FOUND-SWITCH     
       END-IF.                               
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Jan 26, 2012 5:22 pm
Reply with quote

Because you have to complete the search of the table for CUSIP before starting the search of the table for INTERNAL. You are still doing each, for each increasing subscript. You'll still find INTERNAL at one (if there) even if CUSIP at 26.
Back to top
View user's profile Send private message
pullaiah.cts

New User


Joined: 02 Sep 2010
Posts: 50
Location: Pune

PostPosted: Thu Jan 26, 2012 5:27 pm
Reply with quote

Hi Bill,

I am assuming that I am searching for 'INTERNAL' only after finishing searching for 'CUSIP'. Can you please let me know where I am wrong in the code?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Thu Jan 26, 2012 5:39 pm
Reply with quote

You perform 3010 from 1 to 26.

You test entry 1 for CUSIP, then if not, you go for and test for INTERNAL, before entry 2-26 are looked at for Cusip.

You need:

Code:
1-26 for CUSIP

IF not CUSIP found
    1-26 for INTERNAL


You have

Code:
1 for CUSIP, if not
    1-26 for INTERNAL, if not
    2 for CUSIP, then 1-26 for INTERNAL again,
    etc.
Back to top
View user's profile Send private message
Jose Mateo

Active User


Joined: 29 Oct 2010
Posts: 121
Location: Puerto Rico

PostPosted: Thu Jan 26, 2012 7:43 pm
Reply with quote

Good day to all!

I really think that you first logic would work with one minor change and that would be to move the statement 'move 'n' to ITEM-FOUND-SWITCH' after the label '3010-SEARCH-PRICE-FLDS' because once you found a true condition the rest would be true due to you didn't reset the flag ITEM-FOUND-SWITCH to 'N'. Another thing is that your WP-TSECTA is 15 bytes long, could it contain 'CUSIP' or 'INTERNAL' plus some other characters as filler to the field?
Back to top
View user's profile Send private message
Marso

REXX Moderator


Joined: 13 Mar 2006
Posts: 1353
Location: Israel

PostPosted: Thu Jan 26, 2012 9:40 pm
Reply with quote

pullaiah.cts wrote:
Code:
3000-READ-CUSIP-PRICE.                             
     MOVE "N" TO ITEM-FOUND-SWITCH.               
     PERFORM 3010-SEARCH-PRICE-FLDS               
     WITH TEST AFTER                               
     VARYING IN-FILE-SUB FROM 1 BY 1               
     UNTIL ITEM-FOUND                             
     OR IN-FILE-SUB = 26.                         
     IF ITEM-FOUND                                 
     PERFORM 4000-WRITE-OUTPUT-FILE THRU 4000-EXIT.                                                   
3000-EXIT. EXIT.                                   

*SEARCHING FOR CUSIP FIELD IN I/P RECORD           
3010-SEARCH-PRICE-FLDS.                           
      IF WP-TSECTA (IN-FILE-SUB) = 'CUSIP'       
      THEN MOVE "Y" TO ITEM-FOUND-SWITCH         
      ELSE IF WP-TSECTA (IN-FILE-SUB) = 'INTERNAL'
         MOVE "Y" TO ITEM-FOUND-SWITCH           
      END-IF.


That is an ugly piece of code. icon_evil.gif
I hope you do better on the mainframe than on the forum.
Do you?
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jan 27, 2012 1:12 am
Reply with quote

Jose Mateo wrote:
Good day to all!

I really think that you first logic would work with one minor change and that would be to move the statement 'move 'n' to ITEM-FOUND-SWITCH' after the label '3010-SEARCH-PRICE-FLDS' because once you found a true condition the rest would be true due to you didn't reset the flag ITEM-FOUND-SWITCH to 'N'. Another thing is that your WP-TSECTA is 15 bytes long, could it contain 'CUSIP' or 'INTERNAL' plus some other characters as filler to the field?


I think you've completely misunderstood what is required and the existing code.

If there is any occurence of CUSIP in the table the first occurence should be located and a record written.

If there is no CUSIP, then the first occurence of INTERNAL should be located and a recored written.

If neither CUSIP nor INTERNAL are found, no record is written.

The change of location of the piece of code you suggest would cause the setting of the flag from the previous time through the code to be used, assuming there is no CUSIP in table-entry-1. The chance that this is what is wanted I would guess to be Nil.

In my experience it is perfectly normal for a field to be used which can contain values of different length followed by spaces.
Back to top
View user's profile Send private message
Jose Mateo

Active User


Joined: 29 Oct 2010
Posts: 121
Location: Puerto Rico

PostPosted: Fri Jan 27, 2012 2:41 am
Reply with quote

Hi, Bill!
Reading his requirement for the 2nd, 3rd and 4th time, yes I misunderstood what he wants to do. This second code is worst than the first and I agree with Marso. Now, by what I understood is that this table is in each record. First, he searches for the Literal 'CUSIP' in all the entries of the table. Once 'CUSIP' is found then he want to write the corresponding WP-NGIDN2 to the o/p and read another record. If the first search fails then he wants to search for the literal 'INTERNAL' in all the entries of the same table. Once 'INTERNAL' is found then he want to write the corresponding WP-NGIDN2 to the o/p and read another record. If the second search fails then he wants to read another i/p record and start the process again. Is this correct?
Back to top
View user's profile Send private message
Marso

REXX Moderator


Joined: 13 Mar 2006
Posts: 1353
Location: Israel

PostPosted: Fri Jan 27, 2012 3:37 am
Reply with quote

Can you show us the paragraph 4000-WRITE-OUTPUT-FILE ?

Just in case, that's why I said ugly:
  1. You should use indentation. It helps at lot when reading a program.
  2. You should use END-PERFORM when writing an in-line PERFORM.
  3. You should be consistent (in paragraph 3010 you have two IFs, one END-IF and one period).
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Fri Jan 27, 2012 4:44 am
Reply with quote

I don't know where the table is, Jose, but I think the rest is right. We have to wait (and it may be some time) for pullaiah.cts for confirmation.

To add to Marso's list:

One THEN (don't have any, or use them always, not a mix); a "flattened" nested IF (could be made EVALUATE); literals scattered instead of datanames with a value (there is no XREF for literals); MOVE to switches, could use 88s and SET; 88s not used for CUSIP/INTERNAL; COMP PIC S99; WITH TEST AFTER with no good reason. I'm not going to look at the second code sample.
Back to top
View user's profile Send private message
pullaiah.cts

New User


Joined: 02 Sep 2010
Posts: 50
Location: Pune

PostPosted: Sat Jan 28, 2012 11:14 pm
Reply with quote

Hi All,

Sorry for the late reply,I was sick.

I have resolved my issue by replacing my logic with SEARCH technique.

Here is my latest code:
Code:

 * CHECKING FOR CUSIP FIELD.
        3000-CUSIP-SEARCH.
             MOVE "Y" TO CUSIP-FOUND-SWITCH.
             SET WS-SEC-TABLE-INDEX TO 1.
             SEARCH WP-SECURITY VARYING WS-SEC-TABLE-INDEX
              AT END PERFORM 3020-INTERNAL-SEARCH THRU 3020-EXIT
             WHEN WP-TSECTA (WS-SEC-TABLE-INDEX) = 'CUSIP'
             PERFORM 4000-WRITE-OUTPUT-FILE THRU 4000-EXIT
             END-SEARCH.

        3000-EXIT. EXIT.

        3020-INTERNAL-SEARCH.
             MOVE "Y" TO INTERNAL-FOUND-SWITCH.
             SET WS-SEC-TABLE-INDEX TO 1.
             SEARCH WP-SECURITY VARYING WS-SEC-TABLE-INDEX
              AT END MOVE 'N' TO INTERNAL-FOUND-SWITCH
             WHEN WP-TSECTA (WS-SEC-TABLE-INDEX) = 'INTERNAL'
             PERFORM 4000-WRITE-OUTPUT-FILE THRU 4000-EXIT
             END-SEARCH.

        3020-EXIT. EXIT.

      * WRITING CUSIP PROCE TO O/P FILE
        4000-WRITE-OUTPUT-FILE.
              MOVE WP-NGIDN2 (WS-SEC-TABLE-INDEX) TO WS-CUSIP-VALUE.
              MOVE WP-AUSDP                TO WS-CUSIP-PRICE.
              MOVE WS-CUSIP-FLD TO OUT-PRICE-FLE-REC.
              WRITE OUT-PRICE-FLE-REC.
              COMPUTE REC-WRITTEN-CNT = REC-WRITTEN-CNT + 1.

        4000-EXIT. EXIT.


Thank you all for your great support.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun Jan 29, 2012 6:15 am
Reply with quote

pullaiah.cts,

Sorry to hear you were sick. Thanks for the update.

You've not really solved your problem by using SEARCH instead of PERFORM. You've solved your problem by searching for CUSIP in all the occurences first, then searching for INTERNAL after that.

We've had a gentle "dig" at your code, not for fun, but for constructive criticism. If you code cosistently, using indentation to show hierachy and avoid "overloading" your performs, you code will look better, be easier to understand and easier to maintain. Errors will be much easier to spot, and much more difficult to introduce in the first place.

To your current code: you are setting one flag on, and never setting it to any other value - if used elsewhere, it is a bug, if not used, ditch it (and the other flag, although that one is set to a different value); your paragraph 3000-SEARCH-CUSIP, despite the name, does three things (search for CUSIP, search for internal, write to output file for CUSIP) - someone lookting through your code further up will be frustrated by that, and will have to learn not to trust your paragraph names; you are still using literals - you may feel that is OK because it is not like you'll ever have to change the value of CUSIP to something else, in that they're not going to rename the term, but what if you "clone" the program to do some similar processing by ISIN? That is more difficult than need be. SET with a well-named 88 does a much better job for a flag than a MOVE of a literal does; you also have two very similar pieces of code - using the value of a field in a SEARCH/PERFORM, and using it with two different values, removes the need to keep two similar but slightly different pieces of code working; why no visible error-checking on the write?

Code:

           SET W-NOT-FOUND-IN-WP-TSECTA TO TRUE
           MOVE W-CUSIP-LIT TO W-ITEM-TO-SEARCH-FOR
           PERFORM 3000-SEARCH-TSECTA

           IF W-NOT-FOUND-IN-WP-TSECTA
                MOVE W-INTERNAL-LIT TO W-ITEM-TO-SEARCH-FOR
                PERFORM 3000-SEARCH-TSECTA
           END-IF

           IF W-FOUND-IN-WP-TSECTA
               PERFORM 4000-BUILD-OUTPUT-RECORD
               PERFORM 4010-WRITE-OUTPUT-FILE
           END-IF
[...]
           .
       3000-SEARCH-TSECTA.
           SET WS-SEC-TABLE-INDEX TO 1
           SEARCH WP-SECURITY VARYING WS-SEC-TABLE-INDEX
              AT END CONTINUE
             WHEN ( WP-TSECTA ( WS-SEC-TABLE-INDEX )
                   EQUAL TO W-ITEM-TO-SEARCH-FOR )
               SET W-FOUND-IN-WP-TSECTA TO TRUE
           END-SEARCH
           .
       4000-BUILD-OUTPUT-RECORD.
           MOVE WP-NGIDN2 (WS-SEC-TABLE-INDEX) TO WS-CUSIP-VALUE
           MOVE WP-AUSDP                TO WS-CUSIP-PRICE
           MOVE WS-CUSIP-FLD TO OUT-PRICE-FLE-REC
           .
       4010-WRITE-OUTPUT-FILE.
           WRITE OUT-PRICE-FLE-REC
           [ERROR CHECKING]
           COMPUTE REC-WRITTEN-CNT = REC-WRITTEN-CNT + 1
           .


To see the "logic" you don't need to look inside the performs, you can trust that the names relate to the one-to-one task that they carry out.

PS. If it were my code, I'd like to format it differently as well, and have nicer prefixes for the paragraphs/sections :-)
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Sun Jan 29, 2012 9:56 am
Reply with quote

if i was coding this routine,
i would make only one pass of the table using a PERFORM VARYING
with two compound (yet very simple to read and follow) IF statements.

also, the flags would be comp fields:
ws-occurance-of-CUSIP
and
ws-occurance-of-INTERNAL

initialize both comp fields as zero.
I would also use an INDEXED BY phrase in the definition of the COBOL INTERNAL TABLE
(since we want this to be good code)

Code:

PERFORM VARYING TABLE-IDX
   FROM 1
     BY 1
  UNTIL TABLE-IDX GT 26
  IF ws-occurance-of-CUSIP-ZERO
  THEN
     IF WP-TSECTA-CUSIP
     THEN
        SET ws-occurance-of-CUSIP TO TABLE-IDX
     END-IF
  END-IF
  IF WS-OCCURANCE-OF-INTERNAL-ZERO
  THEN
     IF WS-TSECTA-INTERNAL
     THEN
        SET WS-OCCURANCE-OF-INTERNAL TO TABLE-IDX
     END-IF
  END-IF
END-PERFORM


1. until the COBOL INTERNAL TABLE exceeds 256 occurances
it is actually faster to do a perform instead of search

2. since the table is only 26 items,
there is no need to delimit based on finding something,
as the extra time needed to pound and compare all 26 items is negligable.

3. at the end of the above perform loop, you will have both values,
if save-cusip-occurance GT zero then write that, you have saved the occurance,
if save-cusip-occurance equal zero, and save-internal-occurance gt zero,
then write that.

if both are zero, read next record.


doing two searches/perform loops is unnecessary.
and yes, ws-occurance-of-CUSIP-ZERO (and INTERNAL)
are level 88's on the save occurance comp fields.
Back to top
View user's profile Send private message
Bill Woodger

Moderator Emeritus


Joined: 09 Mar 2011
Posts: 7309
Location: Inside the Matrix

PostPosted: Sun Jan 29, 2012 2:48 pm
Reply with quote

pullaiah.cts, hope you are still attending.

With dbz's code you can see how something which can match your requirement doesn't have to be "ugly" and can be really rather attractive*.

I've not used THENs in Cobol, and don't like to see them used as the last thing on the line containing the IF, but dbz's layout works really well.

Even if you find yourself getting very, very tired typing all this by hand (in which case become "lazy", as put forward by Don, and invest some of your time in learning how to use the editor better) it saves time each time someone else has to look at the code (or when you do, after two weeks).

* relative to code
Back to top
View user's profile Send private message
dbzTHEdinosauer

Global Moderator


Joined: 20 Oct 2006
Posts: 6966
Location: porcelain throne

PostPosted: Sun Jan 29, 2012 11:37 pm
Reply with quote

a correction to my code is in order (thx Bill)

the two IF's
IF WP-TSECTA-CUSIP
and
IF WP-TSECTA-INTERNAL

must be:
IF WP-TSECTA-CUSIP (TABLE-IDX)
and
IF WP-TSECTA-INTERNAL (TABLE-IDX)
Back to top
View user's profile Send private message
View previous topic :: :: View next topic  
Post new topic   Reply to topic View Bookmarks
All times are GMT + 6 Hours
Forum Index -> COBOL Programming

 


Similar Topics
Topic Forum Replies
No new posts Copy only TEXT or String from a record SYNCSORT 4
No new posts ICETOOL to SUM String DFSORT/ICETOOL 1
No new posts Mark Previous & next lines when a... DFSORT/ICETOOL 9
No new posts sort to find out the char which repea... Mainframe Interview Questions 10
No new posts Unload and Load ISPF Table TSO/ISPF 4
Search our Forums:

Back to Top