COBOL Unstring into an Array

2019-04-15 02:21发布

问题:

I'm trying to unstring my input-line which is seperated with ";", into an array. But i'm having trouble with displaying every word after the first ";".

So basically, Input: Hello;Stack;Overflow


Output: Value: 2 (because of 2 semicolons)


Line 1 of my Record Table: Hello


Line 2 of my Record Table: Stack


Line 3 of my Record Table: Overflow

My code so far:

*-------------------------------------------------------------
 LINKAGE SECTION.                                             
 01  X-INPUT-LINE                   PIC X(2000).              
 01  X-SEP-CHAR                     PIC X(1).                                     
 01  X-RET-TABLE.                                             
  02 CMAX                           PIC 9(5) COMP-3.          
  02 ENTRY-REC OCCURS 0 TO 9999 TIMES DEPENDING ON CMAX       
                                      INDEXED   BY CIDX.      
   04 ENTRY-REC2.                                             
    07 LINEVALUE                    PIC X(100).               

PROCEDURE DIVISION USING X-INPUT-LINE
                         X-SEP-CHAR  
                         X-RET-TABLE.

MAIN SECTION.
MN-00.       
INITIALIZE WERT.                                

INSPECT X-INPUT-LINE TALLYING WERT FOR ALL      
        X-SEP-CHAR.                             
MOVE X-INPUT-LINE TO VAL.                       

ADD 1 TO WERT.                                  
PERFORM WERT TIMES                              
MOVE WERT TO LINEVALUE OF X-RET-TABLE (WERT)    
     UNSTRING VAL DELIMITED BY ";"              
     INTO STRVAL                                
     END-UNSTRING                               


IF CMAX OF X-RET-TABLE < 9999                   
   ADD  1  TO CMAX OF X-RET-TABLE               
   MOVE STRVAL TO ENTRY-REC(CMAX OF X-RET-TABLE)

END-IF                                          
END-PERFORM.    

With my following code I can only display the "Hello" in my example and the program displays it 3 times in 3 different rows.

回答1:

Your original code nearly works.

The main issue is, that you UNSTRING a given variable and always use the same starting point.

He we can use WITH POINTER. Used on STRING the clause says "position where next character is stored", used on UNSTRING it says "position where next character is read from".

Using the starting code (added the caller, actually use the given separator instead of the fixed ";" and a DISPLAY of the result), added here we add a variable for the starting point and use it.

     UNSTRING X-INPUT-LINE DELIMITED BY X-SEP-CHAR
     INTO STRVAL
     END-UNSTRING

becomes

     UNSTRING X-INPUT-LINE DELIMITED BY X-SEP-CHAR
     INTO STRVAL
     WITH POINTER STARTING-POINT
     END-UNSTRING

You'll also need to initialize some parts and can directly use the table item (as long as you ensure the counter doesn't get too big), providing you with the result (includes more samples).



回答2:

Unstring doesn't really work that way. Unstring will work if you know the field names of the what you want to unstring into. Basically what is happening in your code is you run the unstring 3 times and because "hello" is the first thing in the unstring it is being unstrung 3 times. If you want to do something scalable into an array, you would need to code a loop like this:

01 WS-UNSTRING-FIELDS.
   05 WS-INPUT PIC X(1000).
   05 WS-SUB   PIC 9(4) COMP.
   05 WS-START PIC 9(4) COMP VALUE 1.
   05 WS-INDEX PIC 9(4) COMP VALUE 0.
   05 WS-ARRAY OCCURS 0 TO 9999 DEPENDING ON WS-INDEX.

PERFORM VARYING WS-SUB
           FROM 1 BY 1 
          UNTIL WS-SUB > FUNCTION LENGTH(WS-INPUT)
   IF WS-INPUT(WS-SUB:1) = ";"
      ADD 1 TO WS-INDEX

      MOVE WS-INPUT(WS-START:WS-SUB - 1) 
        TO WS-ARRAY(WS-INDEX)

      COMPUTE
         WS-START = WS-SUB + 1
      END-COMPUTE
   END-IF
END-PERFORM

I haven't really had time to test this and ensure it works 100%, but you would need something along those lines. I would avoid using unstring here at any rate.

Unstring works great when you know exactly how many fields are coming in. Like for instance, lets say you have generic program that interacts with MQ series. As input to this program, you can pass a string that holds instructions something like

QueueName/Action

you could then use unstring in this context to split them into 2 fields:

UNSTRING WS-INPUT DELIMITED BY "/"
   INTO WS-Q-NAME
        WS-ACTION
END-UNSTRING

Lets say the input here was:

THIS_IS_MY_QUEUE/DELETE

WS-Q-NAME would have THIS_IS_MY_QUEUE_NAME and WS-ACTION would have DELETE