I have a text box with numeric values and thousand separators etc. For ex: 12,111,111,111.804
The max length is 14 characters.
The problem is that when I edit that text box it counts the special characters and not allowing to enter the new value to the box. how do I simply eliminate the special characters form the max length.
Edit:
Sorry guys was out of the town . Lets say we take the following no : 12,312,312,312,312 . so there are 14 digits. and i erase last 3. so it will be 12,312,312,312, . now i want to add another 3 digits for the once i deleted. I'm using .net 2.0. this is a windows application.
Add a keyPress event and include the below code.
Replace >= 5 with the max size of your text box not including the decimals or commas.
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
if(Char.IsNumber(e.KeyChar))
if(textBox1.Text.Replace(",", "").Replace(".", "").Length >= 5)
e.Handled = true;
}
You can try and use following jquery code by customizing it as your need:
$(document).ready(function ()
{
$('#textbox1').keyup(function (event)
{
var currentValue = $(this).val();
var length = currentValue.length;
var commaCount = 0;
// Get Comma Count
for (i = 0; i < this.value.length; i++)
{
if (this.value.charAt(i) == ',')
commaCount++;
}
if (length > 3)
{
// remove comma's to work out the number of digits.
length = length - commaCount;
}
if (length<=14)
{
$(this).val(currentValue);
}
else
{
alert("validation fails! length can not exceed 14 digits");
}
});
});
You can use Linq to count the digits in the string
int count = textBox1.Text.Count(char.IsNumber);
So you could use like
if (textBox1.Text.Count(char.IsNumber) <= 14)
{
//valid
}
Related
Doing practice with a note app, I have a text file that contain notes by line numbering like this:
1) First note
2) Second note
n) n note
Anticipating that a user may remove a note from the list, I want to avoid having these notes un-organized, so the lines numbers would be re-organized automatically.
int NumérotationFromTheUserTextFile, NumérotationInOrder = 1;
string[] Strings = File.ReadAllLines(logPath);
for(int i=0; i<Strings.Length; i++)
{
using (TextReader reader = File.OpenText(logPath))
{
string text = File.ReadLines(logPath).Skip(i).Take(1).First();
string[] bits = text.Split(')');
if(int.TryParse(bits[0], out int x))
{
NumérotationFromTheUserTextFile = x;
if (NumérotationFromTheUserTextFile != NumérotationInOrder)
{
Strings[i] = Strings[i].Replace(NumérotationFromTheUserTextFile.ToString(CultureInfo.InvariantCulture), NumérotationInOrder.ToString(CultureInfo.InvariantCulture));
}
NumérotationInOrder++;
}
}
}
File.WriteAllLines(logPath, Strings);
The code above does the job EXCEPT it does affect/change all other similar numbers at the same line. and I want it to stop editing at each line by this symbol ')'.
Any suggestion on how to improve it would be appreciated.
As I mentioned in the comments, it seems like a design flaw to store the line number with the line itself. That's something you can determine at runtime when you load the note, and you can display them in your UI without writing them to the file. Since it's obvious that the user has access to modify the file outside of your application, the fewer "rules" you have about the contents of each line the better.
However, if you need to store '#) at the start of each line, then we need to validate a couple of things:
If the line does not contain a ')' character, add #) to the beginning of the line
If the line doesn't start with numeric text, add #) to the beginning of the line
If the number before the ')' character is not correct, modify it.
Here's one way to do it:
public static void ReNumberLines(string filePath)
{
if (!File.Exists(filePath)) throw new FileNotFoundException(nameof(filePath));
var lines = File.ReadAllLines(filePath);
for (int i = 0; i < lines.Length; i++)
{
var num = i + 1;
var parts = lines[i].Split(new[] {')'}, 2); // Split on the first ')'
// If there was no ')' character, add a line number to this line
if (parts.Length == 1)
{
lines[i] = $"{num}) {parts[0].Trim()}";
continue;
}
// Try to determine if we need to modify the beginning of the line.
// If it starts with non-numeric characters, add '#)'
// Otherwise if the number doesn't match, replace it with the correct #
int number;
if (int.TryParse(parts[0].Trim(), out number))
{
// There was a number before the ')', so if it matches we can continue
if (number == num) continue;
// Otherwise replace it with the correct number
lines[i] = $"{num}) {parts[1].Trim()}";
}
else
{
// The characters before the ')' are not numeric, so we have to assume that
// user content is here and prefix this line with the correct number and ')'
lines[i] = $"{num}) {parts[0]}){parts[1]}";
}
}
File.WriteAllLines(filePath, lines);
}
I have hit a snag in some data parsing because the title line of what I am parsing is somewhat complex. It has the year, the title, and the edition, but not always in that order. the year and the edition can be converted to ints but the rest cannot be. how could I split the year from the rest of the line to be parsed to an int if I don't know where it would be in the line every time?
example data sets:
2016 Super special regular season, 01 fifteenth tossup
Math problems galore 2013 Round 02 directed problems
FooBar the amazing game part 1 0f 2 round 03 problems 2015
I know that I can't just test the whole line to see if a character is a number, because there are multiple numbers. Nor can I do something like IndexOf because of not knowing the dates ahead of time.
To get all numbers from string use the regex.Matches() method to get
all matches from the regex
/* \d+ Is used to find integers */
Regex regex = new Regex(#"\d+");
// Loop thrue all matches
foreach (Match match in regex.Matches("2016 Super special regular season, 01 fifteenth tossup"))
{
Console.WriteLine(match.Value); /* Test output */
int i = Convert.ToInt32(match.Value); /* Convert To Int and do something with it */
}
============ output ===========
2016
01
/* Use this \d{4} to return the 4 character from current match from \d*/
/* (Example) => 12564568 => (output) : 1256 and 4568 */
/* (Notice!!) If you use \d{4} and there are only 2 numbers found by \d
It has no result. */
Or in one line to get the result value from the first occurring number:
string resultString = Regex.Match(subjectString /*string to test */, #"\d+").Value;
Use Regex :
string pattern_Year = #"\(\d{4}\)";
string pattern_Edition = #"\(\d{2}\)";
string search = "2016 Super special regular season, 01 fifteenth tossup";
var year = Regex.Matches(search, pattern_Year );
var edition = Regex.Matches(search, pattern_Edition );
if(year.Count > 0)
Console.WriteLine(year[0].Value);
if(edition.Count > 0)
Console.WriteLine(edition [0].Value);
var line = "FooBar the amazing game part 1 0f 2 round 03 problems 2015";
var numbers = line.Split(' ').Where(word => word.All(char.IsDigit)).Select(int.Parse).ToList();
Now you have the ints 1, 2, 3, 2015.
How you find out what the year is is up to you. Maybe check which is between 1900 and 2017?
Something like this:
static int GetYearFromTextLine(string s)
{
string [] words = s.Split(' ');
foreach (string w in words)
{
int number = 0;
if (int.TryParse(w, out number))
{
// assume the first number found over "1900" must be a year
// you can modify this test yourself
if (number >= 1900)
{
return number;
}
}
}
return 0;
}
static void Main(string[] args)
{
Console.WriteLine(GetYearFromTextLine("Math problems galore 2013 Round 02 directed problems"));
}
Try this, should work
string strValue = "abc123def456";
char[] charArr = strValue.ToCharrArray();
List<int> intList = new List<int>();
for(int i =0; i < charArr.Length; i++)
{
string tmpInt ="";
if(char.IsDigit(charArr[i]))
{
tmpInt += charArr[i];
while((i < charArr.Lenght -1 ) && char.IsDigit([i + 1)
{
tmpInt += charArr[i+1];
i++;
}
}
if(tmpInt != "")
intList.Add(int.Parse(tmpInt));
}
Advantage of this script is, does not matter where digits located in the string and not depended on split or any pattern.
I have already looked at similar questions here but it did not help.
I am using windows forms. I have button1 and textbox1.
I am trying to replace (or delete) the selected text in textBox1 and enter new letter (letter A) in place of it.
The code works well with random mixed numbers and letters
for example:
385F1 select 8 and then result = 3A5F1 (8 replaced by A)
H74S31B select 4S and then the result is = H7A31B
KQ5689 select Q5689 and then the result is KA
So it works well, but when I select a number or a letter from a string which consists of same numbers or letters then it does not work, for example:
666777222333 select any 7 then the result = 666AAA222333 (not
working)
9992244GG select any 9 then the result = AAA2244GG (not working)
QQQHHHUUU select any Q then the result = AAAHHHUUU (not working)
QQQHHHUUU select any QH then the result = QQAHHUUU(it works when
different letters selected)
4433366 select 333 then the result = 44A66 (it works when all same
numbers is selected)
Hope I explained it well. I don't know what causes this behavior. please help. Thank you
public partial class Form1 : Form
{
int TxTindex;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ActiveControl = textBox1;
textBox1.Focus();
}
private void button1_Click(object sender, EventArgs e)
{
textBox1.Focus();
if (textBox1.SelectedText.Length > 0) // to check if any text selected
{
TxTindex = textBox1.SelectionStart; // save the caret position
textBox1.Text = textBox1.Text.Replace(textBox1.Text.Substring(textBox1.SelectionStart, textBox1.SelectionLength),"A");
textBox1.SelectionStart = TxTindex + 1; // place the caret after the inserted string
}
else
{
return;
}
}
}
Your problem is here :
textBox1.Text = textBox1.Text.Replace(textBox1.Text.Substring(textBox1.SelectionStart, textBox1.SelectionLength),"A");
The Substring function returns string. In your example (666777222333 select any 7 then the result = 666AAA222333 (not working)), it returns "7". But Text.Replace will replace all occurrences of 7. That is not what you want. What you can do is, instead of using string.Replace function, use string.Remove and string.Insert
textBox1.Text = textBox1.Text.Remove(textBox1.SelectionStart, textBox1.SelectionLength).Insert(textBox1.SelectionStart, "A");
But this might not be very efficient for large strings. A StringBuilder would be better.
The problem is caused by the usage of string.Replace function.
What you are trying to accomplish can be done simply by
if (textBox1.SelectionLength > 0)
textBox1.SelectedText = "A";
There is no need to save/set selection start.
I have these data files comming in on a server that i need to split into [date time] and [value]. Most of them are delimited a single time between time and value and between date and time is a space. I already have a program processing the data with a simple split(char[]) but now found data where the delimiter is a space and i am wondering how to tackle this best.
So most files i encountered look like this:
18-06-2014 12:00:00|220.6
The delimiters vary, but i tackled that with a char[]. But today i ran into a problem on this format:
18-06-2014 12:00:00 220.6
This complicates things a little. The easy solution would be to just add a space to my split characters and when i find 3 splits combine the first two before processing?
I'm looking for a 2nd opining on this matter. Also the time format can change to something like d/m/yy and the amount of lines can run into the millions so i would like to keep it as efficient as possible.
Yes I believe the most efficient solution is to add space as a delimiter and then just combine the first two if you get three. That is going to be be more efficient than regex.
You've got a string 18-06-2014 12:00:00 220.6 where first 19 characters is a date, one character is a separation symbol and other characters is a value. So:
var test = "18-06-2014 12:00:00|220.6";
var dateString = test.Remove(19);
var val = test.Substring(20);
Added normalization:
static void Main(string[] args) {
var test = "18-06-2014 12:00:00|220.6";
var test2 = "18-6-14 12:00:00|220.6";
var test3 = "8-06-14 12:00:00|220.6";
Console.WriteLine(test);
Console.WriteLine(TryNormalizeImportValue(test));
Console.WriteLine(test2);
Console.WriteLine(TryNormalizeImportValue(test2));
Console.WriteLine(test3);
Console.WriteLine(TryNormalizeImportValue(test3));
}
private static string TryNormalizeImportValue(string value) {
var valueSplittedByDateSeparator = value.Split('-');
if (valueSplittedByDateSeparator.Length < 3) throw new InvalidDataException();
var normalizedDay = NormalizeImportDayValue(valueSplittedByDateSeparator[0]);
var normalizedMonth = NormalizeImportMonthValue(valueSplittedByDateSeparator[1]);
var valueYearPartSplittedByDateTimeSeparator = valueSplittedByDateSeparator[2].Split(' ');
if (valueYearPartSplittedByDateTimeSeparator.Length < 2) throw new InvalidDataException();
var normalizedYear = NormalizeImportYearValue(valueYearPartSplittedByDateTimeSeparator[0]);
var valueTimeAndValuePart = valueYearPartSplittedByDateTimeSeparator[1];
return string.Concat(normalizedDay, '-', normalizedMonth, '-', normalizedYear, ' ', valueTimeAndValuePart);
}
private static string NormalizeImportDayValue(string value) {
return value.Length == 2 ? value : "0" + value;
}
private static string NormalizeImportMonthValue(string value) {
return value.Length == 2 ? value : "0" + value;
}
private static string NormalizeImportYearValue(string value) {
return value.Length == 4 ? value : DateTime.Now.Year.ToString(CultureInfo.InvariantCulture).Remove(2) + value;
}
Well you can use this one to get the date and the value.
(((0[1-9]|[12][0-9]|3[01])-(0[1-9]|1[012])-(19|20)\d\d)\s((\d{2}:?){3})|(\d+\.?\d+))
This will give you 2 matches
1º 18-06-2014 12:00:00
2º 220.6
Example:
http://regexr.com/391d3
This regex matches both kinds of strings, capturing the two tokens to Groups 1 and 2.
Note that we are not using \d because in .NET it can match any Unicode digits such as Thai...
The key is in the [ |] character class, which specifies your two allowable delimiters
Here is the regex:
^([0-9]{2}-[0-9]{2}-[0-9]{4} (?:[0-9]{2}:){2}[0-9]{2})[ |]([0-9]{3}\.[0-9])$
In the demo, please pay attention to the capture Groups in the right pane.
Here is how to retrieve the values:
var myRegex = new Regex(#"^([0-9]{2}-[0-9]{2}-[0-9]{4} (?:[0-9]{2}:){2}[0-9]{2})[ |]([0-9]{3}\.[0-9])$", RegexOptions.IgnoreCase);
string mydate = myRegex.Match(s1).Groups[1].Value;
Console.WriteLine(mydate);
string myvalue = myRegex.Match(s1).Groups[1].Value;
Console.WriteLine(myvalue);
Please let me know if you have questions
Given the provided format I'd use something like
char delimiter = ' '; //or whatever the delimiter for the specific file is, this can be set in a previous step
int index = line.LastIndexOf(delimiter);
var date = line.Remove(index);
var value = line.Substring(++index);
If there are that many lines and efficiency matters, you could obtain the delimiter once on the first line, by looping back from the end and find the first index that is not a digit or dot (or comma if the value can contain those) to determine the delimiter, and then use something such as the above.
If each line can contain a different delimiter, you could always track back to the first not value char as described above and still maintain adequate performance.
Edit: for completeness sake, to find the delimiter, you could perform the following once per file (provided that the delimiter stays consistent within the file)
char delimiter = '\0';
for (int i = line.Length - 1; i >= 0; i--)
{
var c= line[i];
if (!char.IsDigit(c) && c != '.')
{
delimiter = c;
break;
}
}
I have a multiline text box called txtOutput that receives messages from the serial port. Each new message is a new line and represents a number from 1 to a maximum of 4 digits.
The method used to add the data in the multiline textbox is an append.
I have no problems with the above feature, it is working fine.
I would like to take the last message from the txtOutput and show it in textBox2 if the number is less than 1000, and in textbox3 if it is not. Then both text boxes would be updated.
I would appreciate if someone can give in an example especially in how to get the last message from the multiline textbox to a variable and how to update the textboxes if there is a new value.
You should save the last message (from the serial port) in a variable such as lastSerialMesssage. You can then convert this value to an integer and use a conditional statement to check if the value is smaller than 1000, if it is, set TextBox3 to the last serial message value, else set the value to TextBox2.
string lastSerialMessage = SerialPortMessage;
int lastMessageValue;
Int32.TryParse(lastSerialMessage, out lastMessageValue);
if (lastMessageValue < 1000)
{
TextBox3.Text = lastSerialMessage;
} else {
TextBox2.Text = lastSerialmessage;
}
http://msdn.microsoft.com/en-us/library/f02979c7.aspx
Thanks to all for the suggestions but as I mentioned in my comments, the suggested methods did not work because the content of the string was not accurate and I ended up receiving in the textBox 2 and 3 only part of the data and not always. I have solved the problem (thanks to other advices) using RegEx in this way:
if (txtOutput.Text.Length > 0)
{
MatchCollection mc = Regex.Matches(txtOutput.Text, #"(\+|-)?\d+");
if (mc.Count > 0)
{
long value = long.Parse(mc[mc.Count - 1].Value);
if (value < 1000)
{
textBox2.Text = value.ToString();
}
else
{
value = value - 1000;
textBox3.Text = value.ToString();
}
}
}
this is working fine and no piece of information are lost.Thanks again for your advices.