Search code examples
perlperl-data-structures

How to use refernce concept and access element of subroutine argument using Perl?


I am writing a code for calling a subroutine which has 4 argument(3 hashes and one file handler).i want to know how to access them in subroutine.My code is as below.

#print OUTFILE "Content of TPC file:.\n";
my $DATA_INFO = $ARGV[0];
my $OUT_DIR = $ARGV[1];
my $log= "$OUT_DIR/log1";
open(LOG1,">$log");
require "$DATA_INFO";
my $SCRIPT_DIR = $ENV{"SCRIPT_DIR"} ; 
require "$SCRIPT_DIR/cmp_fault.pl";
require "$SCRIPT_DIR/pattern_mismatch.pl";
require "$SCRIPT_DIR/scan_count.pl";

print "\nComparing data:\n\n" ;
pattern_mismatch("\%data","\%VAR1","\%status",*LOG1);
cmp_fault("\%data","\%VAR1","\%status",*LOG1);
scan_count("\%data","\%status",*LOG1);
print "\n Comparison done:\n";

foreach $pattern (keys %status) {
 print "pattern";
  foreach $attr (keys %{$status{$pattern}}) {
   print ",$attr";
 }
 print "\n";
 last; 
 }    

 #Print Data
 foreach $pattern (keys %status) {
  print "$pattern";
 foreach $attr (keys %{$status{$pattern}}) {
  print ",$status{$pattern}{$attr}";

} print "\n";

Sub routine cmp_fault is here:

sub cmp_fault {
use strict;
use warning;
$data_ref= $_[0];;
$VAR1_ref= $_[1];
$status_ref = $_[2];
$log1_ref=$_[3];

 # print LOG1"For TPC : First find the pattern and then its fault type\n";

 for $pat ( keys %$data_ref ) {
  print  "fgh:\n$pat,";
  for $key (keys %{$data_ref{$pat}}) {
    if($key=~/fault/){
      print LOG1 "$key:$data_ref{$pat}{$key},\n";
       }
    }
}
 # print LOG1 "\nFor XLS : First find the pattern and then its pattern type\n";
  for $sheet (keys %$VAR1_ref){
   if ("$sheet" eq "ATPG") {
     for $row (1 .. $#{$VAR1_ref->{$sheet}}) {
       $patname = $VAR1_ref->{'ATPG'}[$row]{'Pattern'} ;
         next if ("$patname" eq "") ;
          $faultXls  = $VAR1_ref->{'ATPG'}[$row]{'FaultType'} ;
    #         print LOG1 " $patname==>$faultXls \n";
      if (defined $data{$patname}{'fault'}) {
      $faultTpc = $data{$patname}{'fault'} ;
     #     print LOG1 "\n $patname :XLS: $faultXls :TPC: $faultTpc\n";
          if("$faultXls" eq "$faultTpc") { 
           print LOG1 "PASS: FaultType Matched $patname :XLS: $faultXls :TPC: $faultTpc\n\n\n";
         print  "PASS: FaultType Matched $patname :XLS: $faultXls :TPC: $faultTpc\n\n";
         $status_ref->{$patname}{'FaultType'} = PASS;

        } 
       else {
          print LOG1 "FAIL: FaultType Doesn't Match\n\n";
       $status_ref->{$patname}{'FaultType'} = Fail;   
            }
       }
    }        
   }
  }
}
 return 1;

Solution

  • When passing parameters into an array, you can only ever pass a single list of parameters.

    For scalars, this isn't a problem. If all you're acting on is a single array, this also isn't a problem.

    If you need to send scalars and an array or hash, then the easy way is to 'extract' the scalar parameters first, and then treat 'everything else' as the list.

    use strict;
    use warnings;
    
    sub scalars_and_array {
        my ( $first, $second, @rest ) = @_;
        print "$first, $second, ", join( ":", @rest ), "\n";
    }
    
    scalars_and_array( "1", "2", "3", 4, 5, 6 );
    

    But it should be noted that by doing so - you're passing values. You can do this with hashes too.

    To pass data structure references, it's as you note - pass by reference, then dereference. It's useful to be aware though, that -> becomes useful, because it's accessing a hash and dereferencing it.

    use strict;
    use warnings;
    use Data::Dumper;
    
    sub pass_hash {
        my ( $hashref ) = @_;
        print $hashref,"\n";
        print $hashref -> {"one"},"\n";
        print $hashref -> {"fish"} -> {"haddock"};
    }
    
    
    my %test_hash = ( "one" => 2,
                      "three" => 4, 
                      "fish" => { "haddock" => "plaice" }, );
    
    pass_hash ( \%test_hash ); 
    print "\n";
    print Dumper \%test_hash;
    

    The core of your problem here though, is that you haven't turned on strict and warnings which would tell you that:

    for $pat ( keys %data_ref ) {
    

    is wrong - there is no hash called data_ref there's only a scalar (which holds a hash reference) called $data_ref.

    You need %$data_ref here.

    And here:

    for $key ( keys %{ $data{$pat} } ) {
    

    You also have no $data - your code says $data_ref. (You might have %data in scope, but that's a really bad idea to mess around with within a sub).

    There's a bunch of other errors - which would also be revealed by strict and warnings. That's a very basic debugging step, and you will generally get a much better response from Stack Overflow if you do this before asking for assistance. So please - do that, tidy up your code and remove errors/warnings. If you are still having problems after that, then by all means make a post outlining where and what problem you're having.