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

hi guys, i have a really simply question, why doesn't these two snippets of code do the same thing? 1)
my @a; $a[0] = 5; $a[1] = 2; for(my $n=0;$n < scalar(@a); $n++) { $b[$n] = sprintf("%.2f", $a[$n]; } print "$b[0] : $b[1]\n";
2)
my @a; $a[0] = 5; $a[1] = 2; $b[0] = sprintf("%.2f", $a[0]; $b[1] = sprintf("%.2f", $a[1]; print "$b[0] : $b[1]\n";
basically the first snippet doesn't set $b[1] it only sets $b[0], is this something weird with sprintf or something dodgey with my for loop?

cheers
Dave

Edit kudra, 2001-11-04 Corrected markup

Replies are listed 'Best First'.
Re: sprintf and for loop weirds???
by Fastolfe (Vicar) on Nov 04, 2001 at 21:16 UTC
    If your intent is to turn @b into an array of %.2f-formatted numbers from @a, this is a perfect job for map:
    @b = map { sprintf("%.2f", $_) } @a;
    The compactness of this might even mean that you don't even need @a in the first place. Avoid unnecessary temporary variable storage.

    Hope this helps...

Re: sprintf and for loop weirds???
by rob_au (Abbot) on Nov 04, 2001 at 16:07 UTC
    Your for loop should read ...

    for (my $n = 0; $n <= scalar(@a); $n++) { ... }

    Note the change in operator - Your code was only doing one iteration through the loop while $n was less than 1 and not less than or equal to 1. As such, it was only iterating through the loop once and setting $b[0] and not $b[1] - If you had more values in @a, you would have found it iterating through and acting on all except the last value.

     

    Ooohhh, Rob no beer function well without!

      Of course it "should" have read:
      for my $n (0..$#a) { ... }
      to avoid the possiblity of the off-by-one mistake in the first place. ;-)

      Update: or for (@a) as larsen notes below....

      -Blake

        Or even more robustly with ...

        for my $n ($[..$#a) { ... }

        For the rare possibility where the first index of arrays may be non-zero as a result of some other strange code obfuscation. :-)

        Update : push(@b, sprintf("%.2f", $_)) foreach @a; as suggested by larsen may be nicer and much prettier, but hey! I like obfuscated code :-)

         

        Ooohhh, Rob no beer function well without!

      scalar(@a) returns the number of elements in @a, not the index of the last element. Using $n <= scalar(@a) will iterate an extra time, past the end of the array. The original poster's use of $n < scalar(@a) was correct.

      In fact, after fixing the missing parentheses in both snippets, both snippets produce the expected results. However, the missing parentheses make it clear we're not looking at the original poster's actual code.

Re: sprintf and for loop weirds???
by larsen (Parson) on Nov 04, 2001 at 16:13 UTC
    Both snippets works well on my box (Windows + ActiveState), but I had to fix a syntax error, adding a ')' at the end of your sprintf instructions. It produced a compile-time error, so I guess this is not your problem.

    As a sidenote, I suggest you to write similar loops in a more "perlish" way:

    foreach (@a) { push @b, springf("%.2f", $_); }
    Update: Ermm... Of course one of the scripts DOES NOT work well. It's better I don't say why I had the impression the first one worked ;)
Re: sprintf and for loop weirds???
by echo (Pilgrim) on Nov 04, 2001 at 17:17 UTC
    When checked with perl -cw, your first snippet yields:

    syntax error at foo line 6, near "];"

    The sprintf call is missing a closing parenthesis.
Re: sprintf and for loop weirds???
by Anonymous Monk on Nov 05, 2001 at 18:45 UTC
    yup thanks guys, i ended up using map :) works best, i think why it wasn't working is because perls sprintf calls the systems sprintf when dealing with floats
    Try this code on for size
    $a[0] = 5; $a[1] = 3; $a[3] = 15; for($n = 0; $n < scalar (@a); $n++) { $b[n]=sprintf("%.2f", $a[n]); } print "$b[0]\n"; print "$b[1]\n"; print "$b[2]\n"; print "$b[3]\n";
    the output of this is "5.00\n\n\n\n"...

    Notice the $a2 is not defined, perhaps something with C's sprintf doesn't like how perl deals with undefined vars???
    this is copied and pasted from a shell so there are no sytax probs here :P

    cheers
    Dave