Quote:
quote:Originally posted by jakeone
Hello,
I read up on regular expressions and after a lot of trial and error I came up with the following function to check to see if a variable contains valid "currency" data.
function isDigits($price) {
return !preg_match("/[^0-9\.]/",$price);
}
It works - sort of. I want to make sure that, at most, only one decimal point is allowed but I'm not sure how to do this. I've tried numerous combinations but, to be honest, I'm just guessing now! Any pointers would be appreciated. Thanks.
|
I don't know how your regular expression works, to be honest! Your regular expression looks like it searches for a single character, which can't be a digit or a decimal point. That's not really what you intended, I think.
A better approach might be to try and match the entire currency number. Before we can do that, we need to define what a valid currency is.
Let's say a currency can have an optional leading dollar sign and any amount of leading whitespace (before or after the $), followed by at least one digit, followed by an optional decimal sign and two additional digits.
Valid currencies, therefore, include:
4
$ 523985.59
$56
529.30
Invalid currencies include:
$$42
$ 52.0
235.003
The regular expression needs to begin with a leading optional dollar sign surrounded by optional whitespace:
$patt = '/^\s*[$]?\s*
Followed by some number of digits
$patt = '/^\s*[$]?\s*\d+
Followed by an optional decimal point and two cent digits
$patt = '/^\s*[$]?\s*\d+(\.\d{2})?
Followed by some additional optional whitespace, I guess:
$patt = '/^\s*[$]?\s*\d+(\.\d{2})?\s*$/';
Keep in mind I haven't tried this out, so play with it.
You could also mess around with commas in the price. Commas must be preceeded by 1, 2, or 3 digits, and can only contain three digits after it before the next punctuation (comma or decimal point).
$patt = '/^\s*[$]?\s*\d{1,3}(\,\d{1,3})+(\.\d{2})?\s*$/';
The main part of this pattern is this:
\d{1,3}(\,\d{3})*(\.\d{2})?
This means 1-3 digits
\d{1,3}
followed by zero or more comma-and-three-digits blocks
(\,\d{3})*
followed by an optional decimal point and two cent digits
(\.\d{2})?
Extending this example even further, you can combine both approaches -- a currency can either be all digits followed by the optional decimal and cents part, or it can be properly formatted with commas, but it can't be both -- that is, you can't have 2345,234.32
To do this, you need to use the OR operator: |.
In pseudocode:
$patt = '/optional whitespace and dollar sign'
. 'either all digits (A) or comma-formatted digits (B)'
. 'an optional decimal and cents part'
. 'optional trailing whitespace/';
In PHP:
Code:
$patt = '/^\s*[$]?\s*((\d+)|(\d{1,3}(\,\d{3})+))(\.\d{2})?\s*$/';
|\---/|\-----------------/|
| A OR B |
\-------------------------/
Outer grouping parens
I've tested this minimally, and it seems to work okay... play with it and let me know how it goes.
Take care,
Nik
http://www.bigaction.org/