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

UNSTRING a big string


IBM Mainframe Forums -> COBOL Programming
Post new topic   Reply to topic
View previous topic :: View next topic  
Author Message
Apurva Ghogale

New User


Joined: 20 Sep 2018
Posts: 9
Location: INDIA

PostPosted: Thu Sep 20, 2018 12:12 pm
Reply with quote

Hi ,

I want to UNSTRING a big string of data approximately 12,60,000(max) in length.And after unstringing the data I need to write each unstrung record (ws-data) to one row in output file. Each record can be of 700 bytes.The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data.

Please suggest the best coding practise or alternative to below approach as if I use the below I need to code WS-DATA from 1 t0 1800 times and may end up in untidy code.

UNSTRING WS-REQUEST DELIMITED BY "|"

INTO WS-DATA1

WS-DATA2

WS-DATA3

WS-DATA4

.

.

.

WS-DATA 1800.

Thanks,
Apurva
Back to top
View user's profile Send private message
expat

Global Moderator


Joined: 14 Mar 2007
Posts: 8796
Location: Welsh Wales

PostPosted: Thu Sep 20, 2018 12:28 pm
Reply with quote

Hi, and welcome to the forum.

Please take a look at the difference between what you have posted and how it looks after I have amended your post using the code tags. They are really easy to use.

Manual code - do this
Code:
[code]Your stuff
goes in between
the tags[/code]


Or - highlight the code that you want to show and simply click the Code box above the text entry box

Code:
Your
stuff
here


Apurva Ghogale wrote:
Hi ,

I want to UNSTRING a big string of data approximately 12,60,000(max) in length.And after unstringing the data I need to write each unstrung record (ws-data) to one row in output file. Each record can be of 700 bytes.The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data.

Please suggest the best coding practise or alternative to below approach as if I use the below I need to code WS-DATA from 1 t0 1800 times and may end up in untidy code.
Code:

UNSTRING WS-REQUEST DELIMITED BY "|"

INTO WS-DATA1

WS-DATA2

WS-DATA3

WS-DATA4

.

.

.

WS-DATA 1800.

Thanks,
Apurva
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2454
Location: Hampshire, UK

PostPosted: Thu Sep 20, 2018 1:04 pm
Reply with quote

Why not try parsing in a loop: find the first delimiter, use reference modification to save the leading part into a table, remove that part from the string and repeat.
Back to top
View user's profile Send private message
Apurva Ghogale

New User


Joined: 20 Sep 2018
Posts: 9
Location: INDIA

PostPosted: Thu Sep 20, 2018 1:20 pm
Reply with quote

How to remove that part from the string? I m really not sure how to achieve this?
Can you paste the code for that?
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2454
Location: Hampshire, UK

PostPosted: Thu Sep 20, 2018 1:27 pm
Reply with quote

you simply read along the string, using reference modification to read each byte, to find your delimiter counting each byt along the way. you now know the length of the first part so you can save it using reference modification (1:lengthOfPart - 1) and move the remainder (lengthOfPart + 1: ) to a temp variable (or replace the current string).

Example code (from a similar topic on another forum, this week)
Code:
01 WS-INPUT  PIC X(20) VALUE 'My|very|long|string'.
01 WS-SUB    PIC 9(4)  COMP.
01 WS-SUB1   PIC 9(4)  COMP VALUE 0.
01 WS-START1 PIC 9(4)  COMP VALUE 1.
01 WS-INDEX  PIC 9(4)  COMP VALUE 0.
01 WS-ARRAY  PIC X(10) OCCURS 0 TO 9999 DEPENDING ON WS-INDEX.

PROCEDURE DIVISION.
PERFORM VARYING WS-SUB
        FROM 1 BY 1
        UNTIL WS-SUB > FUNCTION LENGTH(WS-INPUT)
       
   COMPUTE WS-SUB1 = WS-SUB1 + 1
   
   IF WS-INPUT(WS-SUB:1) = ";"
   
      ADD 1 TO WS-INDEX

      MOVE WS-INPUT(WS-START1:WS-SUB1 - 1)
        TO WS-ARRAY(WS-INDEX)
      MOVE 0 TO WS-SUB1
     
      COMPUTE
         WS-START1 = WS-SUB + 1         
      END-COMPUTE
     
   END-IF
   
   IF WS-SUB EQUAL FUNCTION LENGTH(WS-INPUT)
   
      ADD 1 TO WS-INDEX
      MOVE WS-INPUT(WS-START1:WS-SUB1)
          TO WS-ARRAY(WS-INDEX)
         
   END-IF
   
END-PERFORM
Back to top
View user's profile Send private message
Apurva Ghogale

New User


Joined: 20 Sep 2018
Posts: 9
Location: INDIA

PostPosted: Thu Sep 20, 2018 2:28 pm
Reply with quote

Thank you Nic for the solution. I will try it and let you know once it works. icon_smile.gif
Back to top
View user's profile Send private message
Rohit Umarjikar

Global Moderator


Joined: 21 Sep 2010
Posts: 3076
Location: NYC,USA

PostPosted: Thu Sep 20, 2018 7:34 pm
Reply with quote

Welcome!
At least , I am not sure of the loop but
Code:
 IF WS-INPUT(WS-SUB:1) = ";"
should be
Code:
IF WS-INPUT(WS-SUB:1) = "|"

But why do you have a problem with COBOL UNSTRING ?
Read more about UNSTRING and POINTER concepts and you do a Unstring into an array of 1800 or whatever occurrences you want. May be you only need 5 lines of code to get what you want.
Example: UNSTRING statement
Refer how its being implemented by others in past.
ibmmainframes.com/about56116.html
ibmmainframes.com/about65202.html
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2454
Location: Hampshire, UK

PostPosted: Thu Sep 20, 2018 7:48 pm
Reply with quote

The code was taken from a response to a similar problem, posted in another forum, where the delimiter was ';'. I thought I had changed it but this is also an exercise for the TS.
Back to top
View user's profile Send private message
Rohit Umarjikar

Global Moderator


Joined: 21 Sep 2010
Posts: 3076
Location: NYC,USA

PostPosted: Thu Sep 20, 2018 7:57 pm
Reply with quote

Yes Nic, that does without saying icon_smile.gif
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8700
Location: Dubuque, Iowa, USA

PostPosted: Fri Sep 21, 2018 12:50 am
Reply with quote

Quote:
The input string can vary ,sometimes we can get less data as well from other systems,but we are considering the maximum possible data.
If the "less data" in your post means you may not get all 1800 delimiters, then UNSTRING is probably not your best option. There is no compiler limit to prevent you from coding up all 1800 INTO variables, but you would need the POINTER and TALLYING variables to determine how far you got when the ON OVERFLOW condition was hit (and if you have less than 1800 delimiters, you will hit the ON OVERFLOW condition).

Also, how are you building your big string (since I know you cannot read it into your program as a single record)? Perhaps it would be better to split out the records there instead of after assembling it into a big string?
Back to top
View user's profile Send private message
sergeyken

Senior Member


Joined: 29 Apr 2008
Posts: 2142
Location: USA

PostPosted: Fri Sep 21, 2018 3:55 am
Reply with quote

Just a note.

UNSTRING had been introduced in COBOL mainly to avoid very bad performance when one-by-one character scan is implemented as COBOL loop.
It's not good idea to return back from UNSTRING to a primitive loop.
It resembles a stone hammer used to build a skyscraper...
Back to top
View user's profile Send private message
Apurva Ghogale

New User


Joined: 20 Sep 2018
Posts: 9
Location: INDIA

PostPosted: Fri Sep 21, 2018 11:49 am
Reply with quote

Hi Rohit/Robert,
The string is coming from other application and they are not ready to split it. Hence they will be sending the whole data in a string only. There is no problem as to use 1800 variables but m not sure what will actually happen if data goes till actual 1800 variables. hence I was looking for some alternative where I can avoid defining 1800 variables.


Hi Robert,

If there is less data than 1800 ,how will ON OVERFLOW will hit? It wont hit right. IT will hit when it goes beyong 1800 ? M I right? So anyways I will have to define maximum possible delimiters.
Back to top
View user's profile Send private message
Nic Clouston

Global Moderator


Joined: 10 May 2007
Posts: 2454
Location: Hampshire, UK

PostPosted: Fri Sep 21, 2018 2:14 pm
Reply with quote

The word is 'Am' not 'M'.
Why do you not try with a simple test of three or four tokens in a string?
Back to top
View user's profile Send private message
Apurva Ghogale

New User


Joined: 20 Sep 2018
Posts: 9
Location: INDIA

PostPosted: Fri Sep 21, 2018 3:22 pm
Reply with quote

Hi Nic,

Yes I have executed the below code suggested by you with few modification and is working fine except the last record is not getting populated. I am looking into it.

Code:

PERFORM VARYING W10-SUB FROM 1 BY 1                   
  UNTIL W10-SUB > FUNCTION LENGTH(WCF-RECORD)         
  OR W20-EOF                                         
                                                     
 COMPUTE W10-SUB1 = W10-SUB1 + 1                     
                                                     
 IF (W10-SUB + 10) NOT GREATER THAN                   
                 FUNCTION LENGTH(WCF-RECORD)         
  IF WCF-RECORD(W10-SUB:10) = 'XXXXXXXXXX'           
   DISPLAY 'MATCH'                                   
   ADD 1 TO W10-INDEX                                 
   MOVE WCF-RECORD(W10-START:(W10-SUB1)- 1) TO       
        W10-ARRAY(W10-INDEX)                         
   MOVE 0 TO W10-SUB1                                 
   COMPUTE W10-START = W10-SUB + 1                     
  END-IF                                               
                                                       
  IF W10-SUB EQUAL FUNCTION LENGTH(WCF-RECORD)                                           
   ADD 1 TO W10-INDEX                                 
   MOVE WCF-RECORD(W10-START:W10-SUB1) TO             
        W10-ARRAY(W10-INDEX)                           
   SET W20-EOF TO TRUE                                 
  END-IF                                               
 ELSE                                                 
  SET W20-EOF TO TRUE                                 
 END-IF                                               
END-PERFORM.                                           
Back to top
View user's profile Send private message
Rohit Umarjikar

Global Moderator


Joined: 21 Sep 2010
Posts: 3076
Location: NYC,USA

PostPosted: Fri Sep 21, 2018 4:28 pm
Reply with quote

Do you know there is depending upon clause in an array? So tally all your pipes in a string and assign that to the array before Unsteing and this is already suggested by Robert. No array fails if the size goes beyond 1800.
ON OVERFLOW phrases
Back to top
View user's profile Send private message
Rohit Umarjikar

Global Moderator


Joined: 21 Sep 2010
Posts: 3076
Location: NYC,USA

PostPosted: Fri Sep 21, 2018 4:35 pm
Reply with quote

Deleted
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


Joined: 06 Jun 2008
Posts: 8700
Location: Dubuque, Iowa, USA

PostPosted: Fri Sep 21, 2018 7:24 pm
Reply with quote

Quote:
If there is less data than 1800 ,how will ON OVERFLOW will hit? It wont hit right. IT will hit when it goes beyong 1800 ? M I right? So anyways I will have to define maximum possible delimiters.
I tested UNSTRING on my COBOL 5.1 system, and if there are fewer fields than you UNSTRING into, ON OVERFLOW is invoked and POINTER is set to the first byte not placed in a variable, and TALLY has the number of fields processed. If you have more fields than you UNSTRING into, ON OVERFLOW is invoked with the same usage for POINTER and TALLY. In both cases, the variables that UNSTRING used as targets do have the correct data in them. So if you want to use UNSTRING, you'll have to carefully consider how to use ON OVERFLOW since it will be invoked unless the number of fields match exactly what you code. And another thing to consider -- with UNSTRING, the last field in the string must be terminated with a delimiter or it will contain however many characters were left in the big string (be that 1 or 1,000,000 bytes).
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 Help with C character vs C string All Other Mainframe Topics 3
Search our Forums:

Back to Top