Re: Validating price (US Currency)

2001-04-23 Thread Paul Johnson

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)

2001-04-23 Thread Casey West

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)

2001-04-23 Thread Paul Johnson

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)

2001-04-23 Thread David Gilden

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
--