views:

92

answers:

2

I've always used printf, and I've never used write/format. Is there any way to reproduce printf("%12.5e", $num) using a format? I'm having trouble digesting the perlform documentation, but I don't see a straightforward way of doing this.

EDIT: based on the answers I got, I'm just gonna keep on using printf.

+2  A: 

Short answer, don't use formats.

Unresearched answer, sure, just use sprintf:

#!/usr/bin/perl

use strict;
use warnings;

our $num = .005;

write;

format STDOUT =
@>>>>>>>>>>>>>>>>>
sprintf("%12.5e", $num)
.

Seriously, if you need something like Perl 5 formats, take a look at Perl6::Form (note, this is a Perl 5 module, it just implements the proposed Perl 6 version of formats).

Chas. Owens
+1: It is truly time to let legacy `format` go....
drewk
+2  A: 

I totally agree with Chas. Owens on formats in general. Format was really slick 15 years ago, but format has not kept up with the advancements of the rest of Perl.

Here is a technique for line oriented output that I use time to time. You can use formline which is one of the public internal functions used by format. Format is page oriented. It is very hard to do things like span columns or change the format by line depending on the data. You can format a single line using the same text formatting logic used by format and then output that result yourself.

A (messy) example:

use strict; use warnings;

sub print_line {
    my $pic=shift;
    my @args=@_;

    formline($pic,@args);
    print "$^A\n";
    $^A='';
}

my ($wlabel, $wlow, $whigh, $wavg)=(0,0,0,0);
my ($plabel,$plow,$phigh, $pavg);
my ($s_low,$s_high,$s_avg)=qw(%.2f %.2e %.2f);


my @results=( ["Label 1", 3.445, 0.00006678, .025],
           ["Label 2", 12.5555556, 55.112, 1.11],
           ["Wide Label 3", 1231.11, 1555.0, 66.66] );

foreach (@results) { 
    my $tmp;
    $tmp=length($_->[0]);
    $wlabel=$tmp if $tmp>$wlabel; 

    $tmp=length(sprintf($s_low,$_->[3]));
    $wlow=$tmp if $tmp>$wlow;

    $tmp=length(sprintf($s_high,$_->[2]));
    $whigh=$tmp if $tmp>$whigh;

    $tmp=length(sprintf($s_avg,$_->[1]));
    $wavg=$tmp if $tmp>$wavg;
}

print "\n\n";
my @a1=("Label", "Rate - Operations / sec");
my @a2=("Text", "Average", "High", "Low");
my @a3=("----------", "-------", "----", "---");
my $l1fmt="@".'|' x $wlabel."   @".'|'x($whigh+$wavg+$wlow+6);

my $l2fmt="@".'|' x $wlabel."    @".'|' x $wavg."   @".'|' x $whigh . 
           "   @".'|' x $wlow;
print_line($l1fmt,@a1);
print_line($l2fmt,@a2);
print_line($l2fmt,@a3);

$plabel="@".'>' x $wlabel;
$phigh="@".'>' x $whigh;
$pavg="@".'>' x $wavg;
$plow="@".'<' x $wlow;


foreach (@results) {
    my $pic="$plabel   $pavg   $phigh   $plow";
    my $mark=$_->[0];
    my $avg=sprintf($s_avg,$_->[1]);
    my $high=sprintf($s_high,$_->[2]);
    my $low=sprintf($s_low,$_->[3]);
    print_line($pic,$mark,$avg,$high,$low);
}
print "\n\n";

Outputs this:

    Label         Rate - Operations / sec
    Text         Average      High       Low
 ----------      -------      ----       ---
      Label 1       3.44    6.68e-05   0.03
      Label 2      12.56    5.51e+01   1.11
 Wide Label 3    1231.11    1.56e+03   66.66

Notice that the width of the columns is set based on the width of the data as formatted by the sprintf format string. You can then left, center, right justify that result. The "Low" data column is left justified, the rest of the data are right justified. You can change this by the symbol used in the scalar $plow and it is the same as format syntax. The labels at the top are centered and the "Rate - Operations / sec" label spans 3 columns.

This is obviously not "production ready" code, but you get the drift I think. You would need to further check the total width of the columns against desired width, etc. You have to manually do some of the work that format does for you, but you have far more flexibility with this approach. It is very easy to use this method for several sections of a line with sprintf for example.

Cheers.

drewk
Even 15 years ago I never used formats. I thought they were some kind of legacy even when I was using Perl 4!
Gabe
@downvoter: why?
drewk