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

Moving variable length strings


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

Active User


Joined: 29 Oct 2010
Posts: 202
Location: Toronto, ON, Canada

PostPosted: Wed Aug 17, 2011 2:11 am
Reply with quote

My program will receive a packed decimal number
Code:
05 W-PHONE-NUM-P   PIC S9(17) COMP-3
which I then have to break apart into 3 fields - country code, area code, and phone number - based on the string length of the number (which is the number of digits). If the number is short then I leave the country code and\or area codes blank.

For example if I get a 5 digit number then I move it to the phone number field (left justified) padded with 2 spaces. I leave country and area code blank.

My plan was to move this to a zoned decimal PIC 9(17) field to convert to a string. Then use INSPECT TALLYING to add up the number of leading zeroes and then subtract this from the field length to get the number of digits. I can then use this length to calculate the starting position of the number and then do a MOVE with a reference modifier


Code:
MOVE W-PHONE-NUM-Z (W-START:) TO something


Anyone have a better idea? I am not looking for actual code - just ideas. I tried doing this in Rexx (just as an exercise) and there was no simple way. I still have to calculate lengths and starting position and then use a SUBSTR function.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


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

PostPosted: Wed Aug 17, 2011 2:43 am
Reply with quote

I cannot think of a WORSE format to deal with unknown data than packed decimal (COBOL COMP-3). Your data comes to you as a 9-byte variable -- if you don't get 9 bytes (17 digits), you most likely will get a S0C7 or S0C4 abend in your program.

Are you guaranteed to always get 17 digits, left-zero-filled? If so, why bother with the rigamarole of INSPECT? Just add 1 to the integer part of the LOG10 value of the number and you'll get the number of digits in the variable.
Quote:
My plan was to move this to a zoned decimal PIC 9(17) field to convert to a string.
Repeat after me: COBOL does not have "strings". COBOL has numeric variables, alphanumeric variables, group variables, and so forth -- but none of them behave like a string in C or PERL or JAVA (etc) behave. Variables in COBOL are pretty much fixed in length at compile time (except for a couple of cases) and variable lengths do not change at run time, so they cannot be strings.
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: Wed Aug 17, 2011 4:21 am
Reply with quote

I'm interested in your spec.

Country codes can be 1, 2, 3 or 4 digits.

Area codes I know of can be 3 to at least 5 digits.

Portugal has no area codes, just 9-digit numbers.

Area codes (at least that I know of) start with a zero when used from within a country, but drop the zero for calls from outside the country. However, there is no law for how some customer enters their international telephone number, so how did your data-entry deal with this?

Phone numbers you have as five? I know of 5-7 digit numbers, excluding Portugal's 9.

This is just what I know, I am certainly no expert on international telephone numbers.

Just wondering how you are going to deal reliably, with even the above, as just a number in a comp-3. You can't even use zero as some sort of terminator, because it is valid in a phone number, code, and international code.

I'd guess this needs to be readdressed at your end. Unless you are only dealing with Canada and USA, or some such manageable subset? Even then you have to do it the right way around (starting from the left, valid country code first, then valid area code, then whatever is left you have to hope is a valid number, unless you can hook-up to some phonebooks online).
Back to top
View user's profile Send private message
mmwife

Super Moderator


Joined: 30 May 2003
Posts: 1592

PostPosted: Wed Aug 17, 2011 4:50 am
Reply with quote

As Bill implies, you haven't been specific about the possibilities you face. I've seen packed data converted to multi field display data using something like this.
Code:
05  W-PHONE-NUM-D     pic Z(17).
05  FIL REDEFINES W-PHONE-NUM-D.
    10  FIL                            pic  X(02).
    10  W-AREA-CODE      pic  X(03).
    10  W-CNTRY-CODE   pic  X(05).
    10  W-PHONE-NBR     pic  X(07).

MOVE W-PHONE-NUM-P TO W-PHONE-NUM-D


It's untested. I had the redef wrong - it's fixed, thanx to Bill W.
Back to top
View user's profile Send private message
jerryte

Active User


Joined: 29 Oct 2010
Posts: 202
Location: Toronto, ON, Canada

PostPosted: Wed Aug 17, 2011 7:57 pm
Reply with quote

The packed decimal field is coming as part of a file from an external vendor. I am fairly confident that it will be a valid numeric with a size from 1 to 17 digits. I have to convert it to a string (alphanumeric) and split it up based on its size.

The challenge is that a numeric field is right justified with leading zeroes. The alphanumeric field is left justified with padded spaces. I have to strip off the leading zeroes and move it. I convert it to alphanumeric and then calculate the length of the number. I then use an EVALUATE statement on the length to perform different actions.

Thanks for the tip about the LOG10 function. I forgot about that.

I know that COBOL does not have a true string type. However an alphanumeric field is very similiar so I sometimes call it a "string". A string type is just a series of bytes with a known length.
Back to top
View user's profile Send private message
jerryte

Active User


Joined: 29 Oct 2010
Posts: 202
Location: Toronto, ON, Canada

PostPosted: Wed Aug 17, 2011 8:05 pm
Reply with quote

Bill Woodger wrote:
I'm interested in your spec.
Area codes I know of can be 3 to at least 5 digits.

Portugal has no area codes, just 9-digit numbers.

Area codes (at least that I know of) start with a zero when used from within a country, but drop the zero for calls from outside the country. However, there is no law for how some customer enters their international telephone number, so how did your data-entry deal with this?

My coworker is from Portugal. He says that you do have area codes which is 2 or 3 digits. Lisbon for example has area code '21'. He says this was introduced recently.

In North America area codes and phone numbers do not begin with the digit '0'. Pressing zero will call the operator.

In Toronto we have 10 digit dialing. We always have to dial the area code and phone number even for a local call. They had to do this because the phone company was running out of numbers.

For my program there is no gaurantee for the area code length. It could be 1 to 4 digits long. I have to move it and remove any leading zeroes.
Back to top
View user's profile Send private message
Robert Sample

Global Moderator


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

PostPosted: Wed Aug 17, 2011 8:37 pm
Reply with quote

Quote:
A string type is just a series of bytes with a known length.
Uh, no. A PERL or C string is variable length at run time, and the length can be changed by program code. The string continues until the appropriate termination character (newline or X'00' for exampel) is found. this is why C and PERL have string length functions to determine the current length of the string.
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: Wed Aug 17, 2011 10:00 pm
Reply with quote

Well, not quite sure if it counts as on-topic, but your Portuguese colleague is wrong. OK, so maybe if you define area code as being meaningless, fair enough. But if area code means the number you have to add to the telephone number to dial a number in a different geographical area than where you are, or from a mobile/cell, then no, Portugal does not have area codes.

However, if area codes mean nothing, then maybe it makes your program easier - or more difficult.

I know Portugal is a pain with many pieces of software for recording telephone numbers, as you have to have an area code, and with some it even insists on the area code starting with a zero.

Lisbon telephone numbers start 21, then there are 7 digits.

All other Portugues numbers start with a 3-digit number (per geographical area) and are followed by six digits.

All it really means is that Lisbon has a number of three-digit-starting numbers, of which the first are 21.

Like you have over there, wherever you are you have to dial the full number, even if in the same "area". No area code, just a permanent geographical prefix.

If the data is from an external source, presumably they have supplied information about how the three items are stored in a 17-digit number. Then you apply a suitable variant of Jack's solution.

Mobile/cellphones have no area code that I know of either, but do have a country code.
Back to top
View user's profile Send private message
prino

Senior Member


Joined: 07 Feb 2009
Posts: 1306
Location: Vilnius, Lithuania

PostPosted: Thu Aug 18, 2011 1:39 am
Reply with quote

Bill Woodger wrote:
Area codes (at least that I know of) start with a zero when used from within a country, but drop the zero for calls from outside the country.

With another exception, Italy.
Back to top
View user's profile Send private message
enrico-sorichetti

Superior Member


Joined: 14 Mar 2007
Posts: 10872
Location: italy

PostPosted: Thu Aug 18, 2011 5:08 pm
Reply with quote

sorry to disagree icon_biggrin.gif
You drop the 0 for mobile numbers, +39335..... a mobile provider
You keep it for <fixed> numbers +3902..... ( Milan )
( to be sure I just checked, called my mother, and my home number )
Back to top
View user's profile Send private message
seagull

New User


Joined: 28 May 2007
Posts: 24
Location: Dublin

PostPosted: Thu Aug 18, 2011 7:17 pm
Reply with quote

Most countries you drop the 0 from the area code regardless if it's a landline or mobile. E.g. Dublin from the rest of Ireland - dial 01 nnnnnnn. Dublin from the rest of the world - +353 1 nnnnnnn.
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 Aug 18, 2011 10:45 pm
Reply with quote

Code:
05  W-PHONE-NUM-D     pic 9(17).
05  FIL REDEFINES W-PHONE-NUM-D.
    10  W-CNTRY-CODE   pic  9(04).
    10  W-AREA-CODE      pic  9(05).
    10  W-PHONE-NBR     pic  9(10).

    10  W-CNTRY-CODE-ED   pic  Z(04).
    10  W-AREA-CODE-ED      pic  Z(05).
    10  W-PHONE-NBR-ED     pic  Z(10).

    MOVE W-PHONE-NUM-P TO W-PHONE-NUM-D

    MOVE W-CNTRY-CODE TO W-CNTRY-CODE-ED
    MOVE W-AREA-CODE  TO W-AREA-CODE-ED
    MOVE W-PHONE-NBR TO W-PHONE-NBR-ED


Hi Jerry,

Have you got anywhere with this one? I've extended Jack's code a little. This works if you have fixed positions for your three types of data. Which you probably don't, maybe because with all the maximums I can find, your supplier's field is two bytes short at least. So I know the redefines doesn't add up and won't work that way.

The above will have blanks automatically for any field which is zero.

How does the supplier say the numbers are formatted?

I prefer solutions with data definitions to reference modification.

If you can show us the spec for the input field, we might be able to get to one for that, even with variable positions.
Back to top
View user's profile Send private message
jerryte

Active User


Joined: 29 Oct 2010
Posts: 202
Location: Toronto, ON, Canada

PostPosted: Fri Aug 19, 2011 2:14 am
Reply with quote

Bill Woodger wrote:
Hi Jerry,

Have you got anywhere with this one? I've extended Jack's code a little. This works if you have fixed positions for your three types of data. Which you probably don't, maybe because with all the maximums I can find, your supplier's field is two bytes short at least. So I know the redefines doesn't add up and won't work that way.


Thanks for the suggestion. I did get it to work but using a different method. The challenge with a zoned decimal field is that it is right justified. I needed to remove the leading zeroes (or spaces) and move to a left justified alphanumeric field. Also I have no gaurantee that the phone number is 7 digits. It could be less.

I did something like below
Code:

COMPUTE W-START = 8 - W-LEN
MOVE W-PHONE-NUM (W-START:) TO alphanumeric-field

where W-LEN is the length of the number. This worked
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 Aug 19, 2011 6:59 pm
Reply with quote

Code:
01  W-PHONE-NO-FULL.
    05  W-PNF-LEADING-ZEROS.
        10  FILLER OCCURS 0 TO 17 TIMES
               DEPENDING-ON W-LENGTH-OF-PHONE-LEADING-ZEROS.
            15  FILLER PIC X.
    05  W-PNF-TELEPHONE-NUMBER.
        10  FILLER OCCURS 0 TO 17 TIMES
               DEPENDING-ON W-LENGTH-OF-PHONE-NUMBER.
            15  FILLER PIC X.

Zero to W-LENGTH-OF-PHONE-LEADING-ZEROS
Length of field to W-LENGTH-OF-PHONE-NUMBER

Comp-3 to PIC 9(17) to W-PHONE-NO-FULL

Calculate number of leading zeros (W-LENGTH-OF-PHONE-LEADING-ZEROS) from number of digits (W-LENGTH-OF-PHONE-NUMBER) and field length.

MOVE W-PNF-TELEPHONE-NUMBER TO alphanumeric-field


It isn't as neat as when you could use redefines with ODO. Can be fiddled about with. By adding a FILLER of 17 to end of W-PHONE-NO-FULL it would no longer require the calculation of lengths before the move (better mimicing the REDEFINES version) but I'd comment it.

Another way to mimic the redefines is in the Linkage section, with the pointers, two 01-levels, same address.

What I like is the self-documenting nature of the thing. Even the piece which is not referenced (the leading zeros) tells you what it is, what the intention of the field is. You have the XREF for all references to the data structure. I don't know (ie I have no idea what it looks like) how easy a reference modification is to find in the XREF. And when you find it, how easy is it to know what it means, what was being attempted?

Edit: Not actually tested, but then 1) it isn't full code 2) I've done it a lot of times and it works 3) not my fault if you get the missing code wrong 4) my fault but tough if there are typos.
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 How to split large record length file... DFSORT/ICETOOL 10
No new posts PARSE Syntax for not fix length word ... JCL & VSAM 7
No new posts Extracting Variable decimal numbers f... DFSORT/ICETOOL 17
No new posts VB to VB copy - Full length reached SYNCSORT 8
No new posts Variable Output file name DFSORT/ICETOOL 8
Search our Forums:

Back to Top