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

Dear monks, I want to push a load of numbers into an array as they are created, but need to also format them using (s)printf before they go into the array. Is there a way to do this? I tried:
push @array, sprintf "%.5f", "$number\n";
but it dodn't work! Cheers

Replies are listed 'Best First'.
Re: (s)printf and push
by Abigail-II (Bishop) on Sep 30, 2003 at 10:40 UTC
    "Doesn't work" is not very useful. Is it sitting on the couch all day, watching television? Can't it be compiled? Does it do something, but not what you expect? Do you bring in your car to the mechanics and say "Fix it, it doesn't work"? Be more specific. As shown in another post in this thread, the code you supply does work for me. At least, it fits my definition of "working code". But we don't know what yours is.

    Abigail

Re: (s)printf and push
by Roger (Parson) on Sep 30, 2003 at 10:27 UTC
    Ummm, of cause it's not going to work, you are passing the wrong argument into sprintf. Try to change to this:
    push @array, sprintf "%.5f\n", $number;
    The reason why your sprintf didn't work is because sprintf was expecting a floating point number as the second argument (that matches %.5f), while you were passing in a string.

    Update: my mistake, as people pointed out, perl is quite happy with the syntax. Only that the string pushed into the array does not contain "\n", which is probably what the monk wanted in the first place.
      Trailing non-digits are fine - Perl will ignore them when converting strings to numbers (not just Perl, atoi() and friends allow that too). And if a newline is following the number, Perl won't even emit a warning:
      #!/usr/bin/perl use strict; use warnings; my @array; my $number = "3\n"; push @array, sprintf "%.5f", "$number\n"; print $array [0], "\n"; __END__ 3.00000

      Abigail

      Oh, it "works" alright, only the formatted string won't contain the newline, which is likely what the OP wanted. Putting the newline where it belongs, in the (s)printf format, like you did, does that trick.
Re: (s)printf and push
by davido (Cardinal) on Sep 30, 2003 at 23:23 UTC
    As others have pointed out, the "\n" contained in the string, "$number\n" basically just falls into the bitbucket since it has nowhere better to go in the string to number conversion that's taking place. Perl would happily do this for you without complaining because you aren't placing "use warnings;" at the top of your program (be sure that "use strict;" is there too!). You also have the potential for order of operations problems, at least from a readability standpoint. For example, do you mean:

    push( @array, sprintf( "%.5f", "$number\n") );
    ....or do you mean....

    push( @array, (sprintf "%.5f"), "$number\n");

    Of course the latter makes no sense at all, and Perl gets it right too. But in more complex constructs a bunch of parameter lists flattened out into one long list separated by commas, with no parenthesis, can get a little confusing.

    As far as how to solve your immediate problem, if what you really want is to push a list of numbers, formatted, with a newline at the end of each number, what you really meant to say was:

    push @array, sprintf( "%.5f", $number) . "\n";

    Note the use of the concatenation operator, ".", which essentially appends "\n" to the string created by your call to sprintf. Then the entire string (the results of sprintf, concatenated with "\n" at the end) gets pushed onto @array by push.

    You could also have done it like this:

    push @array, sprintf( "%.5f%s", $number, "\n");

    In which case you're providing multiple fields to be pasted into the format string in sprintf.

    On a non-technical note, you also really meant to say (instead of "doesn't work") that "It doesn't do what I expected.". You would then go on to explain what you expected and what you got instead. "doesn't work" usually fails to accurately describe the problem, and ambiguity in describing problems is almost as difficult to decipher as the ambiguity that often created the problem in the first place.

    Dave

    "If I had my life to do over again, I'd be a plumber." -- Albert Einstein