Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

using format twice

by zer (Deacon)
on Apr 05, 2006 at 02:01 UTC ( [id://541253]=perlquestion: print w/replies, xml ) Need Help??

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;

OUTPUT

Format 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

Replies are listed 'Best First'.
Re: using format twice
by moklevat (Priest) on Apr 05, 2006 at 03:44 UTC
    You might look into using Perl6::Form. Damian Conway mentions it in his book, Perl Best Practices. Incidentally, the book also has a lot of advice for avoiding ugly (unmaintainable) code.

    You might do something like this:
    updated with a better example and output text.

    #!/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 | ===========================================================
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
      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.
        Doc--

        I think he meant "Hideoust" 8^)

        --roboticus

      ya as ugly as my code is............. yaaaaaaa..... no comment

      BTW with the printf "%10d... it errors on numbers like 90000000000... part of the reason im doing this in perl and not C *shudders*

        No problem there. Change it to printf "%10s. That would work for C too. :)


        DWIM is Perl's answer to Gödel
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

      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;
      OUTPUT
      Format 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
        zer--

        You'll want to read up the "perlform" man page and see how to use multiple formats. There are several ways listed, but my favorite is shown below. (I got really bored and hacked on your program a little)

        #!/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

Re: using format twice
by novitiate (Scribe) on Apr 05, 2006 at 03:27 UTC
    Create a sub and call it in the foreach passing a (\%val,$_) each time around. in the sub, create a format with a name and localize $~ (current format) like this local $~ = 'SOME_FORMAT_NAME'; then just call write like this: write(); return the total of price * quantity as a return value to the caller in the foreach loop and it to $total; for the end print, just define the STDOUT format for printing the total after the last call to write immediately outside the foreach (write automatically calls STDOUT).


    humbly,
    novitiate

    "...goodnight you princes of main(e)"  --The Cider House Rules

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://541253]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-04-20 03:42 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found