Re: Changing the Value Assigned To A Hash Key
by dragonchild (Archbishop) on Feb 08, 2005 at 20:08 UTC
|
Add 'use strict;' to the top of your script. That will catch the spelling error.
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
|
|
use strict;
use warnings;
Are you seeing a spelling error I am not? Just triple checked... | [reply] [d/l] |
|
|
The value of $app{"first_name"} is not changed to undef in &print_application but @errors is. print statements confirm both are changed inside of the "if (request_method() eq "POST")" block.
Your statement implies that there is an issue with changing values in the %app hash within the print_application() function. Since you didn't show us the print_application() function nor did you show us the beginning of your script where you (correctly) have 'use strict;', I gave you the most common error which is a mispelling of %app.
Some other possibilities include:
- Mispelling 'first_name'. Hash keys are case-sensitive.
- Declaring %app within print_application().
- Using this script under mod_perl (or some other persistent environment like FastCGI). (You'd be getting a "%app will not stay shared" error, but you might not be looking at the error log.)
Given the dearth of information, this is the best I can do. Good luck!
Being right, does not endow the right to be rude; politeness costs nothing. Being unknowing, is not the same as being stupid. Expressing a contrary opinion, whether to the individual or the group, is more often a sign of deeper thought than of cantankerous belligerence. Do not mistake your goals as the only goals; your opinion as the only opinion; your confidence as correctness. Saying you know better is not the same as explaining you know better.
| [reply] |
Re: Changing the Value Assigned To A Hash Key
by cog (Parson) on Feb 08, 2005 at 20:31 UTC
|
A couple of thoughts:
unless ($first_name_check == "1") {
If == is numeric comparison, why are you giving it a string? Do either $first_name_check eq "1" or $first_name_check == 1. Not that it's going to change anything in how your program works, but do it for consistency.
Also, as cowboy notes, instead of $app{"first_name"} = ""; you should probably use undef $app{"first_name"}
Another thing: instead of "First Name: ".$first_name_check, I would use "First Name: $first_name_check" directly. | [reply] [d/l] [select] |
|
|
I had wondered if == "1" was the best technique. This is alllmost my first ever Perl script.
A number of quick functions are used to check user data against input criteria (for checking telephone numbers, postal codes, etc.). The code below is for checking a persons first or last name; one of many checks on this form. All we want to do is verify that more than two characters of an acceptable type are used.
sub check_name {
my $name = $_[0];
if ($name =~ /^[A-Z][A-Za-z\-']{2,40}/s) {
return 1;
} else {
return "Friendly message...";
}
}
I wanted to return true or false, but wasn't sure how to incorporate an error message anywhere in the many scripts that call this function. It seemed OK to return a true of OK and a string warning if bad. Running with that idea, the "($first_name_check == "1")" test seemed to be the way to go.
It crossed my mind to move the all error messages to a seperate file and return error codes greater than one as index references in the seperate error message file. I haven't seen any good examples of accomplishing this task and would certainly appreciate suggestions on where to go look/read. (All I have is an old Perl cookbook that just seems wrong...
Switch undef around. Thanks for both your suggestions
# was $app{"first_name"} = ""; switch to next line
undef $app{"first_name"};
| [reply] [d/l] [select] |
|
|
Your code doesn't check if two characters are used; it checks if one of [A-Z] is used plus two to fourty of [A-Za-z\-'].
If you really want at least two characters and the first one must be in [A-Z], use this instead: [A-Z][A-Za-z\-']+. It does the trick :-)
As for returning the warning string, I don't think that's a good idea, because both 1 and "Friendly message..." evaluate to a true value; hence, the caller won't be able to tell the difference easily. Return 0 or undef in case there's something wrong. This way, you can do something like if ($first_name_check) {.
The Cookbook sure is a good book, but I'd advise you to buy the Learning Perl. Trust me, it'll be worth the money and you'll enjoy the reading :-)
| [reply] [d/l] [select] |
Re: Changing the Value Assigned To A Hash Key
by cowboy (Friar) on Feb 08, 2005 at 20:12 UTC
|
Can you post more of the code?
Try running it under perl -w,
It should point out a few possible mistakes
(like comparing a string using ==)
Also, your code is not changing $app{"first_name"} to undef.
It is changing it to "", which is merely an empty string.
| [reply] |
|
|
Hi, thanks for responding. Wow, you guys are f-a-s-t.
I think -w is ignored by Windows since it doesn't understand the she-bang. The top of the script does "use warnings".
Oh, and the "" are back to undef. That was leftovers from desperate testing. :-)
| [reply] |
|
|
It's neither ignored on the command line (perl -w script.pl) nor on the shebang line (#!/usr/bin/perl -w). While Windows doesn't know anything about the shebang line, Perl checks for a shebang line, and treats everything after perl as options.
| [reply] [d/l] [select] |
Re: Changing the Value Assigned To A Hash Key
by gnurob (Initiate) on Feb 08, 2005 at 22:07 UTC
|
dragonchild,
The significant lines of the script are posted in another reply. Yes, the values in the %app hash are not changed in the &print_application() function. Or, rather, the &print_application() function is seeing values that should be undef when another function tests thoese values and finds them to be unacceptable.
Thank you for your list of possible causes. I checked the hash key spelling, "my (or local) %app" in the &print_application() function, and the IIS error logs say nothing (they never do offer much help). Did I mention I hate IIS today?
"Given the dearth of information". Opps. (Sorry. I was hoping not to clutter the post with noise.)
cog,
I missed the "returned value" == "1" vs. "returned value" == 1 vs. "returned value" eq "1" in your earlier post. Thanks for the suggestion. I'll always aspire to write things more exactly. Unfortunatley the O'Reilly Perl book is slightly larger than my head and is among my first programming attempts. (You've all probably noticed my unusual methods such this cludge (I'll find a better way sometime):
my $first_name_check = &check_name($app{"first_name"});
unless ($first_name_check == 1) {
undef $app{"first_name"};
push (@errors, "First Name: ".$first_name_check);
}
Thanks for catching the regex mistake. :-)
Your comment, "As for returning the warning string, I don't think that's a good idea, because both 1 and "Friendly message..." evaluate to a true value" has made me reconsider that technique. It did cross my mind that both return values were technically true but thought that keeping the failure message with the test function was helpful. What do you think of returing (1, "Test OK") or (0, "Helpful message")? ...another bad idea? My first attempt was:
sub check_name {
my $name = $_[0];
if ($name =~ /^[A-Z][A-Za-z\-']+/s) {
return 1;
} else {
return 0;
}
}
unless (check_name($app{"first_name"}) {
undef $app{"first_name"};
push (@errors, "Helpful error message here...");
}
It seems that seperating the error message from the function would require the error message to be repeated everywhere the test will be preformed and the user notified. This could result in error messages falling out of sync with the current rendition of the regular expression. Either way, I'll stick with your recommendation and keep my return values as true/false only. :-)
Learning Perl is a great book (third edition is much better than the second). The table of contents completely fell out of the binding because of the number of times I fall back on this book.
I'm hoping to develop better habbits with time and practice.
| [reply] [d/l] [select] |
Re: Changing the Value Assigned To A Hash Key
by gnurob (Initiate) on Feb 08, 2005 at 21:29 UTC
|
This should be enough of the code to let you see the complete picture. Hopefully I didn't miss anything important.
#!perl.exe
use strict;
use warnings;
use CGI qw(:standard -no_xhtml);
# the check_name, etc, functions are in this require'd file except in
# this example code
# require "D:/Inetpub/wwwroot/gpa/functions.pl";
my @errors;
my %app;
$app{"first_name"} = param('first_name');
$app{"telephone"} = param('telephone');
$app{"email"} = param('email');
# Verify the POST data (if any) using custom tests and undef bad
# values. If everything checks OK, accept the data and print a
# success message. Else print the application form (which will
# preserve all good values which users will appreciate.
if (request_method() eq "POST") {
my $first_name_check = &check_name($app{"first_name"});
unless ($first_name_check == "1") {
undef $app{"first_name"};
push (@errors, "First Name: ".$first_name_check);
}
my $phone_check = &check_phone($app{"telephone"});
unless ($phone_check == "1") {
undef $app{"telephone"};
push (@errors, "Telephone: ".$phone_check);
}
my $email_check = &check_email($app{"email"});
unless ($email_check == "1") {
undef $app{"email"};
push (@errors, "E-mail: ".$email_check);
}
if (@errors) {
# Give the user another chance.
&print_application;
} else {
# Done!
&print_accepted;
}
} else {
# Give the user an application form.
&print_application;
}
# We want first and last names to be a certain way.
sub check_name {
my $name = $_[0];
if ($name =~ /^[A-Z][A-Za-z\-']{2,40}/s) {
return 1;
} else {
return "Helpful message.";
}
}
# Chopped other subs to shorten post
sub check_phone {
return 1;
}
sub check_email {
return 1;
}
# Print account application page.
sub print_application {
# chopped lots of non-relevant code...
# here's those helpful error messages regarding BAD data...
if (@errors) {
print h2("Account Application Error"), "\n\n",
p(b("Problems found...")), "\n\n",
ol(li[@errors]), "\n\n";
}
# print the form and populate form with GOOD data...
# Avoiding line wraps in on-line post. n/b the funny indents :-)
Tr(
[
td([
b('First Name:'),
textfield(-name=>'first_name', -default=>"$app{'first_name'}")
]),
td([
b('Organization:'),
textfield(-name=>'organization', -default=>"$app{'organization'}")
]),
td([
b('Telephone:'),
textfield(-name=>'telephone', -default=>"$app{'telephone'}")
]),
td([
b('E-mail:'),
textfield(-name=>'email', -default=>"$app{'email'}")
]),
td([
'',
submit
])
]
)
}
# Print account accepted page.
sub print_accepted {
# ...
}
| [reply] [d/l] |
Re: Changing the Value Assigned To A Hash Key
by phaylon (Curate) on Feb 08, 2005 at 22:17 UTC
|
Works for me if I change your check to:
unless ($first_name_check eq 1) {
perl version is 5.8.6,
hth,
p
Thru the darkness of futures past, the magician longs to see.
One chants out, between two worlds - fire, walk with me.
| [reply] [d/l] |
|
|
sub check_name {
return 0;
}
unless (&check_name($app{"first_name"})) { # code } # ,
unless (&check_name($app{"first_name"}) == 1) { # code } # ,
unless (&check_name($app{"first_name"}) eq 1) { # code } # , or
unless (&check_name($app{"first_name"}) eq "1") { # code }
# perl -v
# This is perl, v5.8.4 built for MSWin32-x86-multi-thread
# (with 3 registered patches, see perl -V for more detail)
| [reply] [d/l] |
|
|
Try running this on your commandline:
use warnings;
use strict;
use Data::Dumper;
my @errors;
my %app;
$app{"first_name"} = param('first_name');
# $app{"first_name"} = "test_value";
if (request_method() eq "POST") {
my $first_name_check = &check_name($app{"first_name"});
unless ($first_name_check eq 1) {
print "Not through namecheck\n";
$app{"first_name"} = "";
push (@errors, "First Name: ".$first_name_check);
}
}
print Dumper \@errors;
print Dumper \%app;
sub request_method { return 'POST' }
sub param { return 'testname' }
sub print_application {
# do some stuff with %app and @errors...
}
sub check_name {
my $name = $_[0];
if ($name =~ /^[A-Z][A-Za-z\-']{2,40}/s) {
return 1;
} else {
return "Helpful message.";
}
I got
Not through namecheck
$VAR1 = [
'First Name: Helpful message.'
];
$VAR1 = {
'first_name' => ''
};
--
Thru the darkness of futures past, the magician longs to see.
One chants out, between two worlds - fire, walk with me.
| [reply] [d/l] [select] |
|
|
|
|
|
|
Re: Changing the Value Assigned To A Hash Key
by gnurob (Initiate) on Feb 10, 2005 at 18:19 UTC
|
"thank you" =~ (dragonchild, cowboy, ikegami, cog, phaylon);
I learned a few good ways to work with Perl along the way thanks to your help and patience.
| [reply] |
Re: Changing the Value Assigned To A Hash Key
by gnurob (Initiate) on Feb 08, 2005 at 22:23 UTC
|
unless (&check_name($app{"first_name"})) {
undef $app{"first_name"};
push (@errors, "Names must be...");
}
P.S. Added use CGI::Carp qw(fatalsToBrowser warningsToBrowser) but found no complaints. | [reply] [d/l] |
Re: Changing the Value Assigned To A Hash Key
by gnurob (Initiate) on Feb 10, 2005 at 18:10 UTC
|
Solved!
Another note The default values that you specify for the forms are only used the first time the script is invoked (when there is no query string). On subsequent invocations of the script (when there is a query string), the former values are used even if they are blank.
If you want to change the value of a field from its previous value, you have two choices:
(1) call the param() method to set it.
(2) use the -override (alias -force) parameter (a new feature in version 2.15). This forces the default value to be used, regardless of the previous value:
print $query->textfield(-name=>'field_name',
-default=>'starting value',
-override=>1,
-size=>50,
-maxlength=>80);
Yet another note By default, the text and labels of form elements are escaped according to HTML rules. This means that you can safely use ``<CLICK ME>'' as the label for a button. However, it also interferes with your ability to incorporate special HTML character sequences, such as Á, into your fields. If you wish to turn off automatic escaping, call the autoEscape() method with a false value immediately after creating the CGI object:
$query = new CGI;
$query->autoEscape(undef);
| [reply] [d/l] [select] |