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

I have Tried to create a Hash data Structure but when i try to access the hash out of the FOR loop i am not getting th e values... also will need help on passing hashes to subroutines and method the compare values in two similar hashes
sub readDRC ( ) { my ( $file , $flag ) = @_ ; $drc::tmpFile1 = "${file}.tmp" if ($file) ; my $moduleName = "" ; my $netName ; my @gateInst ; my $gate ; my $netCap ; my $violation ; my @maxTrans ; my $worstTrans ; open ( TMPDRC, "<$drc::tmpFile1" ) ; my $line ; my $i; my $j = 0 ; @drc::file1 = <TMPDRC> ; for ( $i = 0 ; $i <= $#drc::file1 - 1 ; $i++ ){ if ( $drc::file1[$i] =~ m/^\s*\Module:/i ) { $moduleName = getModuleName ( $drc::file1[$i] ) ; } # End of IF Statement if ( $drc::file1[$i] =~ /Net:/ ) { $netName = getNetName ( $drc::file1[$i] ) ; } # End of IF Statement if ( $drc::file1[$i] =~ /Max Capacitance/ ) { @gateInst = getMaxCapacitance ( $drc::file1[$i] ) ; $gate = $gateInst[5].$gateInst[6] ; } # End of IF Statement if ( $drc::file1[$i] =~ /Net Capacitance/ ) { $netCap = getNetCapacitance ( $drc::file1[$i] ) ; } # End of IF Statement if ( $drc::file1[$i] =~ /VIOLATION/ ) { $violation = getViolation ( $drc::file1[$i] ) ; if ( $drc::flag ) { $drc::rpt1{$moduleName}{$netName}{$gate}{"Cap +acitance"} = $violation; } else { $drc::rpt2{$moduleName}{$netName}{$gate}{"Capaci +tance"} = $violation; } } # End of IF Statement if ( $drc::file1[$i] =~ /Max Transition/ ) { @maxTrans = getMaxTransition ( $drc::file1[$i] ) ; $gate = $maxTrans[5].$maxTrans[6] ; } # End of IF Statement if ( $drc::file1[$i] =~ /Pin Worst Transition/ ) { $worstTrans = getWorstTransition ( $drc::file1[$i] ) ; } # End of IF Statement if ( $drc::file1[$i] =~ /VIOLATION/ ) { $violation = getViolation ( $drc::file1[$i] ) ; if ( $drc::flag ) { $drc::rpt1{$moduleName}{$netName}{$gate}{"Tra +nsition"} = $violation } else { $drc::rpt2{$moduleName}{$netName}{$gate}{"Tran +sition"} = $violation } } # End of IF Statement # } # End of FOR Loop # if ($flag) {compareFiles(\@drc::rpt1 , \@drc::rpt2 , \$drc::tmpFile +1 ) } # Calling The Function to Compare Values # only if both Hashes are +assigned printValues(\@drc::rpt1) ; # my $caps = "Capacitance" ; # my $tran = "Transition"; # if ( $drc::rpt1{$moduleName}{$netName}{$gate}{$tran} != $drc::rp +t2{$moduleName}{$netName}{$gate}{$tran}) { # print " Module = $moduleName \n" ; # print " Net = $netName \n" ; # print " Gate = $gate \n" ; # print " Transition Violation Value = $drc::rpt1{$modu +leName}{$netName}{$gate}{$tran} \n" ; # print " Capacitance Violation Value = $drc::rpt1{$mod +uleName}{$netName}{$gate}{$caps} \n" ; # print " Transition Violation NEW Value = $drc::rpt2{$ +moduleName}{$netName}{$gate}{$tran} \n" ; # } # End of IF } # End of FOR Loop close TMPDRC ; $drc::flag = 1 ; # unlink ( $drc::tmpFile1 ) if ( -f $drc::tmpFile1 ) ; return 0 ; # mission successful :=) }

Edited by Chady -- added code tags.

Replies are listed 'Best First'.
Re: Hash Data Structure
by dave_the_m (Monsignor) on May 11, 2004 at 10:27 UTC
    If you were to reduce this to a 5-10 line program that demonstrates the problem, you'll probably get more responses. Dave.
Re: Hash Data Structure
by ambrus (Abbot) on May 11, 2004 at 14:48 UTC

    Some suggestions (I don't reaaly know the real problem).

    if ( $drc::file1[$i] =~ /VIOLATION/ ) { $violation = getViolation ( $drc::file1[$i] ) ; if ( $drc::flag ) { $drc::rpt1{$moduleName}{$netName}{$gate}{ +"Transitio else { $drc::rpt2{$moduleName}{$netName}{$ +gate}{"Transition"} = } +# End of IF Statement

    Try to check if the assignment is really executed (place a breakpoint with the debugger, or add a warn statement). Maybe the conditions never stand, so you get no data in the hash.

    Also here: for ( $i = 0 ; $i <= $#drc::file1 - 1 ; $i++ ) you're not iterating through the last line, is that on purpose? Remove the  - 1 if it was accidental.

Re: Hash Data Structure
by duff (Parson) on May 11, 2004 at 15:28 UTC

    My comments:

    • You're defining the subroutine to take no arguments (the empty parens after the sub name are the prototype for no args) yet you are apparently expecting args:
      sub readDRC ( ) { my ( $file , $flag ) = @_ ;
      This leads me to believe that you probably don't understand perl's "protoypes", so you probably shouldn't use them.
    • You're not checking the return value of your open()
    • Your C-style for loop is very non-idiomatic. When looping over an array like that, it typically looks like this: for (my $i = 0; $i < @array; $i++) { ... }
    • And also relating to the for loop, it looks like you really want the Perl-style for loop:

      for my $item (@drc::file) { if ($item =~ m/^\s*\Module:/i ) { $moduleName = getModuleName($item +); } ... }
    • And as to why you're not getting the values out that you put in, make sure that that all of your keys have the values you think they do. If you don't have warnings and strict on, turn them on. Perhaps you typoed a variable name or something. Sorry I can't be more help on that.
    • As for passing hashes to subroutines, you do it the same way you are passing your arrays (i.e. you pass a reference to your hashes)
Re: Hash Data Structure
by TomDLux (Vicar) on May 11, 2004 at 18:26 UTC

    I was going to comment on the for loops, but duff beat me too it. Isn't it a whole lot cleaner to deal with the array elements ... and to bypass that long namespace specifying name?

    Less significant, but it will trim 10 lines from your program. Instead of declaring your variables one by one, if you make a list of them by wrapping them in parentheses, you can declare them all at once:

    my ( $moduleName, $netName, @gateInst, $gate, $netCap, $violation, @maxTrans, $worstTrans, $line );

    You never use $j, and you don't need $i any more. As for $moduleName, the first thing you do in the loop is assign a value, so you don't need to initialize it to an empty string.

    The $drc::flag if/then/else section is a great situation for using references .... you do the exact same dereferencing, but a flag decides whether you access %drc::rpt1 or %drc::rpt1. How about:

    my $rpt = $drc::flag ? \%drc::rpt1 : \%drc::rpt2; $rpt->{$moduleName}{$netName}{$gate}{"Capacitance"} = $violation;

    Or maybe you could cause an error to assign the right object reference to a variable, instead of setting the flag?

    If there's a possibility that the bodies of the loops will expand, it's worth keeping them explicit. But if they are defined as short one-liners, consider collapsing them:

    if ( $drc::file1[$i] =~ m/^\s*\Module:/i ) { $moduleName = getModuleName ( $drc::file1[$i] ) ; } # could become $moduleName = getModuleName ( $item ) if ( $item =~ m/^\s*\Modul +e:/i );

    I use a bit of space before the if() to emphasis what happens, and to separate the action and the condition.

    This way, the subroutine becomes: For each element in the array, do A if appropriate, do B if appropriate, ,do C if appropriate, handle errors, .....

    --
    TTTATCGGTCGTTATATAGATGTTTGCA