Convert part of string to double with regex - c#

My application seem crash on "wrong format", I have this:
Match m = Regex.Match(value, "[0-9]+[.[0-9]+]?");
double number = Convert.ToDouble(m.Value);
return number;
Point is to make string values like this: 114.6W, 120.6W. into values I can sort.
My function that I wrote is suppose to turn any string into a 9999.9999 double value, but it crash on Convert.ToDouble(). Saying wrong input format?

Maybe the . is not the decimal separator for the culture you are using. Try specifying InvariantCulture when parsing:
double number = Convert.ToDouble(m.Value, CultureInfo.InvariantCulture);

The problem is with your regex: it should read
[0-9]+(\.[0-9]+)?
[.[0.9]+] (which I am surprised parses at all) is a character class looking for any character in the following set: a dot, an opening and closing bracket, 0 to 9, or a plus sign.

You must replace square brackets by parenthesis
Match m = Regex.Match(value, #"[0-9]+(?:\.[0-9]+)?");

If it is guaranteed to always be a decimal number followed by a single letter, then:
var word = "120.6W";
var d = Decimal.Parse(word.Substring(0,word.Length-1));

Try these two regexes, you may need to test and adjust to your needs
this one will grab all numbers including the ., but only if followed by a W (won't grab the w)
(?i)\d+\.\d+(?=w)
this one will grab all the digits regardless what's after it
\d+\.\d+
or if your data sets consists of only the numbers plus one letter and nothing in front or after it, do as #paul suggests, just strip the last char

Related

Regex floating point Number Formatter for Wpf Textbox

I saw Regex today for the first time. I need a regex formatter for my WPF Textbox like this:
12345,1234
I need a decimal separator like "," or "." and negative Numbers should be allowed.
So you can write something like this:
230,56 / 1289,4 / -1.9 / 63478,1252 / 0.3265
This should not be possible:
086,344 / 34,7000 / 1.0×10−4
A 0 at first if there is not a comma behind there should not be allowed. And if the last Number after the Comma is a 0 is also bad. No scientific notation.
I found a code for simple integer values:
private void Int_PreviewTextInput(object sender, System.Windows.Input.TextCompositionEventArgs e)
{
// Just Ints
Regex regex = new Regex("[^0-9]+");
e.Handled = regex.IsMatch(e.Text);
}
So how does a formatter for floating point numbers like my description looks like?
Looking at your requirements, it seems that the following pattern would work:
^-?(?!.*0$)(?!0\d)\d+(?:[,.]\d+)?$
See the demo
^ - Start string ancor.
-? - Optional hyphen to allow for negative values.
(?!.*0) - Negative lookahead to prevent a string that ends with 0.
(?!0\d) - Negative lookahead to prevent a string that starts with 0 and a digit.
\d+ - Any digit at least once.
(?: - Open non-capture group.
[,.] - A comma or dot as decimal delimiter.
\d+ - One or more digits.
)? - Close non-capture group and make it optional.
$ - End string ancor.
If you want to check if user entered valid decimal number, .NET offers you readable and simple way of validating that. Justs use decimal.TryParse
In the spirit of "use the right tool for the job", you should not use regex for such validation.
Just use it like:
var parseOk = decimal.TryParse(textBlock.Text, out _); // here I used _ as parameter name, as it is not relevant
if(! parseOk)
{
// validation failed
}
In order to control how decimal separators are treated, you can use overload fo metnioned method:
public static bool TryParse (string s, System.Globalization.NumberStyles style,
IFormatProvider provider, out decimal result);
And please look at the docs.
Also, you have to decide how number will be stored (float, decimal or double). Fortunately, each of these types exposes two static methods: Parse and TryParse - I encourage you to read about them.
I interpret your requirements as follows:
The string might have an optional "-" character in front
Before the decimal separator, there should be either a single "0", or any number of digits not starting with a "0".
After the decimal separator, there should be either a single "0", or any number of digits not ending with a "0".
This translates straightforward to the following regex:
#"^-?(0|[1-9]\d*)[,\.](0|\d*[1-9])$"
If numbers without decimal separators are allowed (the question is not clear about this), the part starting from the separator would be optional, i.e.
#"^-?(0|[1-9]\d*)([,\.](0|\d*[1-9]))?$"

Match two comma separated numbers with period as decimal separator inside angle brackets

I'm trying to build a regex pattern in C# for matching the following format
<0.0,100000.0>
and so far came up with this regex
var regexItem = new Regex(#"[<(]*[0-9][.]*[0-9][,]*[0-9][.]*[0-9][>)]$");
But this regex is accepting something like <0,100000>
Generally I want to match a range where numbers need to have a decimal separator.
Edit: Finally I used this
var regexItem = new Regex(#"^[(<]\d+\.\d+,\d+\.\d+[)>]$");
Thank you for help
It might help to simplify this regex to see the problem.
[0-9] is actually equal to \d. Also if [] only has one value inside it, the brackets can be omitted (as long as the item inside is escaped if required): Therefore [.] -> \.
[<(]*\d\.*\d,*\d\.*\d[>)]$
Now looking at this I think what has happened is that you have put the * before an element instead of after it. Also dots should also be escaped (because they actually mean any character, not a literal dot)
So this should hopefully do the trick:
^[<(]\d+\.\d+,\d+\.\d+[>)]$
var regexItem = new Regex(#"^[<(]\d+\.\d+,\d+\.\d+[>)]$");
You'll have to modify the regex yourself to match your exact needs, this merely fixes the problem that you specified in your question.

Regex to exclude a particular substring pattern

My current regex code is as beow .
var caption = Regex.Replace(fileImage.Caption, #"[^\w\s\(\)\.#-]", "",RegexOptions.None);
Here I replace special characters with empty character excluding certain special characters
Now I have a strange situation where I along with above match i need to exculde a substring of type × where 215 can any number . Its can be a normal decimal or hexadecimal . if it is a hexadecimal number then it starts with 'x' after &#.
How can I achive this?
Think you mean this,
var caption = Regex.Replace(fileImage.Caption, #"(&#x?[a-f\d]+;)|[^\w\s\(\)\.#-]", "$1");
DEMO

Regex to allow some special characters c#

I have to check whether a string contains special characters or not but I can allow these 5 special characters in it .()_-
i have written my regex as
var specialCharacterSet = "^[()_-.]";
var test = Regex.Match("a!", specialCharacterSet);
var isValid = test.Success;
but its throwing an:
error parsing "^[()_-.]" - [x-y] range in reverse order.
You have specified a range with -. Place it at the end:
[()_.-]
Otherwise the range is not correct: the lower boundary symbol _ appears later in the character table than the upper bound symbol .:
Also, if you plan to check if any of the character inside a string belongs to this set, you should remove ^ that checks only at the beginning of a string.
To test if a string meets some pattern, use Regex.IsMatch:
Indicates whether the regular expression finds a match in the input string.
var specialCharacterSet = "[()_.-]";
var test = Regex.IsMatch("a!", specialCharacterSet);
UPDATE
To accept any string value that doesnt contains the five characters, you can use
var str = "file.na*me";
if (!Regex.IsMatch(str, #"[()_.-]"))
Console.WriteLine(string.Format("{0}: Valid!", str));
else
Console.WriteLine(string.Format("{0}: Invalid!", str));
See IDEONE demo
You can use ^[()_\-.] or ^[()_.-] if you use special characters then best use \ before any special characters (which are used in regex special char.).
[()_.-]
Keep - at end or escape it to avoid it forming an invalid range.- inside a character class forms a range.Here
_ is decimal 95
. is decimal 46.
So it is forming an invalid range from 95 to 46
var specialCharacterSet = "^[()_.-]";
var test = Regex.IsMatch("a!", specialCharacterSet);
Console.WriteLine(test);
Console.ReadLine();
Convert all special characters in a pattern to text using Regex.Escape(). Suppose you already have using System.Text.RegularExpressions;
string pattern = Regex.Escape("[");
then check like this
if (Regex.IsMatch("ab[c", pattern)) Console.WriteLine("found");
Microsoft doesn't tell about escape in the tutorial. I learned it from Perl.
The best way in terms of C# is [()_\-\.], because . and - are reserved characters for regex. You need to use an escape character before these reserved characters.

Match pattern of [0-9]-[0-9]-[0-9], but without matching [0-9]-[0-9]

I'm not sure how to accomplish this with a regular expression (or if I can; I'm new to regex). I have an angle value the user will type in and I'm trying to validate the entry. It is in the form degrees-minutes-seconds. The problem I'm having, is that if the user mistypes the seconds portion, I have to catch that error, but my match for degrees-minutes is a success.
Perhaps the method will explain better:
private Boolean isTextValid(String _angleValue) {
Regex _degreeMatchPattern = new Regex("0*[1-9]");
Regex degreeMinMatchPattern = new Regex("(0*[0-9]-{1}0*[0-9]){1}");
Regex degreeMinSecMatchPattern = new Regex("0*[0-9]-{1}0*[0-9]-{1}0*[0-9]");
Match _degreeMatch, _degreeMinMatch, _degreeMinSecMatch;
_degreeMinSecMatch = degreeMinSecMatchPattern.Match(_angleValue);
if (_degreeMinSecMatch.Success)
return true;
_degreeMinMatch = degreeMinMatchPattern.Match(_angleValue);
if (_degreeMinMatch.Success)
return true;
_degreeMatch = _degreeMatchPattern.Match(_angleValue);
if (_degreeMatch.Success)
return true;
return false;
}
}
I want to check for degrees-minutes if the degrees-minutes-seconds match is unsuccessful, but only if the user didn't enter any seconds data. Can I do this via regex, or do I need to parse the string and evaluate each portion separately? Thanks.
EDIT: Sample data would be 45-23-10 as correct data. The problem is 45-23 is also valid data; the 0 seconds is understood. So if the user types 45-23-1= on accident, the degreeMinMatchPattern regex in my code will match succesfully, even though it is invalid.
Second EDIT: Just to make it clear, the minutes and second portions are both optional. The user can type 45 and that is valid.
You can specify "this part of the pattern must match at least 3 times" using the {m,} syntax. Since there are hyphens between each component, specify the first part separately, and then each hyphen-digit combination can be grouped together after:
`[0-9](-[0-9]){2,}`
You also can shorten [0-9] to \d: \d(-\d){2,}
First off, a character in a regex is matched once by default, so {1} is redundant.
Second, since you can apparently isolate this value (you prompt for just this value, instead of having to look for it in a paragraph of entered data) you should include ^ and $ in your string, to enforce that the string should contain ONLY this pattern.
Try "^\d{1,3}-\d{1,2}(-\d{1,2})?$".
Breaking it down: ^ matches the beginning of the string. \d matches any single decimal character, and then behind that you're specifying {1,3} which will match a set of one to three occurrences of any digit. Then you're looking for one dash, then a similar decimal pattern but only one or two times. The last term is enclosed in parenthesis so we can group the characters. Its form is similar to the first two, then there's a ? which marks the preceding character group as optional. The $ at the end indicates that the input should end. Given this, it will match 222-33-44 or 222-33, but not 222-3344 or 222-33-abc.
Keep in mind there are additional rules you might want to incorporate. For instance, seconds can be expressed as a decimal (if you want a resolution smaller than one second). You would need to optionally expect the decimal point and one or more additional digits. Also, you probably have a maximum degree value; the above regex will match the maximum integer DMS value of 359-59-59, however it will also match 999-99-99 which is not valid. You can limit the maximum value using regex (for example "(3[0-5]\d|[1-2]\d{2}|\d{1,2})" will match any number from 0 to 359, by matching a 3, then 0-5, then 0-9, OR any 3-digit number starting with 1 or 2, OR any two-digit number), but as the example shows the regex will get long and messy, so document it well in code as to what you're doing.
Maybe you would do better to just parse the input out and check is piece separately.
I'm not sure I understand correctly, but I think
(?<degrees>0*[0-9])-?(?<minutes>0*[0-9])(?:-?(?<seconds>0*[0-9]))?$
might work.
But this is quite ambiguous; also I'm wondering why you're only allowing single-digit degree/minute/second values. Please show some examples you do and don't want to match.
Maybe you should to try something like this and test for empty/invalid groups:
Regex degrees = new Regex(
#"(?<degrees>\d+)(?:-(?<minutes>\d+))?(?:-(?<seconds>\d+))?");
string[] samples = new []{ "123", "123-456", "123-456-789" };
foreach (var sample in samples)
{
Match m = degrees.Match(sample);
if(m.Success)
{
string degrees = m.Groups["degrees"].Value;
string minutes = m.Groups["minutes"].Value;
string seconds = m.Groups["seconds"].Value;
Console.WriteLine("{0}°{1}'{2}\"", degrees,
String.IsNullOrEmpty(minutes) ? "0" : minutes,
String.IsNullOrEmpty(seconds) ? "0" : seconds
);
}
}

Categories