LogicalChaos has asked for the wisdom of the Perl Monks concerning the following question:

In this node, a question was asked on how to get leading 0's on a numerical input from a cgi script. dmmiller2k offers some good info on the subject of not using numerical methods on strings to keep them strings. And this is where my question lies. How/why does perl keep the leading 0 in some cases, but not in others? The below example and output demonstrate:
use warnings; use strict; my $v = 99; $v = sprintf( "%04d", $v ); print "$v\n"; ++$v; print "$v\n";
The output is:
0099 0100 200
Adding 1 to 99 and getting 100 shows that we're not incrementing in string land, so why does one numerical method preserve the leading 0 and not the other?
Thank you for your enlightnment.

Replies are listed 'Best First'.
Re: Leading zero's, and their persistance
by derby (Abbot) on Jan 08, 2002 at 01:59 UTC
    LogicalChaos,

    Ahh but you are incrementing in string land (and integer land is left alone). I missed what operation you used to get to 200 but it probably forced a switch from the PV value to the IV (or maybe NV). Use Devel::Peek to check:

    use warnings; use strict; use Devel::Peek; my $v = 99; print Dump( $v ); $v = sprintf( "%04d", $v ); print "$v\n"; print Dump( $v ); ++$v; print "$v\n"; print Dump( $v ); ++$v; print "$v\n"; print Dump( $v );

    and the output:

    SV = IV(0x8101d8c) at 0x8118330 REFCNT = 1 FLAGS = (PADBUSY,PADMY,IOK,pIOK,IsUV) UV = 99 0099 SV = PVIV(0x80f6ba8) at 0x8118330 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK) IV = 99 PV = 0x8103178 "0099"\0 CUR = 4 LEN = 5 0100 SV = PVIV(0x80f6ba8) at 0x8118330 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK) IV = 99 PV = 0x8103178 "0100"\0 CUR = 4 LEN = 5 0101 SV = PVIV(0x80f6ba8) at 0x8118330 REFCNT = 1 FLAGS = (PADBUSY,PADMY,POK,pPOK) IV = 99 PV = 0x8103178 "0101"\0 CUR = 4 LEN = 5

    -derby

Re: Leading zero's, and their persistance
by dmmiller2k (Chaplain) on Jan 08, 2002 at 01:48 UTC

    You code has only two print statements, but your output shows three lines; it's a little unclear whether you've inadvertantly omitted another print statement.

    However, presuming that the missing code looks like these two lines:

    $v += $v; print "$v\n";

    I may have an explanation.

    Which is, the increment and decrement operators, in particular, can be used to increment strings. In other words, they are not strictly numeric operations.

    my $x = 'A'; ++$x; print "$x\n";

    would print

    B

    So, changing the ++ to += 1 in your example produces different results.

    use warnings; use strict; my $v = 99; $v = sprintf( "%04d", $v ); print "$v\n"; $v += 1; print "$v\n"; $v += $v; print "$v\n";
    prints:
    0099 100 200

    dmm

    You can give a man a fish and feed him for a day ...
    Or, you can
    teach him to fish and feed him for a lifetime
Re: Leading zero's, and their persistance
by danger (Priest) on Jan 08, 2002 at 01:55 UTC
    Adding 1 to 99 and getting 100 shows that we're not incrementing in string land

    Actually, you didn't add 1 to 99 to get 100, you incremented the string '0099' and got '0100'. This is indeed incrementing in string land. String incrementing is magic and uses the ranges of digits, lowercase alpha, and upper case alpha to do the right kind of roll-over for each slot in the string.

Re: Leading zero's, and their persistance
by LogicalChaos (Beadle) on Jan 08, 2002 at 02:54 UTC
    Apologies for the missing code:
    $v *= 2; print "$v\n";
    I am now appropriately humbled by the insightful and useful comments. I knew I wasn't up to speed on Perl's internals, but I had no idea just how slow I was going until now...