[comp.lang.perl] Why are my digits disappearing?

mfrost@sword (Mark Frost) (12/05/90)

Thanks to all those who replied to my previous problem involving pattern
matching (yes, I did pick up the fact that I should have been using =!
instead of =~ -- oops! 8-) ).

Anyway, I've got another problem that has really been puzzling me. As part
of a larger script I am writing which deals extensively with IP addresses,
I am trying to convert decimal IP addresses to hex format. So 129.214.009.096
would give me "81D60960". I clipped the code below from my other script to 
illustrate the problem. Each time I run the subroutine to convert decimal
IP address to hex ("IPTOHEX") the routine seems to drop some digits
semi-consistently.

So sometimes I might get "81600" instead of "81D6A0A0" for 129.214.160.160.
I can't see any reason for this. Being a perl novice, most of the constructs
below are quite new to me, but I don't see why they don't work. I have
included sample output below and the script itself.

Thanks


          -m-----------  Mark Frost    (mfrost@pyramid.com)
        ---mmm---------  System Administrator - Hardware Engineering
      -----mmmmm-------  Pyramid Technology Corporation
    -------mmmmmmm-----  1295 Charleston Rd, P.O. Box 7295
  ---------mmmmmmmmm---  Mountain View, California 94039-7295 
-----------mmmmmmmmmmm-  (415) 335-8163

----------------------------script--------------------------------
#!/usr/bin/perl
# Convert decimal IP address to Hex form
sub IPTOHEX
	{
	local(@ipaddr) = @_;
	local($hexaddr,$loop);
	local($digit1,$digit2) = 0;
	for ($loop = 0; $loop < 4; $loop++)
		{
		$digit1 = (0 .. 9, 'A' .. 'F')[( $ipaddr[$loop] / 16) & 15];
		$digit2 = (0 .. 9, 'A' .. 'F')[( $ipaddr[$loop] % 16) & 15];
		$hexaddr = join('',$hexaddr,$digit1,$digit2);

print "ipaddr[$loop] = $ipaddr[$loop] ";
print "... digit1 = $digit1 ... digit2 = $digit2 ";
print "... hexaddr = $hexaddr\n";

		} # for
	$hexaddr;
	} # iptohex

for ( $i = 0; $i < 5; $i++)
	{
	print "\nPlease enter the hostname which you want to configure (XX.XX.XX.XX)\n";
	print "-> ";
	$ipraw=<STDIN>;
	chop($ipraw);
	@ip=split(/\./,$ipraw);
	$hexstring = &IPTOHEX(@ip);
	print "\nHost ip entered was $ip[0].$ip[1].$ip[2].$ip[3] ($hexstring)\n";
	}

------------------program output------------------------
Please enter the hostname which you want to configure (XX.XX.XX.XX)
-> 129.214.160.160
ipaddr[0] = 129 ... digit1 = 8 ... digit2 = 1 ... hexaddr = 81
ipaddr[1] = 214 ... digit1 = D ... digit2 = 6 ... hexaddr = 81D6
ipaddr[2] = 160 ... digit1 = A ... digit2 = 0 ... hexaddr = 81D6A0
ipaddr[3] = 160 ... digit1 =  ... digit2 = 0 ... hexaddr = 81D6A00

Host ip entered was 129.214.160.160 (81D6A00)

Please enter the hostname which you want to configure (XX.XX.XX.XX)
-> 129.214.160.160
ipaddr[0] = 129 ... digit1 = 8 ... digit2 = 1 ... hexaddr = 81
ipaddr[1] = 214 ... digit1 =  ... digit2 = 6 ... hexaddr = 816
ipaddr[2] = 160 ... digit1 =  ... digit2 = 0 ... hexaddr = 8160
ipaddr[3] = 160 ... digit1 =  ... digit2 = 0 ... hexaddr = 81600

Host ip entered was 129.214.160.160 (81600)

Please enter the hostname which you want to configure (XX.XX.XX.XX)
-> 129.214.160.160
ipaddr[0] = 129 ... digit1 = 8 ... digit2 = 1 ... hexaddr = 81
ipaddr[1] = 214 ... digit1 =  ... digit2 = 6 ... hexaddr = 816
ipaddr[2] = 160 ... digit1 =  ... digit2 = 0 ... hexaddr = 8160
ipaddr[3] = 160 ... digit1 =  ... digit2 = 0 ... hexaddr = 81600

Host ip entered was 129.214.160.160 (81600)

Please enter the hostname which you want to configure (XX.XX.XX.XX)
-> 129.214.009.096
ipaddr[0] = 129 ... digit1 = 8 ... digit2 = 1 ... hexaddr = 81
ipaddr[1] = 214 ... digit1 =  ... digit2 = 6 ... hexaddr = 816
ipaddr[2] = 009 ... digit1 = 0 ... digit2 = 9 ... hexaddr = 81609
ipaddr[3] = 096 ... digit1 = 6 ... digit2 = 0 ... hexaddr = 8160960

Host ip entered was 129.214.009.096 (8160960)

Please enter the hostname which you want to configure (XX.XX.XX.XX)
-> 129.214.009.096
ipaddr[0] = 129 ... digit1 = 8 ... digit2 = 1 ... hexaddr = 81
ipaddr[1] = 214 ... digit1 =  ... digit2 = 6 ... hexaddr = 816
ipaddr[2] = 009 ... digit1 = 0 ... digit2 = 9 ... hexaddr = 81609
ipaddr[3] = 096 ... digit1 = 6 ... digit2 = 0 ... hexaddr = 8160960

Host ip entered was 129.214.009.096 (8160960)

tchrist@convex.COM (Tom Christiansen) (12/05/90)

In article <136559@pyramid.pyramid.com> mfrost@pyramid.com (Mark Frost) writes:
>Anyway, I've got another problem that has really been puzzling me. As part
>of a larger script I am writing which deals extensively with IP addresses,
>I am trying to convert decimal IP addresses to hex format. So 129.214.009.096
>would give me "81D60960". 

I didn't look too closely at your code, because it looks like you're
working way, way too hard.  I would just do this:

    sub in2hex { sprintf('%02X' x 4, split(/\./, $_[0])); } 

Of course, this isn't really like inet_addr(3N), as that will
accept addresses in the form a.b and a.b.c as well as a.b.c.d, 
which is the only form this rendition works for.  Accepting the
other forms I leave as an exercise to the reader.  :-)

--tom
--
Tom Christiansen		tchrist@convex.com	convex!tchrist
"With a kernel dive, all things are possible, but it sure makes it hard
 to look at yourself in the mirror the next morning."  -me

flee@dictionopolis.cs.psu.edu (Felix Lee) (12/05/90)

It looks like a Perl bug (tm).  Consider this fragment:
	for (1..3) {
		for $k (0..7) {
			$x = (1..4, 'a'..'d')[$k];
			print $x;
		}
		print "\n";
	}

This prints
	1234abcd
	1234
	1234

There's a number of different workarounds, but if you just want an
&IPTOHEX subroutine, this should do:
	sub IPTOHEX {
		local(@ip) = @_;
		sprintf('%02X' x 4, @ip);
	}
--
Felix Lee	flee@cs.psu.edu

lwall@jpl-devvax.JPL.NASA.GOV (Larry Wall) (01/11/91)

In article <F2tmzvm3@cs.psu.edu> flee@dictionopolis.cs.psu.edu (Felix Lee) writes:
: It looks like a Perl bug (tm).  Consider this fragment:
: 	for (1..3) {
: 		for $k (0..7) {
: 			$x = (1..4, 'a'..'d')[$k];
: 			print $x;
: 		}
: 		print "\n";
: 	}
: 
: This prints
: 	1234abcd
: 	1234
: 	1234

Fixed in 42.

Larry