I am reading from a TextBox in C# and I want to make sure that only real positive values are allowed (including integers).
i.e. 1, 23, 23., 23.0, 23.42, etc.
The Regex I am using is:
[0-9]+\\.?[0-9]*
But C# does only let me type numbers and I can never put a period.
Thank you
Code:
private static readonly Regex rgx_onlyPositiveReals = new Regex("[0-9]+\\.?[0-9]*");
private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
e.Handled = !IsSamplingRateAllowed(e.Text);
}
private static bool IsSamplingRateAllowed(string text)
{
if(rgx_onlyPositiveReals.IsMatch(text))
{
if(text.Equals(".") || float.Parse(text) <= 0.0)
{
MessageBox.Show("Sampling Rate has to be positive.", "Wrong Sampling Frequency Error", MessageBoxButton.OK, MessageBoxImage.Error);
return false;
}
return true;
}
return false;
}
From the looks of things this input box is supposed to only contain the number and no other text; in this case I would avoid the regular expression altogether.
Given that you're parsing the regex match result into a float anyway, it might make more sense to try parsing the input as a float directly which has the added benefits of allowing any valid positive float that can be parsed in the first place, it also allows entering the number in any other valid formats supported by float.Parse/float.TryParse e.g. scientific notation "1E5" == 100000f or commas "1,500" == 1500f (depending on the culture) without any additional effort.
private static bool IsSamplingRateAllowed(string text)
{
float number;
return float.TryParse(text, out number) && number >= 0.0f;
}
Unless this data is being used for some external process as a string with additional restrictions on the format (which seems unlikely and is worth including in the question if that is the case), then if it isn't already, I'd recommend separating this input box from any other information and have users enter the number and only the number directly into the box. If you need to collect other information from the user you can add other input boxes and controls as necessary (which can also simplify validation for other pieces of information).
Give this a try
The pattern is ^[0-9]+\.?[0-9]*
In C# you can prefix your string with # which makes it easier to read a regex. It results in the following:
"\\this \\is \\the \\same" == #"\this \is \the \same"
You can simply use the below Regex
^\d*[.]?\d*$
Demo Fiddle
I have string text="camel", and then I want to check if text contains letter "m", so I loop through it and checking it using:
if (text[i].Equals("m"))
but this never returns me true... why?
Since you are comparing a character with a string this won't work.
Here's some more information on String comparisons
In this case you should use
if(text.Contains("m"))
As mentioned by #MattGreer, you're currently comparing a character and a string. This is because of the delimiter you've chosen for your literal, and because text[i] returns a character from a string rather than a substring of that string.
Please note the difference between using string literal delimiters (quote) and character literal delimiters (apostrophe):
if (text[i].Equals('m'))
Also, as others have stated, unless there is some reason you want to iterate through each character, String.Contains() would seemingly serve the intended purpose.
You need to find all occurences of a letter in a text as I understand it:
string text = "camel";
string lookup = "M";
int index = 0;
while ( (index = text.IndexOf(lookup, index, StringComparison.OrdinalIgnoreCase) != -1)
{
// You have found what you looked for at position "index".
}
I don't think that you get it any faster than this.
Good luck with your quest.
The answers has been given to you by Kyle C, so this is how you complete the whole process and I'm gonna use winforms as an example:
private void button1_Click(object sender, EventArgs e)
{
string text = "camel";
if (text.Contains("m") || text.Contains("M"))//also checks for capital M
{
MessageBox.Show("True");
}
}
Miraclessss
Use Contains
You're asking if "camel" is the equivalent of "m" -- which it is not.
"camel" contains "m".
I need to be able to convert user input to [a-z] roman characters ONLY (not case sensitive). So, there are only 26 characters that I am interested in.
However, the user can type in any "form" of those characters that they wish. The Spanish "n", the French "e", and the German "u" can all have accents from the user input (which are removed by the program).
I've gotten pretty close with these two extension methods:
public static string LettersOnly(this string Instring)
{
char[] aChar = Instring.ToCharArray();
int intCount = 0;
string strTemp = "";
for (intCount = 0; intCount <= Instring.Length - 1; intCount++)
{
if (char.IsLetter(aChar[intCount]) )
{
strTemp += aChar[intCount];
}
}
return strTemp;
}
public static string RemoveAccentMarks(this string s)
{
string normalizedString = s.Normalize(NormalizationForm.FormD);
StringBuilder sb = new StringBuilder();
char c;
for (int i = 0; i <= normalizedString.Length - 1; i++)
{
c = normalizedString[i];
if (System.Globalization.CharUnicodeInfo.GetUnicodeCategory(c) != System.Globalization.UnicodeCategory.NonSpacingMark)
{
sb.Append(c);
}
}
return sb.ToString();
}
Here is an example test:
string input = "Àlièñ451";
input = input.LettersOnly().RemoveAccentMarks().ToLower();
console.WriteLine(input);
Result: "alien" (as expected)
This works for 99.9% of the cases. However, a few characters seem to pass all of the checks.
For instance, "ß" (a German double-s, I think). This is considered by .Net to be a letter. This is not considered by the function above to have any accent marks... but it STILL isn't in the range of a-z, like I need it to be. Ideally, I could convert this to a "B" or an "ss" (whichever is appropriate), but I need to convert it to SOMETHING in the range of a-z.
Another example, the dipthong ("æ"). Again, .Net considers this a "letter". The function above doesn't see any accent, but again, it isn't in the roman 26 character alphabet. In this case, I need to convert to the two letters "ae" (I think).
Is there an easy way to convert ANY worldwide input to the closest roman alphabet equivalent? It is expected that this probably won't be a perfectly clean translation, but I need to trust that the inputs at FlipScript.com are ONLY getting the characters a-z... and nothing else.
Any and all help appreciated.
If I were you, I'd create a Dictionary which would contain the mappings from foreign letters to Roman letters. I'd use this for two reasons:
It will make understanding what you want to do easier to someone who is reading your code.
There are a small, finite, number of these special letters so you don't need to worry about maintenance of the data structure.
I'd put the mappings into an xml file then load them into the data structure at run-time. That way, you do not need to modify any code which uses the characters, you only need to specify the mappings themselves.
how do I make a boolean statement to only allow text? I have this code for only allowing the user to input numbers but ca'nt figure out how to do text.
bool Dest = double.TryParse(this.xTripDestinationTextBox.Text, out Miles);
bool MilesGal = double.TryParse(this.xTripMpgTextBox.Text, out Mpg);
bool PriceGal = double.TryParse(this.xTripPricepgTextBox.Text, out Price);
Update: looking at your comment I would advise you to read this article:
User Input Validation in Windows Forms
Original answer: The simplest way, at least if you are using .NET 3.5, is to use LINQ:
bool isAllLetters = s.All(c => char.IsLetter(c));
In older .NET versions you can create a method to do this for you:
bool isAllLetters(string s)
{
foreach (char c in s)
{
if (!char.IsLetter(c))
{
return false;
}
}
return true;
}
You can also use a regular expression. If you want to allow any letter as defined in Unicode then you can use this regular expression:
bool isOnlyLetters = Regex.IsMatch(s, #"^\p{L}+$");
If you want to restrict to A-Z then you can use this:
bool isOnlyLetters = Regex.IsMatch(s, #"^[a-zA-Z]+$");
You can use following code in the KeyPress event:
if (!char.IsLetter(e.KeyChar)) {
e.Handled = true;
}
You can use regular expression, browse here: http://regexlib.com/
You can do one of a few things.
User Regular Expression to check that the string matches your concept of 'Text' only
Write some code that checks each character against a list of valid characters. Or even use char.IsLetter()
Use the MaskedTextBox and set a custom mask to limit input to text only characters
I found hooking up into the text changed event of a textbox and accepting/rejecting the changes an acceptable solution. To "only allow text" is a rather vague definition, but you may as well check if your newly added text (the next char) is a number or not and simply reject all numbers/disallowed characters. This will make users feel they can only enter characters and special characters (like dots, question marks etc.).
private void UTextBox_TextChanged(object sender, EventArgs e)
{
string lastCharacter = this.Text[this.Text.Length-1].ToString();
MatchCollection matches = Regex.Matches(lastCharacter, "[0-9]", RegexOptions.None);
if (matches.Count > 0) //character is a number, reject it.
{
this.Text = Text.Substring(0, Text.Length-1);
}
}
I am trying to use C# to parse CSV. I used regular expressions to find "," and read string if my header counts were equal to my match count.
Now this will not work if I have a value like:
"a",""b","x","y"","c"
then my output is:
'a'
'"b'
'x'
'y"'
'c'
but what I want is:
'a'
'"b","x","y"'
'c'
Is there any regex or any other logic I can use for this ?
CSV, when dealing with things like multi-line, quoted, different delimiters* etc - can get trickier than you might think... perhaps consider a pre-rolled answer? I use this, and it works very well.
*=remember that some locales use [tab] as the C in CSV...
CSV is a great example for code reuse - No matter which one of the csv parsers you choose, don't choose your own. Stop Rolling your own CSV parser
I would use FileHelpers if I were you. Regular Expressions are fine but hard to read, especially if you go back, after a while, for a quick fix.
Just for sake of exercising my mind, quick & dirty working C# procedure:
public static List<string> SplitCSV(string line)
{
if (string.IsNullOrEmpty(line))
throw new ArgumentException();
List<string> result = new List<string>();
bool inQuote = false;
StringBuilder val = new StringBuilder();
// parse line
foreach (var t in line.Split(','))
{
int count = t.Count(c => c == '"');
if (count > 2 && !inQuote)
{
inQuote = true;
val.Append(t);
val.Append(',');
continue;
}
if (count > 2 && inQuote)
{
inQuote = false;
val.Append(t);
result.Add(val.ToString());
continue;
}
if (count == 2 && !inQuote)
{
result.Add(t);
continue;
}
if (count == 2 && inQuote)
{
val.Append(t);
val.Append(',');
continue;
}
}
// remove quotation
for (int i = 0; i < result.Count; i++)
{
string t = result[i];
result[i] = t.Substring(1, t.Length - 2);
}
return result;
}
There's an oft quoted saying:
Some people, when confronted with a
problem, think "I know, I'll use
regular expressions." Now they have
two problems. (Jamie Zawinski)
Given that there's no official standard for CSV files (instead there are a large number of slightly incompatible styles), you need to make sure that what you implement suits the files you will be receiving. No point in implementing anything fancier than what you need - and I'm pretty sure you don't need Regular Expressions.
Here's my stab at a simple method to extract the terms - basically, it loops through the line looking for commas, keeping track of whether the current index is within a string or not:
public IEnumerable<string> SplitCSV(string line)
{
int index = 0;
int start = 0;
bool inString = false;
foreach (char c in line)
{
switch (c)
{
case '"':
inString = !inString;
break;
case ',':
if (!inString)
{
yield return line.Substring(start, index - start);
start = index + 1;
}
break;
}
index++;
}
if (start < index)
yield return line.Substring(start, index - start);
}
Standard caveat - untested code, there may be off-by-one errors.
Limitations
The quotes around a value aren't removed automatically.
To do this, add a check just before the yield return statement near the end.
Single quotes aren't supported in the same way as double quotes
You could add a separate boolean inSingleQuotedString, renaming the existing boolean to inDoubleQuotedString and treating both the same way. (You can't make the existing boolean do double work because you need the string to end with the same quote that started it.)
Whitespace isn't automatically removed
Some tools introduce whitespace around the commas in CSV files to "pretty" the file; it then becomes difficult to tell intentional whitespace from formatting whitespace.
In order to have a parseable CSV file, any double quotes inside a value need to be properly escaped somehow. The two standard ways to do this are by representing a double quote either as two double quotes back to back, or a backslash double quote. That is one of the following two forms:
""
\"
In the second form your initial string would look like this:
"a","\"b\",\"x\",\"y\"","c"
If your input string is not formatted against some rigorous format like this then you have very little chance of successfully parsing it in an automated environment.
If all your values are guaranteed to be in quotes, look for values, not for commas:
("".*?""|"[^"]*")
This takes advantage of the fact that "the earliest longest match wins" - it looks for double quoted values first, and with a lower priority for normal quoted values.
If you don't want the enclosing quote to be part of the match, use:
"(".*?"|[^"]*)"
and go for the value in match group 1.
As I said: Prerequisite for this to work is well-formed input with guaranteed quotes or double quotes around each value. Empty values must be quoted as well! A nice side-effect is that it does not care for the separator char. Commas, TABs, semi-colons, spaces, you name it. All will work.
FileHelpers supports multiline fields.
You could parse files like these:
a,"line 1
line 2
line 3"
b,"line 1
line 2
line 3"
Here is the datatype declaration:
[DelimitedRecord(",")]
public class MyRecord
{
public string field1;
[FieldQuoted('"', QuoteMode.OptionalForRead, MultilineMode.AllowForRead)]
public string field2;
}
Here is the usage:
static void Main()
{
FileHelperEngine engine = new FileHelperEngine(typeof(MyRecord));
MyRecord[] res = engine.ReadFile("file.csv");
}
Try CsvHelper (a library I maintain) or FastCsvReader. Both work well. CsvHelper does writing also. Like everyone else has been saying, don't roll your own. :P
FileHelpers for .Net is your friend.
See the link "Regex fun with CSV" at:
http://snippets.dzone.com/posts/show/4430
The Lumenworks CSV parser (open source, free but needs a codeproject login) is by far the best one I've used. It'll save you having to write the regex and is intuitive to use.
Well, I'm no regex wiz, but I'm certain they have an answer for this.
Procedurally it's going through letter by letter. Set a variable, say dontMatch, to FALSE.
Each time you run into a quote toggle dontMatch.
each time you run into a comma, check dontMatch. If it's TRUE, ignore the comma. If it's FALSE, split at the comma.
This works for the example you give, but the logic you use for quotation marks is fundamentally faulty - you must escape them or use another delimiter (single quotes, for instance) to set major quotations apart from minor quotations.
For instance,
"a", ""b", ""c", "d"", "e""
will yield bad results.
This can be fixed with another patch. Rather than simply keeping a true false you have to match quotes.
To match quotes you have to know what was last seen, which gets into pretty deep parsing territory. You'll probably, at that point, want to make sure your language is designed well, and if it is you can use a compiler tool to create a parser for you.
-Adam
I have just try your regular expression in my code..its work fine for formated text with quote ...
but wondering if we can parse below value by Regex..
"First_Bat7679",""NAME","ENAME","FILE"","","","From: "DDD,_Ala%as"#sib.com"
I am looking for result as:
'First_Bat7679'
'"NAME","ENAME","FILE"'
''
''
'From: "DDD,_Ala%as"#sib.com'
Thanx