in reply to How to right align outputs of stored data in a variable?

I like the answer from davido. Some additional comments for you...

The printf() "format spec" reserves a minimum field width. In some cases that minimum width will be exceeded to print what is necessary.

When there are multiple variables, I always put an explicit space in the format spec to guarantee that the printout will have a space between columns. If you have a 5 digit integer, do not use %6d and count on that leading column to be blank. Use " %5d". If 8 digits show up for the integer, they will get printed and perhaps more importantly a space will separate that column from the previous one. Here are some examples:

#!/usr/bin/perl use strict; use warnings; my $x = "a_long_string"; print "*using a single field:\n"; printf "%3s\n","a"; printf "%3s\n","abc"; printf "%3s\n",$x; print "\n*using format with 2 fields:\n"; printf "%3s%4s\n", "abc", "a"; printf "%3s%4s\n", "abc", "abcd"; printf "%3s%4s\n", $x, "abcd"; printf "%3d%3d\n", 123, 456; # # better, use a explict space between format fields # print "\n*using explict space between 2 fields\n"; printf "%3s %4s\n", $x, "abcd"; printf "%3d %3d\n", 123789, 456; __END__ *using a single field: a abc a_long_string *using format with 2 fields: abc a abcabcd a_long_stringabcd 123456 *using explict space between 2 fields a_long_string abcd 123789 456

Replies are listed 'Best First'.
Re^2: How to right align outputs of stored data in a variable?
by AnomalousMonk (Archbishop) on Feb 05, 2017 at 23:23 UTC
    ... a minimum field width. ... that ... will be exceeded to print what is necessary. ... an explicit space in the format spec to guarantee that the printout will have a space between columns.

    A good point. I guess I was distracted by the fact that the field labels already had semicolons to delimit the name fields. :)


    Give a man a fish:  <%-{-{-{-<

      No problem. Your post++ also illustrated a good point that might be missed by many... The "format string" can be calculated dynamically. This is also possible in C using sprintf(). But here is a Perl demo:
      #!/usr/bin/perl use strict; use warnings; my $textlength=3; my $numlength=1; # on purpose too narrow my $fmt = "%-$textlength".'s '."%$numlength"."d\n"; print "format is:$fmt"; printf $fmt, "a",1; printf $fmt, "abc",123; printf $fmt, "abcdef",12345; __END__ prints: format is:%-3s %1d a 1 abc 123 abcdef 12345
      I like uniformity in the code and probably would have written the OP's code something like this:
      #!/usr/bin/perl use strict; use warnings; use List::Util qw(sum); my ($FreqP, $FreqN, $FreqZ) = map {int rand 41600} 0..2; my $Sum = sum($FreqP, $FreqN, $FreqZ); printf ( "Freq(Z+): %19d\n" , $FreqP) ; printf ( "Freq(Z-): %19d\n" , $FreqN) ; printf ( "Freq(0): %19d\n" , $FreqZ) ; printf ( "Total: %19d\n" , $Sum) ; __END__ Freq(Z+): 11640 Freq(Z-): 3527 Freq(0): 33243 Total: 48410
        my $fmt = "%-$textlength".'s '."%$numlength"."d\n";

        I don't see the point of all the dots. I think I would have used a straight double-quote interpolation:
            my $fmt = "%-${textlength}s %${numlength}d\n";
        It seems clearer to my eye IMHO.

        I like uniformity in the code ...

        I like it too, and also the idea of reducing code to data. If I were to go all the way with this, I might write something like this (which also takes care of a common colon that's running through all the strings):

        c:\@Work\Perl\monks>perl -wMstrict -le "use List::Util qw(sum); ;; my $Sum = sum my ($FreqP, $FreqN, $FreqZ) = map { int rand 41600 } 0. +.2; ;; my @rows = ( ['Freq(Z+)', $FreqP], ['Freq(Z-)', $FreqN], ['Freq(0)', $FreqZ], [' +Total', $Sum], ); ;; my $txtwidth = 9; my $numwidth = 16; ;; my $fmt = qq{%-*s %*d \n}; printf $fmt, $txtwidth, qq{$_->[0]:}, $numwidth, $_->[1] for @rows; " Freq(Z+): 25578 Freq(Z-): 39490 Freq(0): 13091 Total: 78159
        The  $fmt string can now be generated/stored/retrieved entirely independently, data to be printed are pure data, etc.

        But this is all probably overkill...


        Give a man a fish:  <%-{-{-{-<