I am working on this method that validates a student Id number. The credentials of the ID number are; the first character has to be 9, the second character has to be a 0, there can not be any letters, and the number must be 9 characters long. The method will return true if the student id is valid. When I go to test the method manually through main it comes out as true, even when I put in a wrong input. In my code, I have the if statements nested, but I originally did not have them nested. What is a better way to validate the input to align with the credentials of the ID number? Would converting the string into an array be more ideal?
public static bool ValidateStudentId(string stdntId)
{
string compare = "123456789";
if (stdntId.StartsWith("8"))
{
if (stdntId.StartsWith("91"))
{
if (Regex.IsMatch(stdntId, #"^[a-zA-Z]+$"))
{
if (stdntId.Length > compare.Length)
{
if (stdntId.Length < compare.Length)
{
return false;
}
}
}
}
}
You can try regular expressions:
public static bool ValidateStudentId(string stdntId) => stdntId != null &&
Regex.IsMatch(stdntId, "^90[0-9]{7}$");
Pattern explained:
^ - anchor - string start
90 - digits 9 and 0
[0-9]{7} - exactly 7 digits (each in [0..9] range)
$ - anchor - string end
So we have 9 digits in total (90 prefix - 2 digits + 7 arbitrary digits), starting from 90
I'm trying to validate a string with this regex
var regexAgencia = new Regex("^(?!0000)([0-9]{4})");
var result = regexAgencia.IsMatch(agencia);
Valid Options:
N-X
NN-X
NNN-X
NNNN-X
N
NN
NNN
NNNN
Invalid Options:
0-X
00-X
000-X
0000-X
0
00
000
0000
Where N is any number 0-9 and X can be X or 0-9
When I validade this "014777417" the regex return true
I need help to write a regex to validade this string with this rules.
This should do it for you:
^(?=\d*[1-9])\d{1,4}(?:-[X\d])?$
It starts with a positive look ahead to ensure a digit other than zero is present ((?=\d*[1-9])). Thereafter it matches 1-4 digits, optionally followed by a hyphen and a digit or X.
See it here at regex101.
You certainly can do this through just Regex, however, I always have this lingering fear of creating code that either:
1) only I understand or remember
2) even I don't understand when looking back
In that spirit, it seems if you do a simple split, your string might be easier to evaluate:
string[] parts = agencia.Split('-');
if ((parts.Length == 1 && Regex.IsMatch(agencia, #"^\d{1,4}$")) ||
(parts.Length == 2 && Regex.IsMatch(parts[0], #"^\d{1,4}$")) &&
Regex.IsMatch(parts[1], #"^[0-9X]$"))
{
}
-- EDIT --
I can't tell if you want 0 or not, so if you don't, change \d from to [1-9].
It would be easier to have two tests: one to check if it could be valid, followed by one to exclude the special case of all leading zeros being invalid:
static void Main(string[] args)
{
string[] agencias = { "", "1234-5", "0-9", "014777417", "0000", "1-23", "01-0", "1-234 abcd", "0123-4" };
var regexAgenciaValid = new Regex("^(([0-9]{1,4})(-[0-9])?)$");
var regexAgenciaInvalid = new Regex("^((0{1,4})(-[0-9])?)$");
foreach (string agencia in agencias)
{
var result = regexAgenciaValid.IsMatch(agencia) && !regexAgenciaInvalid.IsMatch(agencia);
Console.WriteLine(agencia + " " + result);
}
Console.ReadLine();
}
Output:
False
1234-5 True
0-9 False
014777417 False
0000 False
1-23 False
01-0 True
1-234 abcd False
0123-4 True
This has the bonus of being easier to modify in the future.
I have state numbers and state letters of vehicles according to States in DB. State numbers can be old and new type.
Example of new types of state number.
273KL01
002UK02
098KZ03
120US04
...
Example of old types of state number.
R575KMM
A887KDN
M784LKA
X647DUA
...
Bold characters indicates specified State.
User will input his car's state number and choose State. I need to validate If state number can be registered in chosen State. If it not possible(wrong user input) I will show him message like "You entered wrong state number or State" .
I have done this with If-Else statement. But I want to know another way with regex.
As I think, here will be two steps of condition.
Check if number is old type(starts with letter), if true get from DB state letter and check with regex statements.
If case 1 is false, I get from DB state digits and check with regex statements.
I have regex statement for the first condition:
^(?i)f - Where state letter is f.
What will be regex statement for my second conditon?
Or can be it done(two steps both) with one regex statements?
As you further explained that you actually do want to match any letter at the beginning, and any two digits at the end of the string, using a regular expression is indeed the shortest way to solve this.
Regex re = new Regex("^[a-z].*[0-9]{2}$", RegexOptions.IgnoreCase);
Console.WriteLine(re.IsMatch("Apple02")); // true
Console.WriteLine(re.IsMatch("Arrow")); // false
Console.WriteLine(re.IsMatch("45Alty12")); // false
Console.WriteLine(re.IsMatch("Basci98")); // true
Otherwise, if your requirement is simple, e.g. just the letter A or a at the beginning, and 12 or 02 at the end, then you can also solve this easily without regular expressions:
bool Match(string s)
{
if (string.IsNullOrWhiteSpace(s))
return false;
if (s[0] != 'a' && s[0] != 'A')
return false;
return s.EndsWith("02") || s.EndsWith("12");
}
Examples:
Console.WriteLine(Match("Apple02")); // true
Console.WriteLine(Match("Arrow")); // false
Console.WriteLine(Match("45Alty12")); // false
Console.WriteLine(Match("a12")); // true
Console.WriteLine(Match("a")); // false
Console.WriteLine(Match("12")); // false
Of course you can also expand this to fit your more complex requirement. In your case, you could use char.IsLetter and char.IsDigit to make the checks:
bool Match(string s)
{
if (string.IsNullOrWhiteSpace(s))
return false;
return s.Length > 2 && char.IsLetter(s[0]) &&
char.IsDigit(s[s.Length - 1]) && char.IsDigit(s[s.Length - 2]);
}
Note that the IsLetter method also accepts letters from non-English alphabets, so you might need to change that. You could alternatively make a comparison like this:
bool Match(string s)
{
if (string.IsNullOrWhiteSpace(s))
return false;
return s.Length > 2 &&
((s[0] >= 'a' && s[0] <= 'z') || (s[0] >= 'A' && s[0] <= 'Z'))
char.IsDigit(s[s.Length - 1]) && char.IsDigit(s[s.Length - 2]);
}
Here's what you need:
^[Aa].*[01][2]$
With a few explanations:
^ assert position at start of a line
[Aa] match a single character present in the list below
Aa a single character in the list Aa literally
.* matches any character (except newline)
Quantifier: * Between zero and unlimited times, as many times as possible, giving back as needed [greedy]
[01] match a single character present in the list below
01 a single character in the list 01 literally
[2] match a single character present in the list below
2 the literal character 2
$ assert position at end of a line
If you need it to start with any letter :
^[A-Za-z].*[01][2]$
Given your edit:
I would use this regex:
^[A-Z].{6}|.{5}\d{2}$
Which guaranties that the input is:
Of length 7;
Start with a capital letter OR finishes with two digit
I'm new to C# so expect some mistakes ahead. Any help / guidance would be greatly appreciated.
I want to limit the accepted inputs for a string to just:
a-z
A-Z
hyphen
Period
If the character is a letter, a hyphen, or period, it's to be accepted. Anything else will return an error.
The code I have so far is
string foo = "Hello!";
foreach (char c in foo)
{
/* Is there a similar way
To do this in C# as
I am basing the following
Off of my Python 3 knowledge
*/
if (c.IsLetter == true) // *Q: Can I cut out the == true part ?*
{
// Do what I want with letters
}
else if (c.IsDigit == true)
{
// Do what I want with numbers
}
else if (c.Isletter == "-") // Hyphen | If there's an 'or', include period as well
{
// Do what I want with symbols
}
}
I know that's a pretty poor set of code.
I had a thought whilst writing this:
Is it possible to create a list of the allowed characters and check the variable against that?
Something like:
foreach (char c in foo)
{
if (c != list)
{
// Unaccepted message here
}
else if (c == list)
{
// Accepted
}
}
Thanks in advance!
Easily accomplished with a Regex:
using System.Text.RegularExpressions;
var isOk = Regex.IsMatch(foo, #"^[A-Za-z0-9\-\.]+$");
Rundown:
match from the start
| set of possible matches
| |
|+-------------+
|| |any number of matches is ok
|| ||match until the end of the string
|| |||
vv vvv
^[A-Za-z0-9\-\.]+$
^ ^ ^ ^ ^
| | | | |
| | | | match dot
| | | match hyphen
| | match 0 to 9
| match a-z (lowercase)
match A-Z (uppercase)
You can do this in a single line with regular expressions:
Regex.IsMatch(myInput, #"^[a-zA-Z0-9\.\-]*$")
^ -> match start of input
[a-zA-Z0-9\.\-] -> match any of a-z , A-Z , 0-9, . or -
* -> 0 or more times (you may prefer + which is 1 or more times)
$ -> match the end of input
You can use Regex.IsMatch function and specify your regular expression.
Or define manually chars what you need. Something like this:
string foo = "Hello!";
char[] availableSymbols = {'-', ',', '!'};
char[] availableLetters = {'A', 'a', 'H'}; //etc.
char[] availableNumbers = {'1', '2', '3'}; //etc
foreach (char c in foo)
{
if (availableLetters.Contains(c))
{
// Do what I want with letters
}
else if (availableNumbers.Contains(c))
{
// Do what I want with numbers
}
else if (availableSymbols.Contains(c))
{
// Do what I want with symbols
}
}
Possible solution
You can use the CharUnicodeInfo.GetUnicodeCategory(char) method. It returns the UnicodeCategory of a character. The following unicode categories might be what you're look for:
UnicodeCategory.DecimalDigitNumber
UnicodeCategory.LowercaseLetter and UnicodeCategory.UppercaseLetter
An example:
string foo = "Hello!";
foreach (char c in foo)
{
UnicodeCategory cat = CharUnicodeInfo.GetUnicodeCategory(c);
if (cat == UnicodeCategory.LowercaseLetter || cat == UnicodeCategory.UppercaseLetter)
{
// Do what I want with letters
}
else if (cat == UnicodeCategory.DecimalDigitNumber)
{
// Do what I want with numbers
}
else if (c == '-' || c == '.')
{
// Do what I want with symbols
}
}
Answers to your other questions
Can I cut out the == true part?:
Yes, you can cut the == true part, it is not required in C#
If there's an 'or', include period as well.:
To create or expressions use the 'barbar' (||) operator as i've done in the above example.
Whenever you have some kind of collection of similar things, an array, a list, a string of characters, whatever, you'll see at the definition of the collection that it implements IEnumerable
public class String : ..., IEnumerable,
here T is a char. It means that you can ask the class: "give me your first T", "give me your next T", "give me your next T" and so on until there are no more elements.
This is the basis for all Linq. Ling has about 40 functions that act upon sequences. And if you need to do something with a sequence of the same kind of items, consider using LINQ.
The functions in LINQ can be found in class Enumerable. One of the function is Contains. You can use it to find out if a sequence contains a character.
char[] allowedChars = "abcdefgh....XYZ.-".ToCharArray();
Now you have a sequence of allowed characters. Suppose you have a character x and want to know if x is allowed:
char x = ...;
bool xIsAllowed = allowedChars.Contains(x);
Now Suppose you don't have one character x, but a complete string and you want only the characters in this string that are allowed:
string str = ...
var allowedInStr = str
.Where(characterInString => allowedChars.Contains(characterInString));
If you are going to do a lot with sequences of things, consider spending some time to familiarize yourself with LINQ:
Linq explained
You can use Regex.IsMatch with "^[a-zA-Z_.]*$" to check for valid characters.
string foo = "Hello!";
if (!Regex.IsMatch(foo, "^[a-zA-Z_\.]*$"))
{
throw new ArgumentException("Exception description here")
}
Other than that you can create a list of chars and use string.Contains method to check if it is ok.
string validChars = "abcABC./";
foreach (char c in foo)
{
if (!validChars.Contains(c))
{
// Throw exception
}
}
Also, you don't need to check for == true/false in if line. Both expressions are equal below
if (boolvariable) { /* do something */ }
if (boolvariable == true) { /* do something */ }
I'm new to programming (C#).
The application is a 'words generator'.
What I'm looking for is a for loop that can generate all possible words with the characters in a given array of characters.
The details:
I have a List<char> = { A,a,6,w,# } (The length may vary)
I want to generate all possible words (for example: 4 letters length ) with this character set. This options should generate 5 characters & 4 letters = 5*5*5*5 = 625 words.
All generated words should be every possible combination of the given letters only
NOTE:
Some might tell me that i should use a solution called (Permutations of a String/Integer)
this method seems to be fine if the required words length is same as given characters length, but in my case i might give the application 100 characters, But i want it to generate all possible words -> 4 letters length (Example: MaRk, M#rK,m4rK...)
You could use an IEnumerable<String> method:
public IEnumerable<String> GenerateStrings (IEnumerable<char> characters, int length) {
if(length > 0) {
foreach(char c in characters) {
foreach(String suffix in GenerateStrings(characters,length-1)) {
yield return c+suffix;
}
}
} else {
yield return string.Empty;
}
}
Result with csharp (interactive C# shell):
csharp> Foo.GenerateStrings(new char[] {'A','a','6','w','#'},3)
{ "AAA", "AAa", "AA6", "AAw", "AA#", "AaA", "Aaa", "Aa6", "Aaw", "Aa#", "A6A", "A6a", "A66", "A6w", "A6#", "AwA", "Awa", "Aw6", "Aww", "Aw#", "A#A", "A#a", "A#6", "A#w", "A##", "aAA", "aAa", "aA6", "aAw", "aA#", "aaA", "aaa", "aa6", "aaw", "aa#", "a6A", "a6a", "a66", "a6w", "a6#", "awA", "awa", "aw6", "aww", "aw#", "a#A", "a#a", "a#6", "a#w", "a##", "6AA", "6Aa", "6A6", "6Aw", "6A#", "6aA", "6aa", "6a6", "6aw", "6a#", "66A", "66a", "666", "66w", "66#", "6wA", "6wa", "6w6", "6ww", "6w#", "6#A", "6#a", "6#6", "6#w", "6##", "wAA", "wAa", "wA6", "wAw", "wA#", "waA", "waa", "wa6", "waw", "wa#", "w6A", "w6a", "w66", "w6w", "w6#", "wwA", "wwa", "ww6", "www", "ww#", "w#A", "w#a", "w#6", "w#w", "w##", "#AA", "#Aa", "#A6", "#Aw", "#A#", "#aA", "#aa", "#a6", "#aw", "#a#", "#6A", "#6a", "#66", "#6w", "#6#", "#wA", "#wa", "#w6", "#ww", "#w#", "##A", "##a", "##6", "##w", "###" }
The advantage of using a method with a yield statement is that it is lazy: if you only need five such strings, not all possible strings will be generated first...
Willem Van Onsem, thanks! This was exactly what i've been looking for. But my problem sounds little different. I have to generate all possible strings without repetition of chars from source array. And here is your code, that i modified to do so:
public static IEnumerable<string> GenerateStrings(IEnumerable<char> characters, int length, int count)
{
if (length > 0)
{
foreach (char c in characters)
{
char[] charactersDec = new char[characters.Count()];
Array.Copy(characters.ToArray(), charactersDec, characters.Count());
int index = Array.IndexOf(charactersDec, c);
charactersDec = charactersDec.Where((val, idx) => idx != index).ToArray();
foreach (string suffix in GenerateStrings(charactersDec, length - 1, count++))
{
yield return c + suffix;
}
}
}
else
{
yield return string.Empty;
}
}
I remove current char from array and passed this array to recursive call.
output for a, b, c, d will be:
ab
ba
ac
ca
ad
da
bc
cb
bd
db
cd
dc
please, sorry my english.