CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Want IF statement to end on first false condition

 



bulrush
Novice

Jul 10, 2014, 6:33 AM

Post #1 of 6 (535 views)
Want IF statement to end on first false condition Can't Post

  • Perl 5.8.8 on Linux RHEL 5.5.56
  • Is the comma in the pattern match supposed to be escaped? Some docs say no.
  • Why the uninit variable in pattern match error?

    I thought a Perl IF statement would exit as soon as it found a check resulting in false, thus not executing the other checks, which is why my first check is to see if $t1 is defined. I have an if statement which has multiple conditions but am getting an "uninitialized variable in pattern match" error here:


    Code
    # Uninit variable in pattern match error  
    if ((defined $t1) && (len($t1)>0) && ($t1=~m/^[\d\, ]+$/))


    When checking $t1 in the debugger, it has a length of 0 and is defined, so why am I getting an error on the pattern match (the third check, ($t1=~m/^[\d\, ]+$/))? And how can I fix that? Because the code is showing the "uninit var in pattern match" then going right to the error message in "else". The program should go on to check the elsif for $t2 if the checks for $t1 do not pass.

    I'd prefer the IF statement fail when any check fails, so other checks are not executed.

    Basically, if $t1 contains something, process $t1. If $t1 contains nothing, check $t2. If $t2 contains something, process it, otherwise check $location. If $location contains nothing, then print error message.

    More code in context here:


    Code
    use Spreadsheet::ParseExcel; 

    $t1=''; # Init to blank
    $cellin=$sheetin->get_cell($row,7); # Include stores
    if ($cellin)
    {
    $t1=$cellin->value(); # Returns empty string if SS cell is blank.
    if (len($t1)>0)
    {
    $t1=dropquote($t1);
    $t1=trimarr($t1); # Also does uniquearr().
    }
    }

    # Uninit variable in pattern match error here
    if ((defined $t1) && (len($t1)>0) && ($t1=~m/^[\d\, ]+$/))
    {
    blah();
    }
    elsif ((defined $t2) && (len($t2)>0) && ($t2=m/^[\d\, ]+$/))
    {
    blah2();
    }
    elsif ((defined $location) && (len($location)>0) && ($location=~m/^[\d\, ]+$/))
    {
    blah3();
    }
    else {
    $s=$prefixsp."$procname ERROR: row $zpos, no data found.";
    writeerr($s); # writeerr() is user-defined.
    }


    Actual debugger output, just before IF statement is executed.


    Code
      readxls: Reading row 2... 
    main::readxls(create.pl:310): if ( (defined $t1) && (len($t1)>0) && ($t1=~m/^[\d, ]+$/))
    main::readxls(create.pl:311): {
    DB<2> p $t1

    DB<3> p len($t1)
    0
    DB<4> if (defined $t1){print "Defined\n";}
    Defined


    I've changed the code a bit to test the length of $t1, $t2 and $location first, then test for $t1. Another debug session showing how $t2 mysteriously changes from valid data to 1:


    Code
    main::readxls(create.pl:330):       if ((len($t1)>0) or (len($t2)>0) or (len($location)>0)) 
    main::readxls(create.pl:331): {
    DB<2> p $t2
    158,171,173,174,176,179,191,194,213,244,247,250,253,257,258,260,261,262,263,264,316
    DB<3> n
    main::readxls(create.pl:332): if ( (len($t1)>0) && ($t1=~m/^[\d, ]+/))
    main::readxls(create.pl:333): {
    DB<3> p $t2
    158,171,173,174,176,179,191,194,213,244,247,250,253,257,258,260,261,262,263,264,316
    DB<4> n
    Use of uninitialized value in pattern match (m//) at create.pl line 332.
    at create.pl line 332
    main::readxls() called at create.pl line 188
    main::readxls(create.pl:397): writeexcel(); # Write out @xlarr.
    DB<4> p $t2

    DB<5>

    -----
    * Redhat Linux RHEL 5.5.56
    * Perl 5.8.8

    (This post was edited by bulrush on Jul 10, 2014, 7:29 AM)


  • FishMonger
    Veteran / Moderator

    Jul 10, 2014, 6:59 AM

    Post #2 of 6 (503 views)
    Re: [bulrush] Want IF statement to end on first false condition [In reply to] Can't Post

    Are you sure the warning is coming from that conditional statement?

    What is your len(..) function doing? Is it a wrapper for perl's built-in length() function?


    Code
    #!/usr/bin/perl 

    use 5.010;
    use strict;
    use warnings;
    use Data::Dumper;

    foreach my $t1 ('', undef, 123){
    print Dumper $t1;

    if ((defined $t1) && (length($t1)>0) && ($t1=~m/^[\d\, ]+$/))
    {
    say "All 3 conditions are true\n"
    }
    else
    {
    say "Conditional test failed\n";
    }
    }


    c:\test>bulrush.pl

    Code
    $VAR1 = ''; 
    Conditional test failed

    $VAR1 = undef;
    Conditional test failed

    $VAR1 = 123;
    All 3 conditions are true



    (This post was edited by FishMonger on Jul 10, 2014, 6:59 AM)


    bulrush
    Novice

    Jul 10, 2014, 7:28 AM

    Post #3 of 6 (482 views)
    Re: [FishMonger] Want IF statement to end on first false condition [In reply to] Can't Post

    Yes, len() is a wrapper for Perl's length() function.

    I'm pretty sure the error is where the $t1 is getting tested. I've posted another debug log above to show how I get an error when testing $t1, yet $t2 gets changed from valid data to 1.
    -----
    * Redhat Linux RHEL 5.5.56
    * Perl 5.8.8


    BillKSmith
    Veteran

    Jul 10, 2014, 7:34 AM

    Post #4 of 6 (476 views)
    Re: [bulrush] Want IF statement to end on first false condition [In reply to] Can't Post

    Use the lower precedence 'and'. (Refer to perlop)

    Quote
    Binary "and" returns the logical conjunction of the two surrounding expressions. It's equivalent to && except for the very low precedence. This means that it short-circuits: the right expression is evaluated only if the left expression is true.



    Code
    use strict; 
    use warnings;
    my $t1 = q(333);
    foreach my $t1 ( q(333), q(33a), q(), undef ) {
    if ( defined $t1 and length($t1) > 0 and $t1 =~ m/^[\d\, ]+$/ ) {
    print "Valid\n";
    }
    else {
    print "Invalid\n";
    }
    }


    Output:

    Code
    Valid 
    Invalid
    Invalid
    Invalid

    Good Luck,
    Bill


    bulrush
    Novice

    Jul 10, 2014, 7:37 AM

    Post #5 of 6 (473 views)
    Re: [BillKSmith] Want IF statement to end on first false condition [In reply to] Can't Post

    Now I don't feel so bad you all missed it. I was missing a tilde:


    Code
    ($t2=m/^[\d\, ]+$/) # Missing tilde after equals sign


    Problem solved. No wonder $t2 was getting changed to 1.

    Thanks for your help.
    -----
    * Redhat Linux RHEL 5.5.56
    * Perl 5.8.8


    FishMonger
    Veteran / Moderator

    Jul 10, 2014, 8:15 AM

    Post #6 of 6 (463 views)
    Re: [bulrush] Want IF statement to end on first false condition [In reply to] Can't Post

    Your missing tildy was from this line:

    Code
    elsif ((defined $t2) && (len($t2)>0) && ($t2=m/^[\d\, ]+$/))


    But you stated that the warning was coming from:

    Code
    if ((defined $t1) && (len($t1)>0) && ($t1=~m/^[\d\, ]+$/))

    and is why I asked if you were sure the warning was coming from that line.

    Adding proper whitespace in and around your statements will make finding these mistakes much easier as would paying attention to the line number specified in the warnings/errors.

     
     


    Search for (options) Powered by Gossamer Forum v.1.2.0

    Web Applications & Managed Hosting Powered by Gossamer Threads
    Visit our Mailing List Archives