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

Hello Master,

I'm stuck with these code in which im having trouble printing data with referring hash values. Can anyone help me. It'll be helpful.

#!/usr/bin/perl use strict; use warnings; use diagnostics; use Data::Dumper; # Define Files and assign strings my $DIN_CAP = "0.0005"; my $DIN_PWR_ARC = "0.000000,0.000000,0.000000,0.000000,0.000000,0.0000 +00,0.000000,0.000000"; sub mainCSV { # Open the CSV input file open (my $infile_CSV1, '<', "$infile_CSV") or die "Unable to open +$infile_CSV: $!\n"; my %hash = (); my $hash_ref = {}; while (my $line = <$infile_CSV1>) { chomp; $line =~ s/\s*\z//; my @array_CSV = split /,/, $line; my $key_CSV = shift @array_CSV; if ($hash{$key_CSV}) { warn "Duplicate key '$key_CSV'"; }; $hash{$key_CSV} = \@array_CSV; } # Explicit scalar context my $size = scalar keys %hash; # Prints Number of Pins (Hash size...) print "Number of Pins: $size\n"; # Open the output file and save hash in $outfile_RX_CSV open (my $outfile2, '>', "$outfile_CSV") or die "Unable to open $o +utfile_CSV: $!\n"; print $outfile2 Dumper(\%hash); close $outfile2; print "Stored $size list of pins in $outfile_CSV file.\n"; ########ERROR concentrated code################ # Continue print with corresponding hash key and value for AsyncIn +NoTimingArc my $count = grep { $_ == {AsyncInNoTimingArc} } values %hash; for ($count ; $count >= 0; $count--) { open (my $outfile1, '>>', "$outfile") or die "Unable to open $ +outfile: $!\n"; print ("\n pin($key_CSV) {\n direction : input ;\n capacitance : $DIN_CAP ;\n }\n \n internal_power(pwr_arc){\n values("$DIN_PWR_ARC");\n related_input : "$key_CSV" ;"\n); } } ##############ERROR#################### mainCSV ();

Replies are listed 'Best First'.
Re: why i cant print reading hash table?
by Athanasius (Archbishop) on Nov 20, 2013 at 04:05 UTC

    Hello waytoperl,

    Here are some of the problems with the code shown:

    • The following variables are used without being declared:

      $infile_CSV, $outfile_CSV, $outfile, $key_CSV
    • The line

      my $count = grep { $_ == {AsyncInNoTimingArc} } values %hash;

      uses a numerical comparison against a bareword. Here is a guess at what was intended:

      my $count = grep { $_ eq 'AsyncInNoTimingArc' } values %hash;
    • The C-style for loop begins with the statement $count; which does nothing. Just remove it:

      for (; $count >= 0; $count--)
    • Within the loop, $outfile is opened for writing but never used. If it is to be used, it should be opened once only, immediately before the loop.

    • The print statement is — well, a mess! Here is my guess as to what was intended:

      print "\n", "pin($key_CSV) {\n", "direction : input ;\n", "capacitance : $DIN_CAP ;\n", "}\n", "\n", "internal_power(pwr_arc){\n", "values(\"$DIN_PWR_ARC\");\n", "related_input : \"$key_CSV\" ;\n";

      Note that you should not try to combine newline control characters (\n) with literal newlines within a string. If you want a different quoting style here, have a look at <<EOF under perlop#Quote-Like-Operators.

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Why with the C for loop again? There are, in my opinion, two better options: a while loop, or a Perl for loop. Consider:

      while ($count--) {

      or

      for (1 .. $count) {

      I'd go for the for loop variant as it makes it clear we are iterating $count times and $count isn't used in the loop body so it doesn't need to be decremented.

      True laziness is hard work

        Hello GrandFather,

        In my reply I was actually addressing this warning generated by the OP:

        Useless use of private variable in void context at...

        (I should have made this explicit.) I certainly agree that either a while or a foreach loop would be preferable here. Unfortunately, neither of your suggested alternatives results in the same number of iterations as the original:

        16:05 >perl -wE "my $c = 0; for (my $n = 3; $n >= 0; $n--) { ++$c; } s +ay $c;" 4 16:05 >perl -wE "my $c = 0; my $n = 3; while ($n--) { ++$c; } say $c;" 3 16:05 >perl -wE "my $c = 0; my $n = 3; for (1 .. $n) { ++$c; } say $c; +" 3 16:05 >

        And since the loop is likely incomplete (see my comments regarding $outfile), we cannot be sure that $count won’t be used for something later on in the loop — in which case, the foreach version of the loop would provide the values in their reverse order. So the safest alternative is probably:

        while ($count-- >= 0) {

        Update 1: Except that the value of $count within this loop is always one less than its “proper” value.

        Update 2: Upon reflection, I now realise that GrandFather’s alternative loops were not intended as equivalents to the original, but as corrections to it, since it’s most likely that the OP code meant to loop for exactly $count iterations. If so, I apologise to GrandFather for the misreading.

        Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      Thank you Athanasius for pointing out problems in code. Made recommended modifications.

      Declared variables

      $infile_CSV, $outfile_CSV, $outfile

      Using 'Asyn...Arc' removes Bareword error

      Using for (; $count >= 0; $count--)

      Placed $outfile outside Loop.

      The print is modified with EOF These introduce some syntax errors. <<EOF prints strings available till EOF. In my code there are syntax problems.

      Most of the errors are removed. There are errors related to $key_CSV. Please take a look. Earlier logic was to search 'AsyncInNoTimingArc' from %hash values. Keep a count of occurrence in $count. Using $count in LOOP print a bunch of line by adding every corresponding %hash table $key_CSV for every occurrence of 'AsyncInNoTimingArc'. Please provide your insight logically its possible, where we can search a hash value, keep a count and in every LOOP iteration of value[] key[] use print statement and use content of key[]

      EXAMPLE: Output of %hash have its respective $key_CSV and values. Search a %hash value, keep a $count and for every values print respective $key_CSV in print statement

      Contents of %hash{}

      $VAR1 = { 'REFCLK_BUF3' => [ 'AsyncOutNoTimingArc' ], 'C_WREN' => [ 'C_CLK_and_SCANCLK_L__IN' ], 'CAL_CLK' => [ 'AsyncInNoTimingArc' ], 'RX_IBIAS_2_25U[4:0]' => [ 'Power' ],

      open (my $outfile1, '>>', "$outfile") or die "Unable to open $outfile: + $!\n"; for (; $count >= 0; $count--) { print <<" EOF"; pin($key_CSV) { direction : input ; capacitance : $DIN_CAP ; } internal_power(pwr_arc){ values(\"$DIN_PWR_ARC\"); related_input : \"$key_CSV\" ; } EOF

        Hi waytoperl. I think I understand what you are trying to achieve. If not, there should be enough code here for you to modify as needed.

        Input CSV

        PinName1,Group1 PinName2,Group1 PinName3,AsyncInNoTimingArc PinName4,Group1 PinName5,AsyncInNoTimingArc PinName6,AsyncInNoTimingArc PinName5,AsyncInNoTimingArc

        Output RX CSV

        $VAR1 = { 'PinName1' => [ 'Group1' ], 'PinName3' => [ 'AsyncInNoTimingArc' ], 'PinName6' => [ 'AsyncInNoTimingArc' ], 'PinName5' => [ 'AsyncInNoTimingArc' ], 'PinName2' => [ 'Group1' ], 'PinName4' => [ 'Group1' ] };

        Output CSV

        pin(PinName3) { direction : input ; capacitance : 0.0005 ; } internal_power(pwr_arc){ values("0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000 +,0.000000"); related_input : "PinName3" ; pin(PinName5) { direction : input ; capacitance : 0.0005 ; } internal_power(pwr_arc){ values("0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000 +,0.000000"); related_input : "PinName5" ; pin(PinName6) { direction : input ; capacitance : 0.0005 ; } internal_power(pwr_arc){ values("0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000 +,0.000000"); related_input : "PinName6" ; ** Found 3 occurrences of 'AsyncInNoTimingArc' **

        Script

        #!/usr/bin/perl use strict; use warnings; use diagnostics; use Data::Dumper; die "Error. Usage \'perl csv_parse.pl inputfile.csv outputfile_RX.csv +outputfile.csv\'\n $!" unless $#ARGV == 2; my $infile_CSV = shift @ARGV; my $outfile_RX_CSV = shift @ARGV; my $outfile_CSV = shift @ARGV; sub mainCSV ($$$); # Assign Global Strings my $DIN_CAP = "0.0005"; my $DIN_PWR_ARC = "0.000000,0.000000,0.000000,0.000000,0.000000,0.0000 +00,0.000000,0.000000"; sub mainCSV ($$$) { my $infile_CSV = shift; my $outfile_RX_CSV = shift; my $outfile_CSV = shift; my %hash = (); my $hash_ref = {}; # Read the CSV input file open (my $infile_CSV1, '<', "$infile_CSV") or die "Unable to open +$infile_CSV: $!\n"; while (<$infile_CSV1>) { chomp; ## Skip blank line next if ($_ eq ""); $_ =~ s/\s*\z//; my @array_CSV = split(/,/,$_); my $key_CSV = shift @array_CSV; if (exists $hash{$key_CSV}) { warn "Duplicate key: $key_CSV\n"; } else { $hash{$key_CSV} = \@array_CSV; } } close($infile_CSV1); # Explicit scalar context my $size = scalar keys %hash; # Prints Number of Pins (Hash size...) print "Number of Pins: $size\n"; # Open output CSV in Write Mode. The output file and save hash in +$outfile_RX_CSV open (my $outfile1, '>', "$outfile_RX_CSV") or die "Unable to open + $outfile_CSV: $!\n"; print $outfile1 Dumper(\%hash); close($outfile1); # Open output CSV File in Append Mode open (my $outfile2, '>>', "$outfile_CSV") or die "Unable to open $ +outfile_CSV: $!\n"; print "Stored $size list of pins in $outfile_CSV file.\n"; + # Print key,value where the hash value is AsyncInNoTimingArc my $count_occurrences = 0; foreach my $key (sort keys %hash) { ## Does current hash key value equal AsyncInNoTimingArc if ( @{$hash{$key}}[0] eq "AsyncInNoTimingArc" ) { $count_occurrences++; print $outfile2 "\n", "pin($key) {\n", "direction : input ;\n", "capacitance : $DIN_CAP ;\n", "}\n", "\n", "internal_power(pwr_arc){\n", "values(\"$DIN_PWR_ARC\");\n", "related_input : \"$key\" ;\n"; } } print "\n** Found $count_occurrences occurrences of 'AsyncInNo +TimingArc' **\n"; print $outfile2 "\n\n** Found $count_occurrences occurrences o +f 'AsyncInNoTimingArc' **\n"; close($outfile2); } mainCSV ($infile_CSV,$outfile_RX_CSV,$outfile_CSV);
Re: why i cant print reading hash table?
by roboticus (Chancellor) on Nov 20, 2013 at 04:05 UTC

    waytoperl:

    Well, since you have use strict in there, and it's failing with errors, I can only assume you're having trouble understanding one or more of the error messages.

    Which of the error messages are you having trouble with?

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.