the field data has 4 acceptable types of values:
j
47d (where the first one-two characters are between 0 and 80 and third character is d)
9u (where the first one-two characters are between 0 and 80 and third character is u)
3v (where the first character is between 1 and 4 and second character is v).
Otherwise the data should be deemed invalid.
string data = readconsole();
what is the best way of validating this input?
I was considering a combination of .Length and Switch substring checks.
ie.
if (data == "j")
else if (data.substring(1) == "v" && data.substring(0,1) >=1 && data.substring(0,1) <=4)
....
else
writeline("fail");
You can use a regular expression that matches the different kinds of values:
^(j|(\d|[1-7]\d|80)[du]|[1-4]v)$
Example:
if (Regex.IsMatch(data, #"^(j|(\d|[1-7]\d|80)[du]|[1-4]v)$")) ...
Explanation of the regular expression:
^ matches the beginning of string
j matches the literal value "j"
| is the "or" operator
\d matches one digit
[1-7]\d matches "10" - "79"
80 matches "80"
[du] matches either "d" or "u"
[1-4] matches "1" - "4"
v matches "v"
$ matches the end of the string
A regular expression will be the most succinct way to validate such rules.
You can use the regular expression:
^(?:j|(?:[0-7]?[0-9]|80)[du]|[1-4]v)$
Another option is to split by number and letter, and check the results. This is quite longer, but probably easier to maintain in the long run:
public bool IsValid(string s)
{
if (s == "j")
return true;
Match m = Regex.Match(s, #"^(\d+)(\p{L})$");
if (!m.Success)
return false;
char c = m.Groups[2].Value[0];
int number;
if (!Int32.TryParse(m.Groups[1].Value, NumberStyles.Integer,
CultureInfo.CurrentCulture, out number)) //todo: choose culture
return false;
return ((c == 'u' || c == 'd') && number > 0 && number <= 80) ||
(c == 'v' && number >= 1 && number <= 4);
}
Related
I am looking to take a string from an input text box and remove all special characters and spaces.
e.g.
Input: ##HH 4444 5656 3333 2AB##
Output: HH4444565633332AB
If dealing with unicode to remove one or more characters that is not a letter nor a number:
[^\p{L}\p{N}]+
See this demo at regexstorm or a C# replace demo at tio.run
\p{L} matches any kind of letter from any language
\p{N} matches any kind of numeric character in any script
Let's define what we are going to keep, not what to remove. If we keep Latin letters and digits only we can put
string result = Regex.Replace(input, "[^A-Za-z0-9]", "");
or (Linq alternative)
string result = string.Concat(input
.Where(c => c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' c >= '0' && c <= '9'));
How can I allow the users that can only type 2words that only accepts M and C word and 5 digits number (0-9) ?
For example MC04326
Here is my code so far
else if (!(new Regex(#"^(MC)(([][0-9])$")).IsMatch(txtStudentIDReg.Text))
{
}
No need for regex with such simple validation:
// str is inputted string
var isValid =
str.StartsWith("MC") && // starts with MC
str.Substring(2).All(ch => char.IsDigit(ch)) && // after second character, all are digits
str.Length == 7; // is of length 7
What regular expression can I use to make sure input matches either a character 'a' or character 'x'.
I have tried the following but this doesn't work as I had hoped.
char option;
Console.WriteLine("Please make your option");
for (int i = 0; i < options.Length; i++)
{
Console.WriteLine(options[i]);
}
option = char.Parse(Console.ReadLine());
while (option != 'a' || option != 'x')
{
Console.WriteLine("'a' or 'x' please!!");
option = char.Parse(Console.ReadLine());
}
What I want is for one of the two characters to be accepted only...as input.
Regex.IsMatch(input, "[ax]", RegexOptions.IgnoreCase);
will match a,x,A,X
a + x in rational language, (a | x) or [ax] in almost every regexp system.
No regex is needed, you have logic error here, you need to use && (AND) logic operator instead of || (OR) in your while loop:
while (option != 'a' && option != 'x')
I am looking for a regex to find out the given word sequence has any special characters.
For example.
In this input string
"test?test";
I would like to find out the words got
"test(any special char(s) including space)test"
You can just use [^A-Za-z0-9], which will match anything that is not alphanumeric, but of course it depends on what you consider a "special character." If underscore is not special [\W] can be a shortcut for anything that is not a word (A-Za-z0-9_) character.
You don't really need a regex here. If you want to test for alphanumeric characters, you car use LINQ, for example (or just iterate over the letters):
string input = "test test";
bool valid = input.All(Char.IsLetterOrDigit);
Char.IsLetterOrDigit checks for all Unicode alphanumeric characters. If you only want the English ones, you can write:
public static bool IsEnglishAlphanumeric(char c)
{
return ((c >= 'a') && (c <= 'z'))
|| ((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'));
}
and use it similarly:
bool valid = input.All(IsEnglishAlphanumeric);
what's the quickest way to extract a 5 digit number from a string in c#.
I've got
string.Join(null, System.Text.RegularExpressions.Regex.Split(expression, "[^\\d]"));
Any others?
The regex approach is probably the quickest to implement but not the quickest to run. I compared a simple regex solution to the following manual search code and found that the manual search code is ~2x-2.5x faster for large input strings and up to 4x faster for small strings:
static string Search(string expression)
{
int run = 0;
for (int i = 0; i < expression.Length; i++)
{
char c = expression[i];
if (Char.IsDigit(c))
run++;
else if (run == 5)
return expression.Substring(i - run, run);
else
run = 0;
}
return null;
}
const string pattern = #"\d{5}";
static string NotCached(string expression)
{
return Regex.Match(expression, pattern, RegexOptions.Compiled).Value;
}
static Regex regex = new Regex(pattern, RegexOptions.Compiled);
static string Cached(string expression)
{
return regex.Match(expression).Value;
}
Results for a ~50-char string with a 5-digit string in the middle, over 10^6 iterations, latency per call in microseconds (smaller number is faster):
Simple search: 0.648396us
Cached Regex: 2.1414645us
Non-cached Regex: 3.070116us
Results for a ~40K string with a 5-digit string in the middle over 10^4 iterations, latency per call in microseconds (smaller number is faster):
Simple search: 423.801us
Cached Regex: 1155.3948us
Non-cached Regex: 1220.625us
A little surprising: I would have expected Regex -- which is compiled to IL -- to be comparable to the manual search, at least for very large strings.
Use a regular expression (\d{5}) to find the occurrence(s) of the 5 digit number in the string and use int.Parse or decimal.Parse on the match(s).
In the case where there is only one number in text.
int? value = null;
string pat = #"\d{5}"
Regex r = new Regex(pat);
Match m = r.Match(text);
if (m.Success)
{
value = int.Parse(m.Value);
}
Do you mean convert a string to a number? Or find the first 5 digit string and then make it a number? Either way, you'll probably be using decimal.Parse or int.Parse.
I'm of the opinion that Regular Expressions are the wrong approach. A more efficient approach would simply to walk through the string looking for a digit, and then advancing 4 characters and seeing if they are all digits. If they are, you've got your substring. It's not as robust, no, but it doesn't have the overhead either.
Don't use a regular expression at all. It's way more powerful than you need - and that power is likely to hit performance.
If you can give more details of what you need it to do, we can write the appropriate code... (Test cases would be ideal.)
If the numbers exist with other characters regular expressions are a good solution.
EG: ([0-9]{5})
will match - asdfkki12345afdkjsdl, 12345adfaksk, or akdkfa12345
If you have a simple test case like "12345" or even "12345abcd" don't use regex at all. They are not known by they speed.
For most strings a brute force method is going to be quicker than a RegEx.
A fairly noddy example would be:
string strIWantNumFrom = "qweqwe23qeeq3eqqew9qwer0q";
int num = int.Parse(
string.Join( null, (
from c in strIWantNumFrom.ToCharArray()
where c == '1' || c == '2' || c == '3' || c == '4' || c == '5' ||
c == '6' || c == '7' || c == '8' || c == '9' || c == '0'
select c.ToString()
).ToArray() ) );
No doubt there are much quicker ways, and lots of optimisations that depend on the exact format of your string.
This might be faster...
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0)
newPhon[i++] = c;
return newPhon.ToString();
}
if you want to limit it to at most five digits, then
public static string DigitsOnly(string inVal)
{
char[] newPhon = new char[inVal.Length];
int i = 0;
foreach (char c in inVal)
if (c.CompareTo('0') > 0 && c.CompareTo('9') < 0 && i < 5)
newPhon[i++] = c;
return newPhon.ToString();
}