Beefy Boxes and Bandwidth Generously Provided by pair Networks
Welcome to the Monastery
 
PerlMonks  

Question on using format and write

by Popcorn Dave (Abbot)
on Dec 13, 2002 at 19:41 UTC ( [id://219719]=perlquestion: print w/replies, xml ) Need Help??

Popcorn Dave has asked for the wisdom of the Perl Monks concerning the following question:

Fellow monks,

For the first time in my Perl programming, I've had to use formats. Up until now I haven't had a need to use them.

I've gone through the docs, and the Perl Black Book, but I'm not getting output from my data. Well I sort of am, but it's all 0.00 and blanks for the name - not exactly what I want.

My format code is:

format STDOUT = @<<<<<<<<<<<<<<<<<<<< $cust @#####.## @#####.## @#####.## @#####.## @#####.## @#####. +## $d1, $c1, $t1, $d2, $c2,$t2 @#####.## $total .

and the code producing the data is:

foreach $key (sort keys %ytd ){ my ($cust, $d1, $d2, $c1, $c2); my $t1 = $ytd{$key}->{d1}-$ytd{$key}->{c1}; my $t2 = $ytd{$key}->{d2}-$ytd{$key}->{c2}; $total = $t2-$t1; $cust = $key; $d1= $ytd{$key}->{d1}; $d2= $ytd{$key}->{d2}; $c1= $ytd{$key}->{c1}; $c2= $ytd{$key}->{c2}; write; }

but I've done something wrong as I'm not getting values out. I've confirmed that I do have vaild data using print statements, so I believe I've narrowed it down to a problem with my format statement.

My other question is if I can just use the foreach function to pass the variables directly to the write function or do I need to assign each one as I tried to do.

Thanks in advance for any help with this!

There is no emoticon for what I'm feeling now.

Replies are listed 'Best First'.
Re: Question on using format and write
by Tanalis (Curate) on Dec 13, 2002 at 19:45 UTC
    Not sure if this is the case from what you've got above, but all the variables in a format have to be in scope when you define the format, otherwise you'll simply get a load of blank lines output when you call write, even if the variables are in scope at the time of the write.

    I've found the easiest way to ensure this is to define the format right after the write call - but it's not the most elegant way to do it.

    Maybe it's something completely different .. not sure from what's there :)

    Hope that helps a little ..
    -- Foxcub

      Foxcub is correct. It looks like it is a scope problem. If you were to enforce warnings ( perl -w ) then you would get an error allong the lines of
      Use of uninitialized value in formline at ????.pl line ??.
      if you remove your line
      my ($cust, $d1, $d2, $c1, $c2);
      from the function, or perhaps put it before you define your format that should give you your output :-)

      _______________________________________________________
      Remember that amateurs built Noah's Ark. Professionals built the Titanic.
(jeffa) Re: Question on using format and write
by jeffa (Bishop) on Dec 13, 2002 at 21:17 UTC
    foreach $key (sort keys %ytd ){ ... 
    
    No strict? ... watch out for the Inquisitors! I'll presume that you declared $key earlier. ;)

    Seriously, i want to point out that anytime i see variables like $t1, $c1, ,$d1, etc., i try to remove these and use 'containers' instead. Here is my take on the problem:

    use strict; my (@stuff,$cust,$total); my %ytd = ( foo => { d1 => 1, d2 => 2, c1 => 3, c2 => 4 }, bar => { d1 => 5, d2 => 6, c1 => 7, c2 => 8 }, baz => { d1 => 9, d2 => 1, c1 => 2, c2 => 3 }, qux => { d1 => 4, d2 => 5, c1 => 2, c2 => 4 }, ); foreach $cust (sort keys %ytd) { my @tot = map { $ytd{$cust}->{"d$_"} - $ytd{$cust}->{"c$_"} } 1..2; $total = do { my $t; $t += $_ for @tot; $t }; @stuff = ( $ytd{$cust}->{d1}, $ytd{$cust}->{c1}, $tot[0], $ytd{$cust}->{d2}, $ytd{$cust}->{c2}, $tot[1], ); write; } format STDOUT = @<<<<<<<<<<<<<<<<<<<< $cust @#####.## @#####.## @#####.## @#####.## @#####.## @#####.## @stuff @#####.## $total .
    I think that shoving the number items into an array is more convenient and allows you to use the array in the format instead of the individual scalars.

    Without knowing the problem, i can't really comment on your datastructure %ytd, but it might benefit you in terms of maintenance to combine each of the 'dN' and 'cN' pairs into one that contains an array. For example:

    my %ytd = ( foo => { d => [1,2], c => [3,4] }, bar => { d => [5,6], c => [7,8] }, baz => { d => [9,1], c => [2,3] }, qux => { d => [4,5], c => [2,4] }, );
    Just food for thought. :)

    jeffa

    L-LL-L--L-LL-L--L-LL-L--
    -R--R-RR-R--R-RR-R--R-RR
    B--B--B--B--B--B--B--B--
    H---H---H---H---H---H---
    (the triplet paradiddle with high-hat)
    
      Ah yes, use strict is there, just not in the snippet I posted. Sort of like American Express, I don't code without it. : )

      My data structure is two flat files with customer names and data. The names should match in both files, but I've got to get the data from the two files in to a structure indexed by customer name. The files generated and ascii is my best option.

      I've got it working at present, but I agree the code is messy at best. I am quite intrigued by your array idea and will try that approach instead. Thanks!

      There is no emoticon for what I'm feeling now.

Re: Question on using format and write
by pg (Canon) on Dec 13, 2002 at 22:20 UTC
    Your problem is that, actually you assigned values to other variables with the same name, but in a different scope. Those variables you my'd in the foreach loop, are not the variables you declared in your format statement.

    This is the answer to your question, but I want to elaborate on this a little bit:
    1. Even within the same scope, you should not re-declare your variables. In the following code, $a is declared twice, first within the format statement, second time with my. Although $a is assigned to 1, don't expect the printing matches it, as that's a different $a. Remove the 'my' resolves the problem, as now it is a pure assignment, not a declaration any more.
      format SomeFormat = @###.## @>>>>>>> $a, $b . my $a = 1;
    2. Although scope migth cause a problem, if one is careless, but I disagree with the thought that the write and format statement have to be in the same scope. Actually, as long as you fully qualify your variables, as you should always do, things would be fine, even if format and write reside in different scopes. The following code I wrote demos this:
      use strict; format Something = Test: @##.## @###.## $a, $b . sayit(); sub sayit { $main::a = 1; $main::b = 2; $~ = 'Something'; write; }

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (None)
    As of 2024-04-25 01:53 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?

      No recent polls found