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 IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

STRING unpredictabilities

Status
Not open for further replies.

Glenn9999

Programmer
Jun 19, 2004
2,312
US
Of course, I've complained incessantly about the unpredictable behavior of certain COBOL verbs (namely STRING, UNSTRING, INSPECT, SEARCH, and SEARCH ALL for those of you who are wondering) in various forums and I've encountered another example of having to do this again.

I am trying to do something where I repeatedly concatenate string values together using STRING. As an example, if I set up a loop whereby I concatenate values in a table, say:

Code:
01  MY-TABLE-DATA.
    04  TABLE-VALUES.
        08  pic x(09) value "MY".
        08  PIC X(09) VALUE "BROWN".
        08  PIC X(09) VALUE "DOG".
        08  PIC X(09) VALUE "POSSESSES".
        08  PIC X(09) VALUE "MANY".
        08  PIC X(09) VALUE "FLEAS".
    04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
01  concat-data.
    04  concat-value          pic x(80).
    04  concat-temp-value     pic x(80).

Now to use my loop to turn this into a proper sentence, I would need to string these values together using a temporary value as shown in my code above. One rather unpredictable thing I already encountered and solved is that I must move my current formed sentence to a temp-value before I string it back...now if we look at our code:

Code:
PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
   MOVE CONCAT-VALUE TO CONCAT-TEMP-VALUE
   STRING WORDS-VALUE (I) DELIMITED BY '  '
          SPACE DELIMITED BY SIZE
          CONCAT-TEMP-VALUE DELIMITED BY '  '
     INTO CONCAT-VALUE
END-PERFORM.
MOVE CONCAT-VALUE TO CONCAT-TEMP-VALUE.
STRING CONCAT-TEMP-VALUE DELIMITED BY '  '
       '.' DELIMITED BY SIZE
  INTO CONCAT-VALUE.

The problem here is that I have to use the double spaces as delimiters to preserve my spaces in my text. Yet I get unpredictable results when I run this. Depending on the lengths of my values I place in my data table, I might get no spaces, I might get one, I might get two as part of the table value.

So how do I counter this unpredictable behavior of STRING?
 
That behaviour is not unpredictable. rules are very clear and it is doing what it is supposed to do.

Dealing with duplicated delimiter values is always difficult, and one way of be absolutelly sure that ALL chars on a string before that last GROUP of spaces (which is where normally problems arise, but not necesseraly the only one) is to use a temporary field that is twice as big as the biggest "real" variable being "string'd/unstring'd".

So on your example and assuming that your final sentence should be "MY BROWN DOG POSSESSES MANY FLEAS" e.g. with a space between words, the I would code as follows.
Code:
       IDENTIFICATION DIVISION.
       PROGRAM-ID.  testing.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  MY-TABLE-DATA.
           04  TABLE-VALUES.
               08  pic x(09) value "MY".
               08  PIC X(09) VALUE "BROWN".
               08  PIC X(09) VALUE "DOG".
               08  PIC X(09) VALUE "POSSESSES".
               08  PIC X(09) VALUE "MANY".
               08  PIC X(09) VALUE "FLEAS".
           04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
       01  concat-data.
           04  concat-delim          pic x(9).
           04  concat-value          pic x(80).
           04  concat-temp-value     pic x(80).
       01 W-POINTER PIC 9(4).
       01 I         PIC 9(4).


       PROCEDURE DIVISION.
       MAIN.
           MOVE 1 TO W-POINTER
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
              MOVE SPACES TO CONCAT-TEMP-VALUE
              MOVE WORDS-TABLE(I) TO CONCAT-TEMP-VALUE
              STRING CONCAT-TEMP-VALUE  DELIMITED BY CONCAT-DELIM
                     SPACE DELIMITED BY SIZE
                INTO CONCAT-VALUE
               POINTER W-POINTER
           END-PERFORM.
           DISPLAY CONCAT-VALUE.

           ACCEPT W-POINTER.
           GOBACK.

Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
A bit of simplification and correction:
Code:
IDENTIFICATION DIVISION.
       PROGRAM-ID.  testing.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  MY-TABLE-DATA.
           04  TABLE-VALUES.
               08  pic x(09) value "MY".
               08  PIC X(09) VALUE "BROWN".
               08  PIC X(09) VALUE "DOG".
               08  PIC X(09) VALUE "POSSESSES".
               08  PIC X(09) VALUE "MANY".
               08  PIC X(09) VALUE "FLEAS".
           04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
       01  concat-value          pic x(80).
       01 W-POINTER PIC 9(4).
       01 I         PIC 9(4).

PROCEDURE DIVISION.
       MAIN.
           MOVE 1 TO W-POINTER
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
              MOVE WORDS-TABLE(I) TO CONCAT-TEMP-VALUE
              STRING WORDS-TABLE(I) DELIMITED BY SPACE
                     SPACE DELIMITED BY SIZE
                INTO CONCAT-VALUE
               POINTER W-POINTER
           END-PERFORM.
           MOVE '.' TO CONCAT-VALUE(W-POINER - 1:1)
           DISPLAY CONCAT-VALUE.

           ACCEPT W-POINTER.
           GOBACK.
 
webrabbit

That example will not work (not only because it has an error on it..) if you have the WS fields like

08 pic x(09) value "MY LIGHT".
08 PIC X(09) VALUE "BROWN".
08 PIC X(09) VALUE "BIG DOG".
08 PIC X(09) VALUE "POSSESSES".
08 PIC X(09) VALUE "MANY".
08 PIC X(09) VALUE "BLACK FLEAS".

Using your code the result will be
MY BROWN BIG POSSESSES MANY BLACK
instead of the correct one

MY LIGHT BROWN BIG DOG POSSESSES MANY BLACK FLEAS


Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
The orginal example showed only on word per table entry. Of course if you change the requirements, the program must change. In your example, perhaps the reqirements are for only the first word in each entry. Then your code will get the wronge results. If the requirements are for the last word only, then other changes are needed. Also, you forgot the period at the end of the sentence as required by the original request.
 
Glenn9999,

Those verbs cited in your original post do not exhibit any type of unpredictable at all.
glenn9999 said:
The problem here is that I have to use the double spaces as delimiters to preserve my spaces in my text. Yet I get unpredictable results when I run this. Depending on the lengths of my values I place in my data table
emphasis added

If you insist on using two spaces as your delimiter (which is not necessary, BTW), then you must account for that decision in the remainder of your algorithm, viz. a data item with a single space in the rightmost character position will not behave as if that space is a delimiter. A modest rework would correct the flaw in your algorithm.

Tom Morrison
 
Actually the algorithm has been written correctly already (not using exclusively STRING or even STRING at all in some cases mind you) - I'm just asking how to correctly complete the job using what STRING has to offer.

It just amazes me that in my experience string processing in other languages can be so predictable and will work the same way everytime and in every case while in COBOL several convoluted and inefficient workarounds (and loads of testing) must be used in order to successfully complete the requirement.
 
Ok, I'm testing some of these solutions that have been provided and they are illustrating my exact issues I'm having with STRING.

Frederico, your solution produces "MY " upon running it, and webrabbits approach by using the same algorithm, essentially, will produce the same problem.

SPACE or SPACES or a variable with spaces will kill the algorithm because STRING will stop processing at the first space. To not kill the spaces between the words and continue, in my testing with STRING I found that ' ' (two constant spaces) was necessary as a delimiter.

If anyone has any other suggestions, feel free.
 
As we don't have ALL the requirements of what you are doing we can't say if you can stick with just string or not but bear in mind the following.

IF the requirement says that the words on the final field must only have single spaces between words then using STRING on it's own is possible. If on the other hand "non single" spaces between words on the original fields must be kept then workarounds as the ones mentioned are required.



Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
So, I gather then that your example (in the original post) is not your actual algorithm. The example posted presents absolutely no reason to use two spaces as a delimiter. Can you clarify?

Tom Morrison
 
What was originally posted is the entire requirement.
 
Glenn9999,


As you and webrabbit have noticed my code is missing the final ".", and is also not considering other situations, specially the final space.

I was not considering those details as I was only trying to give the general idea.

In order to deal with the final space one way is as follows.

Code:
       IDENTIFICATION DIVISION.
       PROGRAM-ID.  testing.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  MY-TABLE-DATA.
           04  TABLE-VALUES.
               08  pic x(09) value "MY".
               08  PIC X(09) VALUE "BROWN".
               08  PIC X(09) VALUE "DOG".
               08  PIC X(09) VALUE "POSSESSES".
               08  PIC X(09) VALUE "MANY".
               08  PIC X(09) VALUE "FLEAS".
           04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
       01  concat-data.
           04  concat-delim          pic x(9).
           04  concat-value          pic x(80).
           04  concat-temp-value     pic x(80).
       01 W-POINTER PIC 9(4).
       01 I         PIC 9(4).


       PROCEDURE DIVISION.
       MAIN.
           MOVE 1 TO W-POINTER
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
              MOVE SPACES TO CONCAT-TEMP-VALUE
              MOVE WORDS-TABLE(I) TO CONCAT-TEMP-VALUE
              IF CONCAT-TEMP-VALUE NOT = SPACES
                 STRING CONCAT-TEMP-VALUE  DELIMITED BY CONCAT-DELIM
                        SPACE DELIMITED BY SIZE
                   INTO CONCAT-VALUE
                  POINTER W-POINTER
              END-IF
           END-PERFORM.
           IF W-POINTER > 1
              SUBTRACT 1 FROM W-POINTER
              MOVE "." TO CONCAT-VALUE(W-POINTER:1)
              DISPLAY "==" CONCAT-VALUE(1:w-pointer - 1) "==
           END-IF.
             

           ACCEPT W-POINTER.
           GOBACK.
the above code also corrects the possibility that a particular occurrence is spaces. I would say that if you are loading the table elsewhere then it would probably not happen but better to be safe.

After running the above code the output is
==MY BROWN DOG POSSESSES MANY FLEAS==

Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
What was originally posted is the entire requirement.

I am trying to do something where I repeatedly concatenate string values together using STRING. As an example, if I set up a loop whereby I concatenate values in a table, say:

The problem here is that I have to use the double spaces as delimiters to preserve my spaces in my text.


The above does not make the full requirements very clear as it is missing, in my opinion, the type of data that is available on the table.

If the items on the table are ALWAYS a single word items, then a single space as delimiter on the string will work in all cases.

If the items can be multiple word, then we need to know if they can have multiple spaces between words, and what to do with these, e.g. keep them or replace them with a single space.

So if you can clarify the above we will give you a better solution than the ones already mentioned.

Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
FWIW, I did it a bit differently than what was posted here, but this is the working code I came up with using Frederico's example to the exact requirement. Evidently an unwritten rule (among many unwritten rules I'm finding about in COBOL) is "thou must not use a delimiter as a participant in STRING.".

Code:
IDENTIFICATION DIVISION.
 PROGRAM-ID.  testing.
 ENVIRONMENT DIVISION.
 DATA DIVISION.
 WORKING-STORAGE SECTION.
 01  MY-TABLE-DATA.
     04  TABLE-VALUES.
         08  pic x(09) value "MY".
         08  PIC X(09) VALUE "BROWN".
         08  PIC X(09) VALUE "DOG".
         08  PIC X(09) VALUE "POSSESSES".
         08  PIC X(09) VALUE "MANY".
         08  PIC X(09) VALUE "FLEAS".
     04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
 01  concat-data.
     04  concat-delim          pic x VALUE '*'.
     04  concat-value          pic x(80).
     04  concat-temp-value     pic x(80).
 01 W-POINTER PIC 9(4).
 01 I         PIC 9(4).

 PROCEDURE DIVISION.
 MAIN.
     MOVE 1 TO W-POINTER
     PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
        MOVE SPACES TO CONCAT-TEMP-VALUE
        MOVE WORDS-TABLE(I) TO CONCAT-TEMP-VALUE
        STRING CONCAT-TEMP-VALUE DELIMITED BY SPACE
               '*' DELIMITED BY SIZE
          INTO CONCAT-VALUE
         POINTER W-POINTER
     END-PERFORM.
* CONVOLUTED WORKAROUND TIME.
     INSPECT CONCAT-VALUE REPLACING ALL '*' BY ' '.
* end convoluted work-around.
     MOVE '.' TO CONCAT-VALUE (W-POINTER - 1:1).
     DISPLAY CONCAT-VALUE.

     ACCEPT W-POINTER.
     GOBACK.
 
Glenn,
The actual "unwritten" rule in COBOL is that

"Thou must get complete specifications - not just examples"

You still haven't answered the questions:

1) Can each element include embedded spaces (i.e. multiple words)

2) If so, must the resulting output include 1 - or the same number of spaces.

3) What "non-Latin-1" characters (if any) may appear in the input (i.e. can "*" or "~" or X'00" appear in input fields)

***
a "complete" solution (using STRING or any other approach) will depend upon the answers to those questions.

The COBOL STRING statement is totally predictable AND portable - but does require a complete understanding of "valid" and invalid input.

Bill Klein
 
glenn9999 said:
among many unwritten rules I'm finding about in COBOL

The guys on the COBOL standards committees must be enjoying that line. [lol] I am not sure that anyone has ever accused COBOL of having many unwritten rules!

So.....

from all this I gather that the requirement is:
from a table of cobol data items each containing a single word, construct a 'sentence' of these words separated by a single space, and terminated with a full stop.

Example:

Table of words
PIC x(9) VALUE "ONE"
PIC x(9) VALUE "TWO"
PIC x(9) VALUE "THREE"
PIC x(9) VALUE "FOUR"

Result:
-->ONE TWO THREE FOUR.<--
(result does not include the 'arrow' metacharacters)

Tom Morrison
 
OK I'll humor the questions, though I thought I've been perfectly clear:

1) No, there are no embedded spaces in each of the elements.
2) One word, one space, one word, period. "MY BROWN DOG POSSESSES MANY FLEAS." (exactly one space between each word)is the proper result for the need.
3) Nothing other than alphanumeric ('A'-'Z', '0'-'9') appears in the data.

"I am not sure that anyone has ever accused COBOL of having many unwritten rules!"

Sure, I have a long laundry list of things like this that fall under the category of "you better do them with COBOL even if the standard compiler or other languages lets you get away with something else because you won't be sure of the results you get otherwise if you don't and you don't like 3am callouts now do you? Of course not." rules. Actually, I don't know anyone else that quite puts it the way I do, but they would still say the same thing - basically "even if the compiler lets you, don't do it".
 
Then the solution is a single string using pointer as follows.
Code:
       IDENTIFICATION DIVISION.
       PROGRAM-ID.  testing.
       ENVIRONMENT DIVISION.
       DATA DIVISION.
       WORKING-STORAGE SECTION.
       01  MY-TABLE-DATA.
           04  TABLE-VALUES.
               08  pic x(09) value "MY".
               08  PIC X(09) VALUE "BROWN".
               08  PIC X(09) VALUE "DOG".
               08  PIC X(09) VALUE "POSSESSES".
               08  PIC X(09) VALUE "MANY".
               08  PIC X(09) VALUE "FLEAS".
           04  WORDS-TABLE REDEFINES TABLE-VALUES PIC X(09) OCCURS 6.
       01  concat-data.
           04  concat-value          pic x(80).
       01 W-POINTER PIC 9(4).
       01 I         PIC 9(4).


       PROCEDURE DIVISION.
       MAIN.
           MOVE 1 TO W-POINTER
           MOVE 1 TO W-POINTER
           PERFORM VARYING I FROM 1 BY 1 UNTIL I > 6
              IF WORDS-TABLE(I) NOT = SPACES
                 STRING WORDS-TABLE(I) DELIMITED BY " "
                        SPACE DELIMITED BY SIZE
                   INTO CONCAT-VALUE
                  POINTER W-POINTER
              END-IF
           END-PERFORM.
           IF W-POINTER > 1
              SUBTRACT 1 FROM W-POINTER
              MOVE "." TO CONCAT-VALUE(W-POINTER:1)
              DISPLAY "==" CONCAT-VALUE(1:w-pointer) "=="
           END-IF.

           ACCEPT W-POINTER.
           GOBACK.

The above code assumes that if you have a empty string you don't wish to have the "." on it's own. If this assumption is wrong add an "else" to the last "IF" to catter for that.

Regards

Frederico Fonseca
SysSoft Integrated Ltd
 
Glenn9999,

I think Frederico has disproved your assertion in the original post, viz. "I have to use the double spaces as delimiters to preserve my spaces in my text."

Also, it has been shown that the behavior of your original example was entirely predictable due to the standardized rules of COBOL, and no counterexample showing a noncomplying compiler implementation has been produced.

I took my bit of humor from your statement about many unwritten rules, because COBOL has very, very many written rules! While the US and other governments have abandoned the practice of certifying compiler compliance, the CCVS test suite is still available; you may wish to obtain the source (search this forum for more information) and read the programs. The tests are a very thorough example of the expected, standardized behavior to which all COBOL compiler implementations had to conform as recently as the 1990s.

I truly hope you will continue to bring 'unpredictable' issues to this forum.

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top