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

Kinda embarrassed to post this, I'm very new to coding, it's bound to be trivial and you guys seem a little beyond that! But here goes:

I'm trying to validate input from a form field by testing if the value's not null (ie has that form field has been filled in). However, the array is refusing to see anything at all, ie treating a filled-in field as though it hasn't been filled in. But a variable seeing the same field *can* see what's there.

form code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html><head><title></title></head> <body> <FORM ACTION="tst.cgi" METHOD="post" ENCTYPE="multipart/form-data"> <INPUT TYPE="file" NAME="photo00"> <INPUT TYPE="submit" NAME="Submit" VALUE="Submit Form"> </FORM></body></html>

perl code:

#!usr/bin/perl -t use strict; use warnings; use CGI; use CGI::Carp qw/fatalsToBrowser/; use File::Basename; our $query = CGI->new; our @array = (); our $photo = $query->param("photo00"); # check if the field's not null, if not, array it if ($photo != "") {push(@array, $photo);} print "Content-type: text/html\n\n"; print "@array \n"; # this does nothing - how come? print "$photo \n"; # this prints to screen fine

Many thanks, and a very Happy New Year to you all from Spain

Replies are listed 'Best First'.
Re: variable sees it, array doesn't - stumped!
by kennethk (Abbot) on Dec 31, 2008 at 16:40 UTC
    You are using a numeric comparison (!=) to compare two stings that evaluate to 0 numerically. You should be using string comparison (ne). See perlop
      Thanks for the tip, and also for the link, most useful.
Re: variable sees it, array doesn't - stumped!
by kyle (Abbot) on Dec 31, 2008 at 16:42 UTC

    The bug is here:

    # check if the field's not null, if not, array it if ($photo != "") {push(@array, $photo);}

    You're using "!=" to compare strings, but it only compares numbers. See perlop for the gory details. You should be using "ne" instead, though you might also want to check if it's defined.

    What happens on that line is that a string in $photo is treated as a number, which will be zero unless it starts with some other digits. That number is then compared to the number that "" is translated to (zero). So you have "if ( 0 != 0 )". As such, @array is still empty by the time you get down to the print.

      Right, got it, how simple was that. I'm working through Beginner's Perl, I really should have seen that.

      Many thanks for your patience!

Re: variable sees it, array doesn't - stumped!
by oko1 (Deacon) on Dec 31, 2008 at 20:48 UTC

    When working with CGI forms, I tend to farm the job out. Required fields, validation, etc. can get really painful if you have to deal with them manually - and pointless suffering is against my religion. :)

    #!/usr/bin/perl -wT use strict; $|++; use CGI::FormBuilder; # Disable the next line for production use CGI::Carp qw/warningsToBrowser fatalsToBrowser/; my @fields = qw/name email zipcode/; my @req = @fields[0, 1]; ### These are the req +uired fields my %val = ( name => 'NAME', email => 'EMAIL' ); ### Validate via pre- +defined methods my $form = CGI::FormBuilder->new(method => 'post', fields => \@fields, required => \@req, validate => \%val, ); if ($form->submitted) { my $field = $form->fields; # update_db($field->fields}; # This is where you'd update the dat +abase, etc. print $form->confirm(header => 1); } else { print $form->render(header => 1); }

    Be sure to take a look at the generated source. There's a lot going on behind the scenes.


    --
    "Language shapes the way we think, and determines what we can think about."
    -- B. L. Whorf
Re: variable sees it, array doesn't - stumped!
by AnomalousMonk (Archbishop) on Dec 31, 2008 at 18:15 UTC
    Since you seem to be using warnings and strictures, I'm surprised that you got no warning messages when you ran your code, e.g.:
    >perl -wMstrict -le "my $s = ''; if ($s != '') { print 'not equal' } " Argument "" isn't numeric in numeric ne (!=) at -e line 1. Argument "" isn't numeric in numeric ne (!=) at -e line 1. >perl -wMstrict -le "my $s = 'foo'; if ($s != '') { print 'not equal' } " Argument "" isn't numeric in numeric ne (!=) at -e line 1. Argument "foo" isn't numeric in numeric ne (!=) at -e line 1. >perl -wMstrict -le "my $s = 0; if ($s != '') { print 'not equal' } " Argument "" isn't numeric in numeric ne (!=) at -e line 1. >perl -wMstrict -le "my $s = [ 'array', 'ref' ]; if ($s != '') { print 'not equal' } " Argument "" isn't numeric in numeric ne (!=) at -e line 1. not equal
      Warnings would go to the log file. Odds are good that the OP doesn't know where that is and/or didn't think to look there.
        The OP sees it now! Thanks for the tip.
Re: variable sees it, array doesn't - stumped!
by Jenda (Abbot) on Jan 01, 2009 at 06:39 UTC

    The cause of the problems is found, now let's look at some other things. Most often when you say "our $variable" you mean "my $variable".

    "my $variable" means "please create a brand new variable with this name that's accessible only within this block". "our $variable" on the other hand means just "I'm going to use the global variable (OK, package variable, there are multiple namespaces for globals) with this name within this block. I know it's global, but I do not want to waste time typing out its whole name each time". "our $variable", doesn't create a new variable, it just silences use strict;.

    Compare,

    use strict; { my $x; $x = 1; print "\$x=$x\n"; } { my $x; $x +=1; print "\$x=$x\n"; } # and { our $y; $y = 1; print "\$y=$y\n"; } { our $y; $y +=1; print "\$y=$y\n"; } # and see the globals in the main namespace print "\$main::x=$main::x, \$main::y=$main::y\n";
      Yes, having declared everything globally just to get the sod to work (work around my ignorance, that is), the penny has just dropped about why/where/how one should use local variables.

      I have managed to get the script working, though am aware there are several things to be done to improve it, primarily in optimising email address validation, and in getting the form field values - oko1's and Jenda's words of wisdom, and indeed everyone else's, have given me much to meditate upon. Phrases like 'reinventing the loop' spring to mind, but it's useful practice for me.

      I'm loth to post acres of pre-competent code here, but if anyone needs a shudder, do feel free to have a look at the form code and/or the Perl code.

      I'm overwhelmed by the response from this forum, muchas gracias senors, mucho gusto. What started as an optimistic 2-hour hack of someone-else's code a week ago seems to be turning into an obsession.

      Cheers, Jim

Re: variable sees it, array doesn't - stumped!
by DStaal (Chaplain) on Dec 31, 2008 at 16:44 UTC

    I find the Perl-magic for printing arrays confusing, so I always just specify exactly I want. How does print (join ' ', @array), "\n"; look?

      print (join ' ', @array), "\n";

      ...sadly, Perl's syntax will have you for breakfast here... the brackets will be interpreted as delimiting the parameters of the print "function" -- see perlfunc.

        You are right: I thought I was using it someplace, but everywhere I've got it I put something else in before the output of the join.

        Either print((join ' ', @array), "\n"); or print (join(' ', @array)), "\n"; or even print join(' ', @array), "\n"; should work better.

      It's true what they say then, there's always another way! Thanks for this, it does indeed look a little more intuitive.