[Omaha.pm] sprintf is your friend

Jay Hannah jay at jays.net
Mon Aug 28 18:11:18 PDT 2006


Daniel Linder wrote:
> On Fri, August 25, 2006 15:47, Jay Hannah wrote:
>> Before:
>>
>> sub prepend_pegheader
>>   {
>>     my ($str, $msgtype) = (@_);
>>     my $len = length($str) + 6;
>>     $len = "00000" . $len;       # Just slap 5 zeroes onto the front and
>> only
>>     $len =~ s/^\d+(\d{5})$/$1/;  # take the last 5 characters.
>>     $str = "$msgtype$len$str";
>>     return $str;
>>   }
> 
> I don't like this -- it seems to use a lot of extra steps to achieve the
> same result.  I'd only use this over the other one if it was faster and
> that was a paramount issue in the program.

Indeed. Whenever I post "Before:" and "After:" code samples I'm asserting that the "After:" is a better way to do the same thing. It appears you and I agree in this case. :)

> The only place I can realistically see this breaking is if "len" is >99999
> - thus only the last five digits of the real number would get captured. 
> At least with "sprintf" it will expand the "%05d" to show all six digits
> if needed.  Of course that might be the intent so that the sixth column is
> *always* the start of "str" nomatter what.
> 
> dan at dglinder:~/tmp$ cat d.pl
> #!perl -w
> 
> $number = 123;
> $line = sprintf ("1: %05d\n", $number);
> printf ("%s", $line);
> 
> $number = 123123;
> $line = sprintf ("2: %05d\n", $number);
> printf ("%s", $line);
> 
> dan at dglinder:~/tmp$ perl ./d.pl
> 1: 00123
> 2: 123123

Ah, yes. Good point about numbers > 99999. In my particular context, such a thing is not supposed to be possible so I think my conversion was valid.

>> After:
>> sub prepend_pegheader
>>   {
>>     my ($str, $msgtype) = (@_);
>>     my $len = sprintf("%05d", length($str) + 6);
>>     return "$msgtype$len$str";
>>   }
> 
> This is my pick, even if it is a slight bit slower in the end -- much more
> readable.  If you do get six digits showing up where you only wanted five
> then I would recommend that you check why the length of "str" is so great,
> and either adjust the five digits to six or larger, or fix the input being
> placed into "str".

In my particular context the vendor specification does not allow for lengths > 99999. So I don't know what I "should do" if the length was longer. Dump core and page everyone, probably. :)

After I posted that I was have tempted to Perl golf it down to 

  sub prepend_pegheader {
     my ($str, $msgtype) = (@_);
     return sprintf("%s%05d%s", $msgtype, length($str) + 6, $str);
  }

or 

  sub prepend_pegheader {
     sprintf("%s%05d%s", $_[1], length($_[0]) + 6, $_[0]);
  }

or no sub at all since it's one line now. :)

But I'm not that evil. I like being able to read the code I wrote yesterday without excessive quantities of ellicit drugs. 

j





More information about the Omaha-pm mailing list