zer has asked for the wisdom of the Perl Monks concerning the following question:
Hello,
Im trying to run a format twice. The problem is that unless I use STDOUT as the format name it fails, and if i use it twice it redefines it.
#!/usr/bin/perl -w
use strict;
use warnings;
print "Packaged Goods Organizer\n========================\n";
my %val;my $total=0;
DO:{
BAR : print "Barcode : ";$_=<>;chomp;last if ($_ == "0");
if (($_ >= 10000000000)|| ($_ < 1000000000)||/[^0-9]/){
print "Bad input (numbers only and between 1000000000 and 9999
+999999)\n";
goto BAR;
}else{
Price : print "Price : ";$val{$_}{"Price"}=<>;chomp($val{$
+_}{"Price"});
do{print "Numbers only\n";goto Price} if ($val{$_}{"Price"}=~
+/[^0-9\.]/);
Quant : print "Quantity : ";$val{$_}{"Quantity"}= <>;chomp($v
+al{$_}{"Quantity"});
do{print "Numbers only\n";goto Quant}if ($val{$_}{"Quantity"}=
+~ /[^0-9]/);
}goto DO;
};
print "\n\n\t\tGoods in Stock\n\t\t==============\nBarcode Price
+Quantity Value\n-----------------------------------\n";
foreach (sort keys %val){
format STDOUT =
@<<<<<<<<<<<<<$@<<<<<<<<<$@<<<<<$@
$_, $val{$_}{"Price"}, $val{$_}{"Quantity"}, $val{$_}{"Price"} * $val{
+$_}{"Quantity"}
.
write STDOUT;
$total += $val{$_}{"Price"} * $val{$_}{"Quantity"};
}close (STDOUT);
format STDOUT =
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$@
"-----"
Total value good in stock>>>>>>>$@
$total
.
write STDOUT;
OUTPUTFormat STDOUT redefined at C:\Documents and Settings\\My Documents\per
+ltest
\Perl-1.pl line 28.
Packaged Goods Organizer
========================
Barcode : 1231231231
Price : 21
Quantity : 2
Barcode : 1231231232
Price : 44
Quantity : 2
Barcode : 0
Goods in Stock
==============
Barcode Price Quantity Value
-----------------------------------
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$-
Total value good in stock>>>>>>>$0
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$-
Total value good in stock>>>>>>>$4
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$-
Total value good in stock>>>>>>>$1
Re: using format twice
by moklevat (Priest) on Apr 05, 2006 at 03:44 UTC
|
#!/usr/bin/perl -w
use strict;
use Perl6::Form;
my @barcodes=qw/8129348 2354234 234234534 21342134 23453421/;
my @prices = qw/625.50 626.35 234.23 546.54 3245.45/;
my @quants = qw/2 2 34 4 6/;
my @values = qw/21345 345345 345345 3453 34534/;
my $total = 0;
foreach(@values){$total+=$_};
print form
' ============================================================',
'| Goods in Stock |',
'|===========================================================|',
'| Barcode | Price | Quantity | Value |',
'|-------------+---------------+-------------+---------------|',
'| {[[[[[[[[[} | {$]]]]]].[[[} | {]]]]]]]]]} | {$]]]]]]].[[[}|',
\@barcodes, \@prices, \@quants, \@values,
'|===========================================================|',
'| Total Value In Stock {$]]]]]]].[[[}|',
$total,
' =========================================================== ',
;
Produces:
===========================================================
| Goods in Stock |
|===========================================================|
| Barcode | Price | Quantity | Value |
|-------------+---------------+-------------+---------------|
| 8129348 | $625.5 | 2 | $21345.0 |
| 2354234 | $626.35 | 2 | $345345.0 |
| 234234534 | $234.23 | 34 | $345345.0 |
| 21342134 | $546.54 | 4 | $3453.0 |
| 23453421 | $3245.45 | 6 | $34534.0 |
|===========================================================|
| Total Value In Stock $750022.0 |
===========================================================
| [reply] [d/l] [select] |
Re: using format twice
by GrandFather (Saint) on Apr 05, 2006 at 03:09 UTC
|
This is some of the uglyest code I've seen posted on PerlMonks! There is absolutly no need for any of the gotos that are scattered all through the code!
The following does what you seem to want to do without the gotos and without the troublesome format stuff:
#!/usr/bin/perl -w
use strict;
use warnings;
print "Packaged Goods Organizer\n========================\n";
my %val;
my $total=0;
while (do {print "Barcode : "; $_ = <DATA>}) {
chomp;
last if ($_ == "0" || ! length);
if (($_ >= 10_000_000_000) || ($_ < 1_000_000_000)|| /[^0-9]/){
print "Bad input (numbers only and between 1000000000 and 9999
+999999)\n";
next;
}
my $code = $_;
while (do {print "Price : "; $_ = <DATA>}) {
chomp;
if (/[^0-9\.]/) {
print "Numbers only\n";
next;
}
$val{$code}{"Price"}= $_;
last;
}
while (do {print "Quantity : "; $_ = <DATA>}) {
chomp;
if (/[^0-9]/) {
print "Numbers only\n";
next;
}
$val{$code}{"Quantity"}= $_;
last;
}
};
print "\n\n\t\tGoods in Stock\n\t\t==============\nBarcode Price
+Quantity Value\n-----------------------------------\n";
for (sort keys %val){
my $value = $val{$_}{"Price"} * $val{$_}{"Quantity"};
printf "%10d%8.2f%9d%8.2f\n",
$_, $val{$_}{"Price"}, $val{$_}{"Quantity"}, $value;
$total += $value;
}
printf "-----\nTotal value in stock \$%.2f\n", $total;
__DATA__
1231231231
21
2
1231231232
44
2
0
Prints:
Packaged Goods Organizer
========================
Barcode : Price : Quantity : Barcode : Price : Quantity :
+ Barcode :
Goods in Stock
==============
Barcode Price Quantity Value
-----------------------------------
1231231231 21.00 2 42.00
1231231232 44.00 2 88.00
-----
Total value in stock $130.00
Note that the <DATA> uses should change to <> to get the data from stdin per your original code. I was too lazy to type the values in so opted for __DATA__ doing the work for me.
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
|
Can I commend you to sainthood for that act of compassion? You remind me of Buddha vanquishing return of the frightening demon "GOTO" with the sword of discrimination, restoring sanity.
However, "uglyest" fails my English language parser. Although one never knows around here whether something is intentional or not, so perhaps you were merely mirroring the uglyness, as in UGLY, of that code you cleaned up.
| [reply] |
|
| [reply] |
|
| [reply] |
|
| [reply] [d/l] |
|
|
|
Re: using format twice
by roboticus (Chancellor) on Apr 05, 2006 at 02:19 UTC
|
zer--
When I loaded your code, I got an entirely different error message. However, at a cursory glance, the error that you're reporting is due to your writing to the STDOUT stream after closing it.
On another note, you might want to format your code a little better to make it easier for others to review. You're using some rather odd coding structures...
--roboticus | [reply] |
|
Update: i removed the close and this is what i get. And as more of an insight to the error... when i changed the second format name to something other than STDOUT it wouldnt print because it is trying to write to an unopened file handle.
#!/usr/bin/perl -w
use strict;
use warnings;
print "Packaged Goods Organizer\n========================\n";
my %val;my $total=0;
DO:{
BAR : print "Barcode : ";$_=<>;chomp;last if ($_ == "0");
if (($_ >= 10000000000)|| ($_ < 1000000000)||/[^0-9]/){
print "Bad input (numbers only and between 1000000000 and 9999
+999999)\n";
goto BAR;
}else{
Price : print "Price : ";
$val{$_}{"Price"}=<>;
chomp($val{$_}{"Price"});
if ($val{$_}{"Price"}=~ /[^0-9\.]/){
print "Numbers only\n";
goto Price;
}
Quant : print "Quantity : ";
$val{$_}{"Quantity"}= <>;
chomp($val{$_}{"Quantity"});
if ($val{$_}{"Quantity"}=~ /[^0-9]/){
print "Numbers only\n";
goto Quant;
}
}goto DO;
};
print "\n\n\t\tGoods in Stock\n\t\t==============\nBarcode Price
+Quantity Value\n-----------------------------------\n";
foreach (sort keys %val){
format STDOUT =
@<<<<<<<<<<<<<$@<<<<<<<<<$@<<<<<$@
$_, $val{$_}{"Price"}, $val{$_}{"Quantity"}, $val{$_}{"Price"} * $val{
+$_}{"Quantity"}
.
write STDOUT;
$total += $val{$_}{"Price"} * $val{$_}{"Quantity"};
}close (STDOUT);
format STDOUT =
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$@
"-----"
Total value good in stock>>>>>>>$@
$total
.
write STDOUT;
OUTPUTFormat STDOUT redefined at C:\Documents and Settings\\My Documents\per
+ltest
\Perl-1.pl line 38.
Packaged Goods Organizer
========================
Barcode : 1231231231
Price : 22
Quantity : 1
Barcode : 0
Goods in Stock
==============
Barcode Price Quantity Value
-----------------------------------
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$-
Total value good in stock>>>>>>>$0
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$-
Total value good in stock>>>>>>>$2
| [reply] [d/l] [select] |
|
#!/usr/bin/perl -w
use strict;
use warnings;
use FileHandle;
my (%val, $total);
$total=0;
format DETAIL =
@<<<<<<<<<<<<<$@<<<<<<<<<$@<<<<<$@
$_, $val{$_}{"Price"}, $val{$_}{"Quantity"}, $val{$_}{"Price"} * $val{
+$_}{"Quant
ity"}
.
format SUMMARY=
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<$@
"-----"
Total value good in stock>>>>>>>$@
$total
.
print "Packaged Goods Organizer\n"
. "========================\n";
# Collect the data
ENTRY:
while (1) {
BAR:
while (1) {
print "Barcode : ";
$_=<>;
chomp;
last ENTRY if ($_ == "0");
last BAR unless ($_ >= 10000000000) || ($_ < 100000000
+0) || /[^0
-9]/;
print "Bad input (numbers only and between 1000000000
+and 999999
9999)\n";
}
Price:
while (1) {
print "Price : ";
$val{$_}{"Price"}=<>;
chomp($val{$_}{"Price"});
last Price unless ($val{$_}{"Price"}=~ /[^0-9\.]/);
print "Numbers only\n";
}
Quant:
while (1) {
print "Quantity : ";
$val{$_}{"Quantity"}= <>;
chomp($val{$_}{"Quantity"});
last Quant unless ($val{$_}{"Quantity"}=~ /[^0-9]/);
print "Numbers only\n";
}
}
# Write the detail records
print "\n\n\t\tGoods in Stock\n"
. "\t\t==============\n"
. "Barcode Price Quantity Value\n"
. "-----------------------------------\n";
format_name STDOUT "DETAIL";
foreach (sort keys %val) {
write STDOUT;
$total += $val{$_}{"Price"} * $val{$_}{"Quantity"};
}
# Write the summary
format_name STDOUT "SUMMARY";
write STDOUT;
close(STDOUT);
Specifically, I added the 'use FileHandle;' up front, renamed your formats to DETAIL and SUMMARY (and moved 'em closer to the front, where I normally put 'em in my programs). Finally, in the code, I put in the 'format_name' statements to tell STDOUT which format to use.
--roboticus
| [reply] [d/l] |
|
Re: using format twice
by novitiate (Scribe) on Apr 05, 2006 at 03:27 UTC
|
| [reply] |
|
|