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

This code executes, however, the first set of results are not as expected.
Thanks
#!/usr/bin/perl # use strict; use warnings; use diagnostics; use FileHandle; my $control_file="/opt/apps/process.txt"; my %process_control; my $control_fh = FileHandle->new; sub openControls { # Opening the status files: print "In openControls\n open $control_file\n"; open( $control_fh, '<', $control_file ) or die "\nUnable to open + [$control_file] file for reading: $!\n\n"; } sub closeControls { # Close the status file: print "In closeControls\n close $control_file\n"; close $control_fh; } sub buildControlMap { if ($control_fh->opened()) { print "control_fh is opened and ready\n"; while (<$control_fh>) { chomp; my( $key, $row ) = split( /\|/, $_ ); $process_control{ $key } = $row; } } else { print "control_fh is closed\n"; } } sub printControlMap { print "Print Process Control hash\n"; while ( my ($control, $process) = each(%process_control)) { print "[".$control."], [".$process."]\n"; } } sub checkControlMap { my $check = $_[0]; print "Look for control [$check] - "; while ( my ($control, $process) = each(%process_control) ) { if ( $check eq $control ) { return $process; } } # If it's not found, return "1" print "WARNING [$check] was not found. - "; return 1; } # Build and step through the control hash openControls; buildControlMap; printControlMap; my $size = keys %process_control; my $control; my $process = 0; my @list1=('a1z','a2x','b3y','b4w','c5u','c6t','d7s','d8r','e0q','e1p' +,'f2o','f3m','i4n','i5l','k6k'); my @list2=('c5u','b3y','e1p','c6t','f3m','a1z','k6k','i4n','e0q','f2o' +,'b4w','d7s','i5l','a2x','d8r','xyz'); print "TEST list 1 #####################\n"; foreach (@list1) { $process = checkControlMap( $_ ); print "checkControlMap( $_ ) returned process [$process]\n" +; } print "TEST list 2 #####################\n"; foreach (@list2) { $process = checkControlMap( $_ ); print "checkControlMap( $_ ) returned process [$process]\n" +; } $process = checkControlMap( " " ); print "checkControlMap( ) returned process [$process]\n"; closeControls; 1; ---------------------------------------------------------------------- +--------- Input control file > cat /opt/apps/process.txt a1z|1 a2x|0 b3y|1 b4w|0 c5u|1 c6t|0 d7s|1 d8r|0 e0q|1 e1p|0 f2o|1 f3m|0 i4n|1 i5l|0 k6k|1 ---------------------------------------------------------------------- +--------- Test 1 > testProcessControls.pl In openControls open /opt/apps/process.txt control_fh is opened and ready Print Process Control hash [c5u], [1] [b3y], [1] [e1p], [0] [c6t], [0] [f3m], [0] [a1z], [1] [k6k], [1] [i4n], [1] [e0q], [1] [f2o], [1] [b4w], [0] [d7s], [1] [i5l], [0] [a2x], [0] [d8r], [0] TEST list 1 ##################### Look for control [a1z] - checkControlMap( a1z ) returned proce +ss [1] Look for control [a2x] - checkControlMap( a2x ) returned proce +ss [0] Look for control [b3y] - WARNING [b3y] was not found. +- checkControlMap( b3y ) returned process [1] Look for control [b4w] - checkControlMap( b4w ) returned proce +ss [0] Look for control [c5u] - WARNING [c5u] was not found. +- checkControlMap( c5u ) returned process [1] Look for control [c6t] - checkControlMap( c6t ) returned proce +ss [0] Look for control [d7s] - checkControlMap( d7s ) returned proce +ss [1] Look for control [d8r] - checkControlMap( d8r ) returned proce +ss [0] Look for control [e0q] - WARNING [e0q] was not found. +- checkControlMap( e0q ) returned process [1] Look for control [e1p] - checkControlMap( e1p ) returned proce +ss [0] Look for control [f2o] - checkControlMap( f2o ) returned proce +ss [1] Look for control [f3m] - WARNING [f3m] was not found. +- checkControlMap( f3m ) returned process [1] Look for control [i4n] - checkControlMap( i4n ) returned proce +ss [1] Look for control [i5l] - checkControlMap( i5l ) returned proce +ss [0] Look for control [k6k] - WARNING [k6k] was not found. +- checkControlMap( k6k ) returned process [1] TEST list 2 ##################### Look for control [c5u] - checkControlMap( c5u ) returned proce +ss [1] Look for control [b3y] - checkControlMap( b3y ) returned proce +ss [1] Look for control [e1p] - checkControlMap( e1p ) returned proce +ss [0] Look for control [c6t] - checkControlMap( c6t ) returned proce +ss [0] Look for control [f3m] - checkControlMap( f3m ) returned proce +ss [0] Look for control [a1z] - checkControlMap( a1z ) returned proce +ss [1] Look for control [k6k] - checkControlMap( k6k ) returned proce +ss [1] Look for control [i4n] - checkControlMap( i4n ) returned proce +ss [1] Look for control [e0q] - checkControlMap( e0q ) returned proce +ss [1] Look for control [f2o] - checkControlMap( f2o ) returned proce +ss [1] Look for control [b4w] - checkControlMap( b4w ) returned proce +ss [0] Look for control [d7s] - checkControlMap( d7s ) returned proce +ss [1] Look for control [i5l] - checkControlMap( i5l ) returned proce +ss [0] Look for control [a2x] - checkControlMap( a2x ) returned proce +ss [0] Look for control [d8r] - checkControlMap( d8r ) returned proce +ss [0] Look for control [xyz] - WARNING [xyz] was not found. +- checkControlMap( xyz ) returned process [1] Look for control [ ] - WARNING [ ] was not found. - ch +eckControlMap( ) returned process [1] In closeControls close /opt/apps/process.txt ---------------------------------------------------------------------- +--------- Change scalar declaration in check routine: sub checkControlMap { my $check = $_[0]; print "Look for control [$check] - "; while ( my ($control, $process) = each(%process_control) ) { if ( $check eq $control ) { return $process; } } . . . > testProcessControls.pl In openControls open /opt/apps/process.txt control_fh is opened and ready Print Process Control hash [c5u], [1] [b3y], [1] [e1p], [0] [c6t], [0] [f3m], [0] [a1z], [1] [k6k], [1] [i4n], [1] [e0q], [1] [f2o], [1] [b4w], [0] [d7s], [1] [i5l], [0] [a2x], [0] [d8r], [0] TEST list 1 ##################### Look for control [a1z] - checkControlMap( a1z ) returned proce +ss [1] Look for control [a2x] - checkControlMap( a2x ) returned proce +ss [0] Look for control [b3y] - WARNING [b3y] was not found. +- checkControlMap( b3y ) returned process [1] Look for control [b4w] - checkControlMap( b4w ) returned proce +ss [0] Look for control [c5u] - WARNING [c5u] was not found. +- checkControlMap( c5u ) returned process [1] Look for control [c6t] - checkControlMap( c6t ) returned proce +ss [0] Look for control [d7s] - checkControlMap( d7s ) returned proce +ss [1] Look for control [d8r] - checkControlMap( d8r ) returned proce +ss [0] Look for control [e0q] - WARNING [e0q] was not found. +- checkControlMap( e0q ) returned process [1] Look for control [e1p] - checkControlMap( e1p ) returned proce +ss [0] Look for control [f2o] - checkControlMap( f2o ) returned proce +ss [1] Look for control [f3m] - WARNING [f3m] was not found. +- checkControlMap( f3m ) returned process [1] Look for control [i4n] - checkControlMap( i4n ) returned proce +ss [1] Look for control [i5l] - checkControlMap( i5l ) returned proce +ss [0] Look for control [k6k] - WARNING [k6k] was not found. +- checkControlMap( k6k ) returned process [1] TEST list 2 ##################### Look for control [c5u] - checkControlMap( c5u ) returned proce +ss [1] Look for control [b3y] - checkControlMap( b3y ) returned proce +ss [1] Look for control [e1p] - checkControlMap( e1p ) returned proce +ss [0] Look for control [c6t] - checkControlMap( c6t ) returned proce +ss [0] Look for control [f3m] - checkControlMap( f3m ) returned proce +ss [0] Look for control [a1z] - checkControlMap( a1z ) returned proce +ss [1] Look for control [k6k] - checkControlMap( k6k ) returned proce +ss [1] Look for control [i4n] - checkControlMap( i4n ) returned proce +ss [1] Look for control [e0q] - checkControlMap( e0q ) returned proce +ss [1] Look for control [f2o] - checkControlMap( f2o ) returned proce +ss [1] Look for control [b4w] - checkControlMap( b4w ) returned proce +ss [0] Look for control [d7s] - checkControlMap( d7s ) returned proce +ss [1] Look for control [i5l] - checkControlMap( i5l ) returned proce +ss [0] Look for control [a2x] - checkControlMap( a2x ) returned proce +ss [0] Look for control [d8r] - checkControlMap( d8r ) returned proce +ss [0] Look for control [xyz] - WARNING [xyz] was not found. +- checkControlMap( xyz ) returned process [1] Look for control [ ] - WARNING [ ] was not found. - ch +eckControlMap( ) returned process [1] In closeControls close /opt/apps/process.txt ---------------------------------------------------------------------- +------- > perl -V Summary of my perl5 (revision 5 version 8 subversion 8) configuration: Platform: osname=hpux, osvers=11.22, archname=IA64.ARCHREV_0-thread-multi uname='hp-ux bigsur03 b.11.22 u ia64 1800516905 unlimited-user lic +ense ' config_args='-ders -Dcc=cc -Dusethreads -Duseithreads -Ud_sigsetjm +p -Uinstallusrbinperl -Ulocincpth= -Uloclibpth= -Dsh=/usr/bin/sh -Dd_ +attribut=undef -Dd_attribute_warn_unused_result=undef -Dd_u32align=de +fine -Aprepend:libswanted=cl -Dvendorprefix=/opt/perl_32 -Doptimize= +-fast +DSitanium2 +Ofltacc=strict -Accflags=+Z -Accflags=-DUSE_SITECU +STOMIZE -Duselargefiles -Accflags=-DNO_HASH_SEED -Dprefix=/opt/perl_3 +2 -Dinc_version_list=5.8.7/$archname 5.8.7 5.8.6/$archname 5.8.6 5.8. +4/$archname 5.8.4 5.8.3/$archname 5.8.3 5.8.2/$archname 5.8.2 5.8.1/$ +archname 5.8.1 5.8.0/$archname 5.8.0 -Dsed=/usr/bin/sed -Duseshrplib +-Dconfig_heavy=Config_dynamic.pl -Dcf_by=ActiveState -Dcf_email=suppo +rt@ActiveState.com' hint=recommended, useposix=true, d_sigaction=define usethreads=define use5005threads=undef useithreads=define usemulti +plicity=define useperlio=define d_sfio=undef uselargefiles=define usesocks=undef use64bitint=undef use64bitall=undef uselongdouble=undef usemymalloc=n, bincompat5005=undef Compiler: cc='cc', ccflags =' -D_POSIX_C_SOURCE=199506L -D_REENTRANT -Ae -D_ +HPUX_SOURCE -Wl,+vnocompatwarnings +Z -DUSE_SITECUSTOMIZE -DNO_HASH_S +EED -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 ', optimize='-fast +DSitanium2 +Ofltacc=strict', cppflags='-D__STDC_EXT__ -D_HPUX_SOURCE -D_POSIX_C_SOURCE=199506L +-D_REENTRANT -D_HPUX_SOURCE -Wl,+vnocompatwarnings -DUSE_SITECUSTOMIZ +E -DNO_HASH_SEED' ccversion='B3910B A.05.55', gccversion='', gccosandvers='' intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=4321 d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=1 +6 ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', + lseeksize=8 alignbytes=8, prototype=define Linker and Libraries: ld='/usr/bin/ld', ldflags =' -L/usr/lib/hpux32' libpth=/usr/lib/hpux32 /lib /usr/lib /usr/ccs/lib /usr/local/lib libs=-lcl -lnsl -lnm -lndbm -ldl -ldld -lm -lsec -lpthread -lc perllibs=-lcl -lnsl -lnm -ldl -ldld -lm -lsec -lpthread -lc libc=/usr/lib/hpux32/libc.so, so=so, useshrplib=true, libperl=libp +erl.so gnulibc_version='' Dynamic Linking: dlsrc=dl_hpux.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E -Wl +,-B,deferred ' cccdlflags='+Z', lddlflags='-b +vnocompatwarnings -L/usr/lib/hpux3 +2' Characteristics of this binary (from libperl): Compile-time options: MULTIPLICITY PERL_IMPLICIT_CONTEXT PERL_MALLOC_WRAP USE_ITHREADS USE_LARGE_FILES USE_PERLIO USE_REENTRANT_API USE_SITECUSTOMIZE Locally applied patches: ActivePerl Build 817.1 [268662] Iin_load_module moved for compatibility with build 806 POSIX: Support the long hostname version of uname() Avoid signal flag SA_RESTART for older versions of HP-UX PerlEx support in CGI::Carp Less verbose ExtUtils::Install and Pod::Find Patch for CAN-2005-0448 from Debian with modifications Partly reverted 24733 to preserve binary compatibility 28671 Define PERL_NO_DEV_RANDOM on Windows 28376 Add error checks after execing PL_cshname or PL_sh_path 28305 Pod::Html should not convert "foo" into ``foo'' 27736 Make perl_fini() run with Sun WorkShop compiler 27619 Bug in Term::ReadKey being triggered by a bug in Term::R +eadLine 27549 Move DynaLoader.o into libperl.so 27528 win32_pclose() error exit doesn't unlock mutex 27527 win32_async_check() can loop indefinitely 27515 ignore directories when searching @INC 27359 Fix -d:Foo=bar syntax 27210 Fix quote typo in c2ph 27203 Allow compiling swigged C++ code 27200 Make stat() on Windows handle trailing slashes correctly 27194 Get perl_fini() running on HP-UX again 27133 Initialise lastparen in the regexp structure 27034 Avoid "Prototype mismatch" warnings with autouse 26970 Make Passive mode the default for Net::FTP 26921 Avoid getprotobyname/number calls in IO::Socket::INET 26897,26903 Make common IPPROTO_* constants always available 26670 Make '-s' on the shebang line parse -foo=bar switches 26379 Fix alarm() for Windows 2003 26087 Storable 0.1 compatibility 25861 IO::File performace issue 25084 long groups entry could cause memory exhaustion 24699 ICMP_UNREACHABLE handling in Net::Ping Built under hpux Compiled at Sep 19 2006 13:53:03 @INC: /opt/perl_32/lib/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl_32/lib/5.8.8 /opt/perl_32/lib/site_perl/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl_32/lib/site_perl/5.8.8 /opt/perl_32/lib/site_perl /opt/perl_32/lib/vendor_perl/5.8.8/IA64.ARCHREV_0-thread-multi /opt/perl_32/lib/vendor_perl/5.8.8 /opt/perl_32/lib/vendor_perl .

Replies are listed 'Best First'.
Re: Hash search yields unexpected results
by kennethk (Abbot) on Feb 13, 2012 at 19:48 UTC
    Your issue is not entirely clear to me -- can you clearly state what your expected output is? It seems like it's operating reasonably to me.

    As a side note, you iterate over your hash values in checkControlMap. To quote our illustrious figurehead,

    Doing linear scans over an associative array is like trying to club someone to death with a loaded Uzi.
    -- TimToady
    That could be written as

    sub checkControlMap { my $check = $_[0]; print "Look for control [$check] - "; my $process = $process_control{$check}; if (not defined $process) { print "WARNING [$check] was not found. - "; $process = 1; } return $process; }
    with no change to functional behavior.

    Update: Actually, it does cause a change in functional behavior, as mortiz points out below. So use this.

      The iteration over a hash with each is not only inefficient, but also wrong. The reason is that the iterations aren't completed, so the next time the while-loop is entered, the the iteration continues where it left off before.

      That's because the state of the each-iterator is not tied to a lexical scope, but rather to the hash itself.

Re: Hash search yields unexpected results
by jwkrahn (Abbot) on Feb 13, 2012 at 21:32 UTC

    If you are going to use subroutines you should localize the data available to those subroutines, something like:

    #!/usr/bin/perl # use strict; use warnings; use diagnostics; sub openControls { my ( $name ) = @_; # Opening the status files: print "In openControls\n open $name\n"; open my $FH, '<', $name or die "\nUnable to open [$name] file for +reading: $!\n\n"; return $FH; } sub closeControls { my ( $FH, $name ) = @_; # Close the status file: print "In closeControls\n close $name\n"; close $FH; } sub buildControlMap { my ( $FH ) = @_; unless ( fileno $FH ) { print "control_fh is closed\n"; return; } print "control_fh is opened and ready\n"; my %data; while ( <$FH> ) { chomp; my ( $key, $row ) = split /\|/; $data{ $key } = $row; } return %data; } sub printControlMap { my ( $data ) = @_; print "Print Process Control hash\n"; while ( my ( $control, $process ) = each %$data ) { print "[$control], [$process]\n"; } } sub checkControlMap { my ( $key, $data ) = @_; print "Look for control [$key] - "; return exists $data->{ $key } ? $data->{ $key } : print "WARNING [ +$key] was not found. - "; # If it's not found, return "1" } my $control_file = 'process.txt'; # Build and step through the control hash my $control_fh = openControls( $control_file ); my %process_control = buildControlMap( $control_fh ); printControlMap( \%process_control ); my @list1 = qw/ a1z a2x b3y b4w c5u c6t d7s d8r e0q e1p f2o f3m i4n +i5l k6k /; my @list2 = qw/ c5u b3y e1p c6t f3m a1z k6k i4n e0q f2o b4w d7s i5l +a2x d8r xyz /; for my $test ( [ 1, @list1 ], [ 2, @list2 ], [ 3, ' ' ] ) { my $number = shift @$test; print "TEST list $number #####################\n"; for my $key ( @$test ) { my $process = checkControlMap( $key, \%process_control ); print "checkControlMap( $key ) returned process [$process]\n"; } } closeControls( $control_fh, $control_file );

    If you just want all of your data global you could do something like this:

    #!/usr/bin/perl # use strict; use warnings; use diagnostics; my $control_file = 'process.txt'; # Opening the status files: print "In openControls\n open $control_file\n"; open my $control_fh, '<', $control_file or die "\nUnable to open [$con +trol_file] file for reading: $!\n\n"; print "control_fh is opened and ready\n"; my %process_control; while ( <$control_fh> ) { chomp; my ( $key, $row ) = split /\|/; $process_control{ $key } = $row; } print "Print Process Control hash\n"; while ( my ( $control, $process ) = each %process_control ) { print "[$control], [$process]\n"; } my @list1 = qw/ a1z a2x b3y b4w c5u c6t d7s d8r e0q e1p f2o f3m i4n +i5l k6k /; my @list2 = qw/ c5u b3y e1p c6t f3m a1z k6k i4n e0q f2o b4w d7s i5l +a2x d8r xyz /; for my $test ( [ 1, @list1 ], [ 2, @list2 ], [ 3, ' ' ] ) { my $number = shift @$test; print "TEST list $number #####################\n"; for my $key ( @$test ) { print "Look for control [$key] - "; my $process = exists $process_control{ $key } ? $process_contr +ol{ $key } : print "WARNING [$key] was not found. - "; print "\$process_control{ $key } returned process [$process]\n +"; } } # Close the status file: print "In closeControls\n close $control_file\n"; close $control_fh;