in reply to Re: Help with Creating a Table from array ref I parsed in
in thread Help with Creating a Table from array ref I parsed in

Hello Ken

I've read printf FORMAT LIST and edited your program to learn how it behaves; however, I do not understand it completely, can you explain some things I am still doubtful?

So, I edited your $fmt statement and tried to left-adjust and play with the spaces in between columns; however, I cannot understand the spaces between the 3rd and 4th columns.

 my $fmt = "%-13s % 24f %-24f %-4s\n %38.6f %14f %-4s\n";

the output of some of the 2nd columns seems to be left-justified except when the number is negative. How can that negative be moved in one more space so everything is left-justified?

And, the spacing between the 3rd and 4th columns are not clear to me yet? I know that Between the % and the format letter, some attributes control the interpretation, Can you explain how these spaces are moved in the 3rd and 4th fields?

MM_STD_gate 152.401574 -22.047244 mils 3871.000000 -560.000000 microns RFN_a 337.244094 0.787402 mils 8566.000000 20.000000 microns RFN_b 366.181102 0.787402 mils 9301.000000 20.000000 microns RFN_c 376.929133 0.787402 mils 9574.000000 20.000000 microns MM_STD2_gate -259.488188 -22.047244 mils -6591.000000 -560.000000 microns RBASE_right_2 -366.181102 -33.464566 mils -9301.000000 -850.000000 microns

I'll like to see all columns left-justified (the negative number is also left-justified with the number below or above) and little bigger spaces in between. Note, that there can only be 6 decimal numbers in columns and upto 13-character string name is allowed.

MM_STD_gate 152.401574 -22.047244 mils 3871.000000 -560.000000 microns RFN_a 337.244094 0.787402 mils 8566.000000 20.000000 microns RFN_b 366.181102 0.787402 mils 9301.000000 20.000000 microns RFN_c 376.929133 0.787402 mils 9574.000000 20.000000 microns MM_STD2_gate -259.488188 -22.047244 mils -6591.000000 -560.000000 microns RBASE_right_2 -366.181102 -33.464566 mils -9301.000000 -850.000000 microns

thanks for the explanations!

Replies are listed 'Best First'.
Re^3: Help with Creating a Table from array ref I parsed in
by roboticus (Chancellor) on May 16, 2022 at 14:19 UTC

    perlnewby:

    In your format specifier, you have '%24f' for the third column in the first line, but '%14f' for the matching column in the second line which is why the string 'mils' is pushed so far to the right. It's saying "the third column is a float and should fill 24 columns", so by changing it to '%14f' to match the second line, you should get the fourth column on both lines to align.

    What I frequently do in cases like this is to first break a multiline format at the line break:

    my $fmt = "%-13s % 24f %-24f %-4s\n" . " %38.6f %-14f %-4s\n";

    And then add some 'fake' fields so that I can use the same formatting on both lines, and in the print statement, just insert '' for the arguments matching the fake fields:

    my $fmt = "%-13s % 24f %-14f %-4s\n" . "%-13s %24.6f %-14f %-4s\n"; . . . . printf $fmt, 'MM_STD_gate', 152.401574, -22.047244, 'mils', '', 3871.0, -560.0, 'microns';

    When you're doing things that aren't time critical, I find it useful to do something like this to make adjusting the format easier and paying a slight loss of inefficiency.

    Note: The formats for the printf() family of functions are pretty convenient, but have some limitations when you're trying to make text reports. Specifically, controlling field widths, aligning values on decimal points, etc., can be difficult. In fact, your format with the %-4s at the end is blowing past your formatted column width for the 'microns' field. Not important, as it's the last field on the line, but if you added another column to the right, you'd discover it fairly soon!

    A lesser-used output formatting technique when you're trying to reports on monospaced devices (like the console or a line printer) is the 'named formats' method of formatting text. (You can read the details about it with the 'perldoc perlform' command.) It's not something you necessarily want to use often, but you should read about it once or twice so you can be aware of it in the event that you want to use it in the future. It's kind of a throwback to the way reports are frequently done in COBOL on mainframes. One advantage of it is that it can handle top of form and bottom of form for printouts, and it's visually easy to edit. It also doesn't blow out the column widths: instead of breaking the report format, it fills fields that are too wide with '#####' instead (for numbers) or it just truncates the value (for text).

    However, now that we're in a more modern era where monospaced output isn't nearly so common and online reports are easier to deal with (and more environmentally friendly that printing a ream of paper for a report you'll use twice and then discard), it would be better to read about Template::Toolkit where you can generate *many* types of reports, flexibly.

    I was still waking up with my morning coffee, so I took a few minutes and put together a quickie demo of the first two techniques below. (I didn't demo the third technique because I don't have Template::Toolkit installed on this machine (and don't really use it much anyway.)

    Roboticus@Waubli ~ $ cat t.pl use strict; use warnings; # The data my @recs = ( [ 'MM_MM_STD_gate', 152.401574, -22.047244, 'mils', 3871.0, -560.0, 'microns' ], [ 'RFN_a', 337.244094, 0.787402, 'mils', 8566.0, 20.0, 'microns' ], [ 'RFN_b', 366.181102, 0.787402, 'mils', 9301.0, 20.0, 'microns' ], [ 'RFN_c', 376.929133, 0.787402, 'mils', 9574.0, 20.0, 'microns' ], [ 'MM_STD2_gate', -259.488188, -22.047244, 'mils', -6591.0, -560.0, 'microns' ], [ 'RBASE_right_2', -366.181102, -33.464566, 'mils', -9301.0, -850.0, 'microns' ], ); print "\n------ Report1: (printf) ------\n\n"; # I made it easy on myself by *not* using the fake field here so I cou +ld # just print the data by expanding the data in-line in the printf stat +ement. my $fmt = "%-13s % 24f %-14f %-4s\n" . " %24.6f %-14f %-4s\n"; for my $ar (@recs) { printf $fmt, @$ar; } print "\n\n------ Report 2 (Named formats) ------\n\n"; # The format statement embeds the variables to map to the fields inlin +e, so # the variable must already be declared my $ar; # Define the format visually, along with the variables to stuff into t +hem format DETAIL = @<<<<<<<<<<<< @####.##### @###.###### @<<<<<<<<< $ar->[0], $ar->[1], $ar->[2], $ar->[3], @####.##### @###.###### @<<<<<<<<< $ar->[4], $ar->[5], $ar->[6]; . # Specify the format type to use for each write statement (you can hav +e # multiple formats and switch between them as needed). select(STDOUT); $~ = "DETAIL"; # Print the report for $ar (@recs) { write; } Roboticus@Waubli ~ $ perl t.pl ------ Report1: (printf) ------ MM_MM_STD_gate 152.401574 -22.047244 mils 3871.000000 -560.000000 microns RFN_a 337.244094 0.787402 mils 8566.000000 20.000000 microns RFN_b 366.181102 0.787402 mils 9301.000000 20.000000 microns RFN_c 376.929133 0.787402 mils 9574.000000 20.000000 microns MM_STD2_gate -259.488188 -22.047244 mils -6591.000000 -560.000000 microns RBASE_right_2 -366.181102 -33.464566 mils -9301.000000 -850.000000 microns ------ Report 2 (Named formats) ------ MM_MM_STD_gat 152.40157 -22.047244 mils 3871.00000 -560.000000 microns RFN_a 337.24409 0.787402 mils 8566.00000 20.000000 microns RFN_b 366.18110 0.787402 mils 9301.00000 20.000000 microns RFN_c 376.92913 0.787402 mils 9574.00000 20.000000 microns MM_STD2_gate -259.48819 -22.047244 mils -6591.00000 -560.000000 microns RBASE_right_2 -366.18110 -33.464566 mils -9301.00000 -850.000000 microns

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.