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

Hello

use strict; my ($row, $col) = (0, -1); my %TABLE; my @COLUMNS = ('Period', 'Code', 'Name', 'Handle', 'Date', 'From', 'To +'); my @VARIABLES = qw/$colPeriod $colCode $colName $colHandle $colDate $c +olFrom $colTo/; my %Header = ( columns => \@COLUMNS, variables => \@VARIABLES, table => \%TABLE, heading => 'true', row => $row, column => $col, ); BuildHeader(\%Header); sub BuildHeader { my ($header_ref) = @_; my $TABLE = $header_ref->{table}; my $row = $header_ref->{row}; my $col = $header_ref->{column}; #columns and variables array must be equal if ( scalar @{$header_ref->{columns}} != scalar @{$header_ref->{va +riables}} ) { return; } foreach ( @{$header_ref->{columns}} ) { $TABLE{table}[$row][++$col]{value} = $_; $TABLE{table}[$row][$col]{heading} = $header_ref->{heading}; #Populate each variable in @variables with $col value ++$col; #return the variables } }

In the above I've declared VARIABLES array. when I run the script it is not giving any errors (may be because I declared under qw operator).

I need to get all the variables back populated with $col value. I mean i need to include the scoping for all the variables with 'my'. How can i achieve that?

Replies are listed 'Best First'.
Re: Populate variables with values
by roboticus (Chancellor) on Sep 10, 2009 at 12:28 UTC
    kalyanrajsista:

    Your question

    In the above I've declared VARIABLES array. when I run the script it is not giving any errors (may be because I declared under qw operator). I need to get all the variables back populated with $col value. I mean i need to include the scoping for all the variables with 'my'. How can i achieve that?

    Yes, you've removed the warnings. But you've hidden them, rather than solve the problem. By using qw/.../ you've just created a list of strings whose values just happen to look like variable names. The problem is that you were trying to use variables that weren't defined. You need to declare them first, something like this:

    my ($colPeriod, $colCode, $colName, $colHandle, $colDate, $colFrom, $c +olTo);

    Once you've defined them, you can then use1 them:

    my @VARIABLES = ($colPeriod, $colCode, $colName, $colHandle, $colDate, + $colFrom, $colTo);

    Some notes on your code

    The first thing I would do is to add these two lines after use strict;:

    use warnings; use Data::Dumper;

    Then use Data::Dumper to print the contents of %Header:

    print Dumper(\%Header); BuildHeader(\%Header); print Dumper(\%Header);

    When you do so, you'll see what's happening in BuildHeader. Then if you review the output, you'll see several oddities that should help you locate your bugs. For example, here's a section of the Data::Dumper output I printed after calling BuildHeader:

    $VAR1 = { 'row' => 0, 'heading' => 'true', 'table' => { 'table' => [ [ { 'value' => 'Period', 'heading' => 'true' }, undef, { 'value' => 'Code', 'heading' => 'true' }, undef,

    There are several clues here. First, in your tablehash, you have a single item: a reference to a hash named table. It seems likely that you want just one level of hash for table rather than two. Similarly, your inner table hash contains a single array that contains another array. Perhaps you wanted just one level of array here?.

    Write down what you think the Data::Dumper output should look like, and then find the differences and repair the problems as you find them.

    Something else that looks odd is the fact that inside your innermost array, you have an alternating series of hash and undef. Looking at your code reveals that you have an extra increment to $col in your loop. You probably want to remove one of them. There appear to be a few other things to repair, but I'm already guessing at what you're trying to do. Try fixing some of the obvious problems, and when you get stuck again, post a reply to your own node with the updated code and the next problem(s) you're encountering.

    Even better would be to write a function that dumps out your table to the screen in a reasonably-nice format using the syntax you *want* to use. Then run your script under the debugger, set a breakpoint in your table dump routine, and then single-step through the code. That way, you can see what you're trying to access and compare it to what you actually have. Having some code that actually *uses* your data structure will help you understand how to *build* it. (If you've never used the debugger, it may sound a little scary at first. But learn to use it anyway--it's not scary at all, and it will help you improve your coding skill quickly.)

    Notes:

    1 You probably weren't trying to do this, however, as this will simply make your variables member contain an array of values. Since none of the variables has a value set yet, you'd simply have a list of undefs. You might be wanting an array of references to the variables, however, in which case you just prefix each of the variable names with a '\' symbol in the list you're assigning to @VARIABLES.

    ...roboticus
      You might be wanting an array of references to the variables, however, in which case you just prefix each of the variable names with a '\' symbol in the list you're assigning to @VARIABLES.

      To save some typing you can take a reference to the list of variables instead of to each variable in the list.

      $ perl -Mstrict -wle ' > my $val1 = 99; > my $val2 = 77; > print $val1; > print $val2; > my @vars = \ ( $val1, $val2 ); > ${ $vars[ 0 ] } = 55; > ${ $vars[ 1 ] } = 33; > print $val1; > print $val2;' 99 77 55 33 $

      I hope this is of interest.

      Cheers,

      JohnGG

Re: Populate variables with values
by leighsharpe (Monk) on Sep 10, 2009 at 12:39 UTC
    When you declare the @VARIABLES array, you are filling it with the literal strings '$colPeriod', '$colCode', '$colName', '$colHandle', '$colDate', '$colFrom', and '$colTo'
    Perhaps that line should be
    my @VARIABLES = ($col."Period", $col."Code", $col."Name", $col."Handle +", $col."Date", $col."From", $col."To");
    Your BuildHeader() function will populate the %Header hash, but I suspect it isn't doing quite what you want. If you add
    use Data::Dumper
    to the start of your program, and then after you have called BuildHeader(), add
    print Dumper(%Header);
    you should see what %Header now looks like.
      use strict; use warnings; use Data::Dumper; my ($row, $col) = (0, -1); my %TABLE; my @COLUMNS = ('Period', 'Code', 'Operator Name', 'Service', 'Invoice +Number', 'FirstSeq', 'LastSeq', 'Message Count', 'PreTax', 'Tax Amount', 'P +ostTax', 'Handle / Date', 'Time UTC', 'From', 'To'); my ($colPeriod, $colPartnerTco, $colOperatorName, $colService, $colInv +oiceNo, $colFirstSeq, $colLastSeq, $colMsgCnt, $colPreTax, $colTax, $col +PostTax, $colHandleDate, $colTime, $colFrom, $colTo); my @VARIABLES = \($colPeriod ,$colPartnerTco ,$colOperatorName ,$colSe +rvice ,$colInvoiceNo ,$colFirstSeq ,$colLastSeq ,$colMsgCnt ,$colPreTax ,$colTax ,$co +lPostTax ,$colHandleDate ,$colTime ,$colFrom ,$colTo); my %Header = ( columns => \@COLUMNS, variables => \@VARIABLES, table => \%TABLE, heading => 'true', row => $row, col => $col, ); BuildHeader(\%Header); print $colMsgCnt; sub BuildHeader { my ($header_ref) = @_; my $i = 0; my $TABLE = $header_ref->{table}; my @variables = @{$header_ref->{variables}}; my $row = $header_ref->{row}; my $col = $header_ref->{col}; foreach ( @{$header_ref->{columns}} ) { $TABLE{table}[$row][++$col]{value} = $_; $TABLE{table}[$row][$col]{heading} = $header_ref->{heading}; ${ $variables[$i] } = $col; $i++; } }
      Above code works as I expected. Thanks Johngg. Your solution gave me the right way. roboticus comments really helped me to find out my flaws. Sincere thanks to leighsharpe.