String checking with Regex - c#

I have a textBox in my program that contains a string that has to meet a few requirements. I'm asking this question to figure out the best way to meet these requirements.
This string can't be NullOrEmpty and it must be completely composed of integers. The string can also contain spaces, which is my sticking point because spaces aren't integers.
This is what I'm working with (I'm aware that it may be a bit redundant at the moment):
//I test the string whenever the textBox loses focus
private void messageBox_LostFocus(object sender, RoutedEventArgs e)
{
if (string.IsNullOrEmpty(TextBox.Text))
ButtonEnabled = true;
else if (Regex.IsMatch(TextBox.Text, #"^\d+$") == false)
{
//I think my problem is here, the second part of the if statement doesn't
//really seem to work because it accepts characters if there is a space
//in the string.
if (TextBox.Text.Contains(" ") && !Regex.IsMatch(TextBox.Text, #"^\d+$"))
ButtonEnabled = true;
else
{
MessageBox.Show("Illegal character in list.", "Warning!", MessageBoxButton.OK, MessageBoxImage.Warning);
ButtonEnabled = false;
}
}
else
ButtonEnabled = true;
}
I got the Regex solution from this answer.
Question: How do I make it so that this textBox only accepts values like these:
"345 78" or "456"?

The regular expression seems simple enough. It could be something along the line of (with the specified constraints):
^([\s\d]+)?$
In your LostFocus handler, you could use something like this:
ButtonEnabled = Regex.IsMatch(TextBox.Text, #"^([\s\d]+)?$");
The button will be enabled if:
It's an empty string
It contains only digits and spaces
If you want a regular expression that will extract the numbers as well, you could change the pattern to:
^(\s*(?<number>\d+)\s*)*$
And use the number capture group.
Note that the first pattern will match strings that are composed of spaces only.

Related

Leave Event / Regex Implemented (Query about ignoring Textboxes if empty / null)

I'm new to C#, and finding some difficulties when trying to implement the 'ignore regex function when textbox is empty'.
As shown below, within Leave event I have made it so that the data submitted in the name textbox is of alphabetic characters, however, upon testing, the application still warns me that the textbox requires alphabetic characters even if the textbox is EMPTY / NULL.
What I would like is to maintain the same regex function, but I want the application to NOT warn me about the requirements if textboxes are left empty.
Many thanks in advance.
private void txtName_Leave(object sender, EventArgs e)
{
if (!System.Text.RegularExpressions.Regex.IsMatch(this.txtName.Text, "^[a-zA-Z ]"))
{
MessageBox.Show("This textbox accepts only alphabetical characters.", "Warning");
this.txtName.ResetText();
}
else if (txtName.Text.Trim() == string.Empty)
{
return;
}
}
What you need to use is ^[a-zA-Z]*$
^ Beginning of string
[a-zA-Z]* with the addition of the * it represents 0+ Alpha
characters
$ end of string

Format String remove or substring from Serial port without exception, how?

I'm using this piece of code to receive the weight from scale.
To the part with .ToString all is good, but when I call .Remove(9, 5) it throws me an ArgumentOutOfRangeException. Why? I'm not out of range.
private delegate void Closure();
private void sport_DataReceived2(object sender, SerialDataReceivedEventArgs serialDataReceivedEventArgs)
{
if (InvokeRequired) //<-- Makes sure the function is invoked to work properly in the UI-Thread
BeginInvoke(new Closure(() => { sport_DataReceived2(sender, serialDataReceivedEventArgs); })); //<-- Function invokes itself
else
{
while (sport.BytesToRead > 0) //<-- repeats until the In-Buffer is empty
{
textBox1.Text += string.Format("{0:X2} ", sport.ReadExisting().ToString().Remove(9, 5));
//<-- bytewise adds inbuffer to textbox
}
}
}
I also tried with a substring but still got an exception.
The whole received string is: "\n00.394KG\r\nS00\r"
Because of this, I have to use remove or substring, to get what i need exactly - "00.394KG" part only.
If those are newline and carriage return characters then you can use String.Split
var result = "\n00.394KG\r\nS00\r".Split()[1];
That will create an array of size 5 where the second item is the one you want, thus the [1]. This will make sure you don't have to worry about the length of the value. Additionally you should add a check to make sure the array has at least two values if you ever get input that doesn't have at least 1 whitespace character in it.
However if your string truly is "\n00.394KG\r\nS00\r" then .Remove(9,5) would not throw the exception you have indicated. Instead you should get "\n00.394KG\r". So, I'm guessing you actually have a shorter string and thus the need to split.
Generally speaking using Remove/Substring or any other size dependant method on a string which is read during runtime is a bad idea, as you usually don't control the behaviour of your string source, and if that string differs only slightly from what you expect at compile time you get in trouble.
Your code is a perfect example, if you do a test like this:
Console.WriteLine("\n00.394KG\r\nS00\r".Remove(9, 5));
Then you can see that your call of remove is not the problem, but the string you are trying to work on differs from what you expected. Probably it is a shorter string as this would produce a ArgumentOutOfRangeException.
A safe bet is using regular expressions on any received string and only continue working if the string matches your expectations coded into the regular expression.
var recvString = sport.ReadExisting().ToString();
Regex readKGRx = new Regex(#"\n(\d{2}\.\d{3}KG)\r\nS00\r");
var readKGMatch = readKGRx.Match(recvString);
if (readKGMatch.Success)
textBox1.Text += string.Format("{0:X2}", readKGMatch.Groups[1].Value);
else
MessageBox.Show(string.Format("Bad string received: {0}", recvString));
If you don't know how to use regular expressions you should at least store your receive string as a variable and make some checks on it before cutting out what you expect to be there.
string expectedFormat = "\n00.394KG\r\nS00\r";
var recvString = sport.ReadExisting().ToString();
bool formatCheckOK = true;
formatCheckOK = formatCheckOK && recvString.Length == expectedFormat.Length;
formatCheckOK = formatCheckOK && recvString[0] == expectedFormat[0];
formatCheckOK = formatCheckOK && recvString.IndexOf("KG") == expectedFormat.IndexOf("KG");
//more checks to be sure...
if (formatCheckOK)
textBox1.Text += string.Format("{0:X2}", recvString.Substring(1,8));
else
MessageBox.Show(string.Format("Bad string received: {0}", recvString));
Try
sport.ReadExisting().ToString().Substring(2, 8)
It starts at the 3rd position and goes for 8 characters, so it should return the string you want.
I think here it not a best chioce in using .remove
sport.ReadExisting().ToString().SubString(9, 5)
Try this instead
Go for a regex solution..
var x = "\n00.394KG\r\nS00\r";
var match = Regex.Match(#"(?<serial>\d+\.\d+\w+)", x);
if (!match.Success) throw new FormatException(); // invalid format..
var serial = match.Groups["serial"].Value;

What would the regex be to match a string whether it has 1 or less apostrophes at any number of different indexes or none at all?

I really don't know Regular Expression syntax that well, but I am using a simple highlighting plug-in for jQuery, and I need it to select a word whether it has 1 or less apostrophes at any number of different indexes or none at all.
For example, say I have a string: Tods (note that this string could be anything).
I need a regular expression that could still select: Tod's, To'ds, T'ods, or 'Tods. (Note that I did not include an apostrophe at the last index, as this is not necessary, although, it probably wouldn't hurt anything).
So far I have this code in jQuery...:
$("input.highlightTerm").each(function () {
$(".resultValue").highlight($(this).val());
});
...where $(this).val() is the string that will be highlighted.
It is also possible for me to do this in C#, as I populate the hidden input fields that this jQuery code picks up ($("input.highlightTerm")) on server-side, using C#.
Simple C# Razor Syntax:
for (var n = 0; n < searchTermsArray.Length; n++)
{
<input class="highlightTerm" type="hidden" value="#searchTermsArray[n]" />
}
What is the regular expression syntax I need to get this done?
More Examples of What Should and Shouldn't Match:
T'o'd's [Should Match]
Tod's [Should Match]
'Tods' [Should Match]
'Tods OR Tods' [Really doesn't matter, because of how the plug-in works, but I guess Should Match, is preferred]
Tod''s [Shouldn't Match]
''Tods [Shouldn't Match]
--Pretty much I only want matches if there is 1 or less apostrophes among any number of different indexes within the string.
First make sure the string has length and that there are no double-apostrophes (this rules out triples and higher as well). Then test the string for containing only word characters or apostrophes.
var re = /^[\w']*$/;
function checkForApostrophe(str) {
if ( !str.length ) { return; }
if ( str.indexOf("''") !== -1 ) { return; }
if ( str.charAt(str.length-1) === "'" ) { return; }
return re.test(str);
}
Replace '\w' in the regex with [a-zA-Z], possibly including [0-9] depending on your requirements.
The question is a little difficult to understand exactly what you want, so if this isn't quite right please comment.
I think after reading the comments on the other answers, I've figured out what it is you're going for. You don't need a single regex that can do this for any possible input, you already have input, and you need to build a regex that matches it and its variations. What you need to do is this.
var re = new RegExp("'?" + "tods".split("").join("'?") + "'?")
This will create a regex that matches in the way you're describing, provided it's OK that it also matches the original string.
In this case, the above line builds this regex:
/'?t'?o'?d'?s'?/
This may still not be 100% right. You know, since I don't have that highlight function around myself to play with, but I think it should get you on the right track.
I think you have to do something like this !
function checkForApostrophe(str) {
var length = str.length;
if (length != 0)
{
// Makes sure string contains only Alphabets, numbers and apostrophe : Nothing else
if (str.matches("[a-zA-Z0-9']*")) {
// makes sure there is only one or zero apostrophe
if ((str.indexOf("'") != -1) && (str.indexOf("'") == str.lastIndexOf("'"))) {
// Makes sure there is no apostrophe stranded at the end
if (str.lastIndexOf("'") == length - 1)
return false
else
return true;
}
else {
return false;
}
}
else {
return false;
}
}
}

SIP: Key.Shift not getting detected

I am trying to create a text box which accepts only alphabets and numbers, and discards all the special characters. I need this for entering a valid file name, without extension.
I am using the following code:
private void txtFName_KeyDown(object sender, KeyEventArgs e)
{
if (!(((e.Key >= Key.A) && (e.Key <= Key.Z)) || ((e.Key >= Key.D0) && (e.Key <= Key.D9)) || (e.Key == Key.Shift) || (e.Key == Key.Back)))
{
e.Handled = true;
MessageBox.Show("No Special Characters are Allowed!");
}
}
Unfortunately the "KeyPress" event is not there, so I figured out that this is the best way to achieve what I am doing.
The problem I am facing is:
As you can see in the code above, I have taken care of the "Shift" key press, but when I press the "Shift" key on the SIP, the "No Special Characters are Allowed" Message box pops up 3 times before I can key in an upper case alphabet!!! So this essentially prevents me from entering any Upper case characters.
Worse still, it is accepting all the characters !##$%^&*(). Probably because it is detecting these as numbers from 0-9. It looks that the key codes are being returned the same for 2 and #, 3 and # and so on. This is very strange behavior! And I can not even use the underscore key with the above technique.
Such behavior is obviously not acceptable in a professional App.
How can I create a text box which accepts only alphabets, numbers and underscore, and discards all other characters?
Also, is there a problem with the "Shift" key not getting detected?
If I understand your query, you want to validate your text box.
I would use regular expressions to do this:
using System.Text.RegularExpressions;
// Add chars which you don't want the user to be able to enter
private Regex regularExpression = new Regex(#"!##$%^&*().", RegexOptions.IgnoreCase);
// Your text changed event handler
private void txtInput_TextChanged(object sender, TextChangedEventArgs e)
{
// Replace the forbidden char with ""
txtInput.Text = regularExpression.Replace(txtInput.Text, "");
txtInput.SelectionStart = txtInput.Text.Length;
}
Hopefully this will work for you.

How to let the textbox drop strings started with an Arabic character (semi each other) as it does in capital and small characters in default language?

In textbox autocomplete properties when i entered a character like 'm' it dropped all strings start with 'm' or 'M' but when i write a character 'أ' (this is an Arabic character) it dropped only string start with 'أ' , I want when i typed 'أ' or 'ا' or 'إ' or 'آ' it drop all strings start with any character from those not the typed character only , in C# windows application I'm not using ASP.net
Any suggestions????
I am quite surprised to see that neither the text box control nor the auto complete string collection has a way to specify what defines string equality for the auto-complete mechanism. The only way I can think of to get the behavior that you want would be to create your own auto-complete mechanism.
I have done this several times in the past, before the functionality was supplied by the framework, and it is not difficult.
Just use an editable ComboBox instead of a TextBox, and handle the TextChanged event to create the autocompletions.
Here is some untried pseudocode of the procedure:
bool textChangedProgramatically = false;
List<string> myStrings; // The list of items that can appear in the auto-complete.
private static myComboBox_TextChanged(object sender, EventArgs args)
{
if (textChangedProgramatically)
return;
string searchText = myComboBox.Text;
// Use appropriate culturally-sensative string StartsWith comparisons
List<string> matchingItems = GetMatchingStrings(searchText, myStrings);
string firstMatch;
if (matchingItems.Length > 0)
firstMatch = matchingItems[0];
else
firstMatch = string.Empty;
myComboBox.Items.Clear;
myComboBox.Items.AddRange(matchingItems);
string fulltext = searchText;
if (firstMatch.Length > fullText.Length)
{
fullText = fullText + firstMatch.Substring(fullText.Length);
textChangeProgramatically = true;
myComboBox.Text = fullText;
myComboBox.SelectionStart = searchText.Length;
myComboBox.SelectionLength = fullText.Length - searchText.Length;
textChangeProgramatically = false;
}
}
The trick is to get the right matching behavior in GetMatchingStrings. You may want to use string compatibility normalization to get the Arabic characters into non-presentation forms before doing the comparison, but I expect the right SubString overload might handle all of these cases for you.

Categories