Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

String Search in Cobol

Status
Not open for further replies.

supra94red

Programmer
Nov 27, 2002
11
0
0
US
Hello,
Is there a way to scan a whole record for a keyword. For
example I want to drop records with the word "widget" that
can be found anywhere in a particular 100 byte field.

Any help you can provide is appreciated.
 
Hi Red,

Just go to the index of any cobol manual or book and look for "inspect". Also look at "reference modification".

Regards, Jack.
 
As Jack said, INSPECT or ref mod will work great. Just be careful how you do your searching. If the character string you are looking for is imbedded within another word, you may get a match that you didn't want.

Example: Say you're looking for the word ADD. If you use INSPECT and the string happens to have the word ADDITIONAL or PADDED, you'll get a match on the character string when you may not have wanted. You might have to be sure there is a space before and after the word in order to ensure you found the right thing. Also, more problems if punctuation like commas or periods are in your character string.
 
You also have to consider capitalization. The easiest way to handle that is to convert the string to all upper case, if that is applicable and you are not sure what the case of the incomming data is.
 
Hi,

In Sedgewick's Algorithms there is a description of how to search a string in an efficient way.

An easy but very time-consuming function would just search for any match for the first byte and if it fits, the second, etc. You can use reference modification for that.

But perhaps you can also use an editor like SPF/ISPF/SPFSE/.. in which you can say something like:

X ALL;F WIDGET 33 132 ALL

Which means: exclude all (make alle lines invisible), find the text widget (capitals are not important) from columns 33 to 132.

After that it is possible to delete the excluded or the not-excluded lines.

Regards,

Crox
 
hi supra94read,

READ in-file.
MOVE 0 TO TAL-CTR.
INSPECT rec-string TALLYING TAL-CTR FOR ALL "widget"

or

INSPECT rec-string TALLYING TAL-CTR FOR ALL " widget "
(if you want to find WHOLE WORDS)

IF TAL-CTR > 0
DELETE IN-FILE RECORD
END-IF.
 
kvshetye wrote:
Code:
INSPECT rec-string TALLYING TAL-CTR FOR ALL " widget "
(if you want to find WHOLE WORDS)​

Unfortunately, this fails to find 'widget' starting at the leftmost character position, or ending in the rightmost character position, and would therefore fail to delete such records (in the example).

One should use
Code:
TALLYING ... FOR CHARACTERS BEFORE 'widget'
and then use reference modification to test if 'widget' is contained within word boundaries.

A note to supra94red:
You asked a question, and then disappeared. Courtesy would suggest that you comment on the usefulness of the suggestions provided. [neutral]

Tom Morrison
 
Thanks for all your responses, I'm referencing an old college Cobol book that has poor examples of INSPECT and
reference modification. Thus, I have not quite figured
it out yet. To Crox, the SPF editor would have been my first choice but I have large files coming in regularly and
would rather automate the process. Kvshetye, I'm going to play around with your suggestion. K5tm, it's only been two days have some patience, some people don't spend all day
on internet forums.
 
Referencing kvshetye's comment,

INSPECT rec-string TALLYING TAL-CTR FOR ALL "widget"

What I would like to do is to ACCEPT user input string called NAME-PROMPT and to use that in place of "widget" below. I cannot figure out how to check my database fields and compare them to my variable fields that I get from an ACCEPT statement.
It would seem that I should be able to do something like:
INSPECT DBA-NAME-FIELD TALLYING NAME-MATCH-CNT FOR NAME-PROMPT.

NAME-PROMPT holds the string input from the user. That's what I need to use to check for a match on every DBA-NAME-FIELD of every record in my file.

It seems crazy COBOL has been around so long and that I would have to be out of luck using INSPECT because the 3rd Identifier in COBOL syntax for this HAS to be a literal i.e. "abc" versus being able to use a field that contains a string.

I want to double check that I cannot rely on INSPECT and go through the joy of reference modification incrementing 1 character at a time and re-checking for a match.

Comments? Thanks.
Disgruntled COBOL programmer.
 
Hi Elvis,

My read of the Format 1 INSPECT stmt in Enterprise COBOL for z/OS & OS/390 Language Reference (Document Number: SC27-1408-00)shows that the literal field you cite can also be a variable (elementary item).

Regards, Jack.


 
Slade and others:

Yeah, I thought I should be able to use a variable in place of a literal(such as using a variable from an ACCEPT statement i.e. NAME-PROMPT variable versus using a literal such as "abc"). But, thus far, I've had no luck and get a syntax compile error. I'm using RM-COBOL 85 on a AIX Unix environment. Strange. I'm really scratchin' my head on this one, so if you or anyone else can tell me I'm heading in the wrong direction with this, please let me know.
Also, if you know for sure that I should be able to use a variable that is populated from an ACCEPT statement from user input, please do me a favor and donate me a snippet of the code that accomplishes this. Yesterday afternoon, I was pretty much "spinning my wheels" and getting no where on it. Weird since it seems like it should not be a very challenging task to code.

Thanks everyone.
-AmarilloElvis
 
Hi Elvis,

Why not show us the relevant code and the compiler msg? It might provoke some ideas.

Regards, Jack.

 
Code:

NAME-SEARCH.
DISPLAY SPACES LINE 1 POSITION 1 ERASE EOS.
DISPLAY "Enter Name: " Line 1 POSITION 30.
ACCEPT NAME-PROMPT LINE 1 POSITION 43.
INSPECT NAME-PROMPT CONVERTING "abcd...wxyz" TO
"ABCD...WXYZ".
...then it goes to...
CHECK-DB-FILE.
READ DB-FILE NEXT RECORD
AT END MOVE "Y" TO SW-EOF
NOT AT END PERFORM NAME-SCAN
END-READ.

NAME-SCAN.
INSPECT DB-NAME TALLYING MATCH-CNT FOR NAME-PROMPT.
*INSPECT DB-NAME TALLYING MATCH-CNT FOR ALL NAME-PROMPT.
*This commented one works and finds a match incrementing my counter, but ONLY if I type the EXACT full value. I other words, if my record field being scanned has a value of "Johnathan" and I type in "johnathan" it will work. But, if I try to type in "nathan" or "john", no match is found.
rmcobol compile error:

361 NAME-PROMPT
$ $
*********** 1)0414: E Statement has wrong format
*********** 2)0005: I Scan resumed.
 
Hi Elvis,

The syntax rule requires ALL before the variable, therefore the error.

The reason you don't get a match for "john" or "nathan" is that INSPECT is looking for, e.g. "john ". This brings us back to the beginning of this thread: "can ref/mod be used in the INSPECT stmt?

Before you go thru the trouble of extracting "john" from your ACCEPT string, try executing:
Code:
INSPECT DB-NAME TALLYING MATCH-CNT 
    FOR ALL NAME-PROMPT(1:4)
after you've entered "john" thru the console.

If the compiler likes it, you can think about how to extract
" john " from an ACCEPT string and code your INSPECT:
Code:
INSPECT DB-NAME TALLYING MATCH-CNT 
    FOR ALL NAME-PROMPT(POS:LEN)

HTH, Jack.
 
Slade:

Thanks. I will try this first thing in the morning and see if my compiler likes it. The DB-NAME field on each record in my file can have up to 200 characters. So, I guess I'll need to search starting at the first character of the DB-NAME field and increment the starting position in the DB-NAME by 1 until the end of that string. Each pass through the loop will check for a match. I guess I'll need to somehow get the length of the NAME-PROMPT accepted also.

INSPECT DB-NAME TALLYING MATCH-CNT
FOR ALL NAME-PROMPT(1:4)

after you've entered "john" thru the console.

If the compiler likes it, you can think about how to extract
" john " from an ACCEPT string and code your INSPECT:

INSPECT DB-NAME TALLYING MATCH-CNT
FOR ALL NAME-PROMPT(POS:LEN)
 
Amarillo:

Here's something "your" compiler will accept...
Code:
identification division.
program-id.  "keyword".
data division.
working-storage section.
01  a-string pic x(40) value "spongebobsquarepants".
01  a-keyword pic x(20) value "bob".
01  i pic 99.
01  j pic 99.
procedure division.
a.
    move 0 to i.
    inspect a-keyword tallying i for characters
                                 before initial space.
    if i > 0
        move 0 to j
        inspect a-string tallying j
                         for all a-keyword (1:i)
        display j
    end-if.
    stop run.

My compiler likes it! [bigsmile]

Tom Morrison
 
K5TM(Tom Morrison):

That worked like a charm.
Thanks to you and Slade for the help.

-David
 
Hi Elvis,

Before you leave the building, the user, for reasons only he knows, might enter "bbjohn".

You could always tell him not to do that or you can code for it.

Regards, Jack.
 
Elvis,

now that you've left the building...

You could also try substituting the following in place of your original ACCEPT statement:
Code:
PERFORM WITH TEST AFTER
    UNTIL NAME-PROMPT NOT = SPACES
        ACCEPT NAME-PROMPT
               LINE 1 POSITION 43
               CONTROL "UPPER"
               CURSOR J
END-PERFORM
SUBTRACT 1 FROM J


"Code what you mean,
and mean what you code!
But by all means post your code!"

Razalas
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top