my @selections = ("Hamburger","Frankfurter","French Fries","Large Coke","Medium Coke","Small Coke","Onion Rings");
my @prices = (3.49, 2.19, 1.69, 1.79, 1.59, 1.39, 1.19);
my @quantity = (3, 0, 0, 4, 0, 0, 8);
printf("%s %10s %12s %10s\n", "Qty", "Desc.", "Unit \$", "Total");
for($meh = 0; $meh <= 6; $meh++)
{
if($quantity[$meh] != 0)
{
printf("%d %10s %9.2f %7.2f\n", $quantity[$meh], $selections[$meh], $prices[$meh], $prices[$meh]*$quantity[$meh])
}
}
我无法弄清楚如何使列排成一行。我按照另一篇文章的建议,但它仍然无效。
答案 0 :(得分:1)
问题是你的字符串长度超过10个字符,除非你指定最大宽度,否则Perl不会剪切它们,这是在字符串(%10.10s
)的点后面给出的。此外,您可能希望使用负数,以便它们与左侧对齐(%-10.10s
)。
答案 1 :(得分:1)
如果希望根据动态输入数据精确对齐列,则需要对行进行两次传递。第一次通过,记录每列的最大长度。然后使用这些长度构造格式字符串。最后,使用该格式字符串打印每一行。
use strict;
use warnings;
my @selections = ("Hamburger","Frankfurter","French Fries","Large Coke","Medium Coke","Small Coke","Onion Rings");
my @prices = (3.49, 2.19, 1.69, 1.79, 1.59, 1.39, 1.19);
my @quantity = (3, 0, 0, 4, 0, 0, 8);
my @rows;
push @rows, ["Qty", "Desc.", "Unit \$", "Total"];
# construct table data as a two-dimensional array
for (my $meh = 0; $meh < @selections; $meh++) {
next unless $quantity[$meh];
push @rows, [$quantity[$meh], $selections[$meh], $prices[$meh], $prices[$meh]*$quantity[$meh]];
}
# first pass over rows: compute the maximum width for each column
my @widths;
for my $row (@rows) {
for (my $col = 0; $col < @$row; $col++) {
$widths[$col] = length $row->[$col] if length $row->[$col] > ($widths[$col] // 0);
}
}
# compute the format. for this data, it works out to "%-3s %-11s %-6s %-5s\n"
my $format = join(' ', map { "%-${_}s" } @widths) . "\n";
# second pass: print each row using the format
for my $row (@rows) {
printf $format, @$row;
}
产生这个输出:
Qty Desc. Unit $ Total
3 Hamburger 3.49 10.47
4 Large Coke 1.79 7.16
8 Onion Rings 1.19 9.52
答案 2 :(得分:1)
很久以前,Perl主要用于格式化文件。它仍具有此功能,但自从Perl 4.x问世以来,我还没有看到它在程序中使用过。
查看perlform文档,format函数和write函数。
我会给你一个关于代码看起来像什么的例子,除了我多年没有做过。否则,请使用printf
语句。您可以使用%-10.10s
类型的格式限制文本字段的大小。这说左对齐字符串,并将其填充为10个字符,但不超过10个字符。
我还建议你买一本关于 现代 Perl的书。一个会教你references。
我已经重写了你的程序以使用引用。请注意,所有数据现在都在一个数组中,而不是分布在四个单独的数组上,您希望将这些数据保持在一起。
我可以通过$item[1]
来讨论$item[1]->{ENTREE}
的 ENTREE 。它更容易阅读,更易于维护。
另请注意,我已更改了for
循环。在你的,你必须知道你有七个项目。如果添加了新项目,则必须更改循环。在我的作品中,我使用$#menu
来获取菜单的最后一个索引。然后我使用(0..$#menu)
自动从0循环到@menu
数组中的最后一项。
use strict;
use warnings;
use Data::Dumper;
my @menu = (
{ ENTREE => "Hamburger", PRICE => 3.49, QUANTITY => 3 },
{ ENTREE => "Frankfurter", PRICE => 2.19, QUANTITY => 0 },
{ ENTREE => "French Fries", PRICE => 1.69, QUANTITY => 0 },
{ ENTREE => "Large Coke", PRICE => 1.79, QUANTITY => 4 },
{ ENTREE => "Medium Coke", PRICE => 1.59, QUANTITY => 0 },
{ ENTREE => "Small Coke", PRICE => 1.39, QUANTITY => 0 },
{ ENTREE => "Onion Rings", PRICE => 1.19, QUANTITY => 8 },
);
printf "%-3.3s %-10.10s %-6.6s %s\n\n", 'Qty', 'Desc.', 'Unit $', 'Total';
# Use $#menu to get the number of items in the array instead of knowing it's 6
foreach my $item (0..$#menu) {
# Dereference $menu[$item] to make $menu_item a hash
# This makes the syntax easier to read.
my %menu_item = %{ $menu[$item] };
if ( $menu_item{QUANTITY} ) {
printf "%3d %-10.10s %9.2f %7.2f\n",
$menu_item{QUANTITY}, $menu_item{ENTREE}, $menu_item{PRICE},
$menu_item{QUANTITY} * $menu_item{PRICE};
}
}
输出:
Qty Desc. Unit $ Total
3 Hamburger 3.49 10.47
4 Large Coke 1.79 7.16
8 Onion Ring 1.19 9.52