Re: Validating price (US Currency)
On Mon, Apr 23, 2001 at 01:15:13PM -0400, David Gilden wrote: [ brought back to the list with permission ] > my camel learning perl book has hashs with the key in quotes, > whats going on with this? In the early days this was necessary, otherwise the key would be interpreted as a function and its result used as the key. I don't think this has been necessary since perl 5.005, But, be careful if your key actually has the same name a function. Things can get confusing. For you if not for perl itself. The camel's getting pretty long in the tooth now. > And is there a short hand for the following? > > > &checkPrice($in{price}); I was going to mention this before, but I forgot. Calling a sub as &sub() is so .. perl4. Of course it's still supported and correct, but I find it helpful to remove superfluous punctuation. I think it helps to make the meat of the program stand out. > sub checkPrice{ > return ($_[0] =~ /^\$?(\d+|\d*\.\d\d)$/) ? 1 : 0; > } > > # can this be rewritten as: > sub checkPrice{ > return ( /^\$?(\d+|\d*\.\d\d)$/) ? 1 : 0; > } No. $_ isn't set on entry to a sub - @_ is. So you will need the first version, but there is no need for the ?: operator. sub checkPrice { return $_[0] =~ /^\$?(\d+|\d*\.\d\d)$/ } Be careful when manipulating @_ though. Perl uses pass-by-reference, so changing @_ changes the actual arguments passed to the sub. This is why many subs start off with my ($a1, $a2, $a3) = @_ or something similar. This takes copies of the arguments and effectively gets you pass-by-value semantics. Depending on how defensive you are being, you might want to check that you are being passed one and only one parameter, possibly by using a prototype or checking the length of @_. Also, for a function this size I would personally also get rid of the return keyword. All subs return the value of their last expression when they fall off the end, and so I would use sub checkPrice { $_[0] =~ /^\$?(\d+|\d*\.\d\d)$/ } but I know some people are (violently) against this sort of thing. I like using Perl's idioms, and with something this size I think it's pretty obvious what's happening. For another can of worms, I would also go with check_price() as the name of the sub. See perldoc perlstyle. But this is very personal. The convention where I work is checkPrice() and I don't like it, but I'm learning to live with it. Almost :-) -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Re: Validating price (US Currency)
On Mon, Apr 23, 2001 at 11:38:42AM -0400, David Gilden wrote: : Is there a better way of doing this? Dave, here is my take on it, hopefully commented well: #!/usr/local/bin/perl -w use strict; $|++; while ( ) { chomp; print( &validate( $_ ) ? 'valid entry' : 'try again punk' ); print "\n"; } sub validate { my $currency = shift; # return false if we have an empty string or the string is just '$'. return 0 unless length( $currency ) > 0 && $currency ne '$'; $currency =~ m< ^ # The beginning of the string \$?# We may have a $ sign, we may not \s*# We may encounter some space here \d*# We may nave a numerator but could just have '.50' (?:\.?\d{1,2})? # and we might have a denominator $ # The end of the string >x ? 1: 0; # true if match succeeded, false otherwise } __DATA__ $ $ 4.000 0 $5 $ 5 $ 5.0 $5.00 5.00 .4 $.60 The output from this program should be: try again punk try again punk try again punk valid entry valid entry valid entry valid entry valid entry valid entry valid entry valid entry which is what I'd expect. I'm sure this won't work in all cased but it handles a few more than your original post. Enjoy! : Thanks! : Dave : : : : if ($in{'price'} eq "") {print '• Missing '; } : elsif (&checkPrice($in{'price'})) { : print '• Wrong Format'; : } : : : : : sub checkPrice{ : : if ($_[0] =~ /\$?(\d*)(\.\d{0,2})?/) { : return 1; : } else { : return 0; : } : : } : : : Allowable input: : $1 : $1.50 : 2 : .50 : $.50 : - : Not allowable input: : a : $5a : $e.40 : -- -- Casey West
Re: Validating price (US Currency)
On Mon, Apr 23, 2001 at 11:38:42AM -0400, David Gilden wrote: > Is there a better way of doing this? Hmmm. Where to start? :-) > Thanks! > Dave > > > > if ($in{'price'} eq "") {print '• Missing '; } > elsif (&checkPrice($in{'price'})) { > print '• Wrong Format'; > } > > > > > sub checkPrice{ > > if ($_[0] =~ /\$?(\d*)(\.\d{0,2})?/) { > return 1; > } else { > return 0; > } > > } > First, a couple of style issues: - There is (now) (normally) no need to quote the keys when accessing a hash. $in{price} will do fine. - Code of the form if (x) { return 1 } else { return 0 }is the same as return x ? 1 : 0 but you normally mean return x Now to the regex. > Allowable input: > $1 > $1.50 > 2 > .50 > $.50 > - > Not allowable input: > a > $5a > $e.40 > -- Your regex doesn't quite cut it at the moment. Try /^\$?(\d+|\d*\.\d\d)$/ I _think_ that's OK. Think about: $ a$1 Finally, I think your elsif clause is backwards. This leaves: if (!length $in{price}) { print '• Missing '; } elsif ($in{price} !~ /^\$?(\d+|\d*\.\d\d)$/) { print '• Wrong Format'; } possibly. -- Paul Johnson - [EMAIL PROTECTED] http://www.pjcj.net
Validating price (US Currency)
Is there a better way of doing this? Thanks! Dave if ($in{'price'} eq "") {print '• Missing '; } elsif (&checkPrice($in{'price'})) { print '• Wrong Format'; } sub checkPrice{ if ($_[0] =~ /\$?(\d*)(\.\d{0,2})?/) { return 1; } else { return 0; } } Allowable input: $1 $1.50 2 .50 $.50 - Not allowable input: a $5a $e.40 --