View previous topic :: View next topic
|
Author |
Message |
jerryte
Active User
Joined: 29 Oct 2010 Posts: 202 Location: Toronto, ON, Canada
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
mmwife
Super Moderator
Joined: 30 May 2003 Posts: 1592
|
|
|
|
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 |
|
|
jerryte
Active User
Joined: 29 Oct 2010 Posts: 202 Location: Toronto, ON, Canada
|
|
|
|
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 |
|
|
jerryte
Active User
Joined: 29 Oct 2010 Posts: 202 Location: Toronto, ON, Canada
|
|
|
|
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 |
|
|
Robert Sample
Global Moderator
Joined: 06 Jun 2008 Posts: 8696 Location: Dubuque, Iowa, USA
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
prino
Senior Member
Joined: 07 Feb 2009 Posts: 1306 Location: Vilnius, Lithuania
|
|
|
|
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 |
|
|
enrico-sorichetti
Superior Member
Joined: 14 Mar 2007 Posts: 10872 Location: italy
|
|
|
|
sorry to disagree
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 |
|
|
seagull
New User
Joined: 28 May 2007 Posts: 24 Location: Dublin
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
jerryte
Active User
Joined: 29 Oct 2010 Posts: 202 Location: Toronto, ON, Canada
|
|
|
|
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 |
|
|
Bill Woodger
Moderator Emeritus
Joined: 09 Mar 2011 Posts: 7309 Location: Inside the Matrix
|
|
|
|
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 |
|
|
|