[ACCEPTED]-Parse an integer from a string with trailing garbage-parsing
You can use Linq to do this, no Regular 2 Expressions needed:
public static int GetLeadingInt(string input)
{
return Int32.Parse(new string(input.Trim().TakeWhile(c => char.IsDigit(c) || c == '.').ToArray()));
}
This works for all your 1 provided examples:
string[] tests = new string[] {
"1",
" 42 ",
" 3 -.X.-",
" 2 3 4 5"
};
foreach (string test in tests)
{
Console.WriteLine("Result: " + GetLeadingInt(test));
}
foreach (var m in Regex.Matches(" 3 - .x. 4", @"\d+"))
{
Console.WriteLine(m);
}
Updated per comments
Not sure why you don't 3 like regular expressions, so I'll just post 2 what I think is the shortest solution.
To 1 get first int:
Match match = Regex.Match(" 3 - .x. - 4", @"\d+");
if (match.Success)
Console.WriteLine(int.Parse(match.Value));
There's no standard .NET method for doing 10 this - although I wouldn't be surprised 9 to find that VB had something in the Microsoft.VisualBasic 8 assembly (which is shipped with .NET, so 7 it's not an issue to use it even from C#).
Will 6 the result always be non-negative (which 5 would make things easier)?
To be honest, regular 4 expressions are the easiest option here, but...
public static string RemoveCruftFromNumber(string text)
{
int end = 0;
// First move past leading spaces
while (end < text.Length && text[end] == ' ')
{
end++;
}
// Now move past digits
while (end < text.Length && char.IsDigit(text[end]))
{
end++;
}
return text.Substring(0, end);
}
Then 3 you just need to call int.TryParse
on the result of 2 RemoveCruftFromNumber
(don't forget that the integer may be too 1 big to store in an int
).
I like @Donut's approach.
I'd like to add 6 though, that char.IsDigit
and char.IsNumber
also allow for some unicode 5 characters which are digits in other languages 4 and scripts (see here).
If you only want to check 3 for the digits 0 to 9 you could use "0123456789".Contains(c)
.
Three 2 example implementions:
To remove trailing non-digit characters:
var digits = new string(input.Trim().TakeWhile(c =>
("0123456789").Contains(c)
).ToArray());
To remove leading non-digit characters:
var digits = new string(input.Trim().SkipWhile(c =>
!("0123456789").Contains(c)
).ToArray());
To remove all non-digit characters:
var digits = new string(input.Trim().Where(c =>
("0123456789").Contains(c)
).ToArray());
And of course: int.Parse(digits)
or 1 int.TryParse(digits, out output)
string s = " 3 -.X.-".Trim();
string collectedNumber = string.empty;
int i;
for (x = 0; x < s.length; x++)
{
if (int.TryParse(s[x], out i))
collectedNumber += s[x];
else
break; // not a number - that's it - get out.
}
if (int.TryParse(collectedNumber, out i))
Console.WriteLine(i);
else
Console.WriteLine("no number found");
0
This is how I would have done it in Java:
int parseLeadingInt(String input)
{
NumberFormat fmt = NumberFormat.getIntegerInstance();
fmt.setGroupingUsed(false);
return fmt.parse(input, new ParsePosition(0)).intValue();
}
I 3 was hoping something similar would be possible 2 in .NET.
This is the regex-based solution 1 I am currently using:
int? parseLeadingInt(string input)
{
int result = 0;
Match match = Regex.Match(input, "^[ \t]*\\d+");
if (match.Success && int.TryParse(match.Value, out result))
{
return result;
}
return null;
}
This doesn't really answer your question 8 (about a built-in C# method), but you could 7 try chopping off characters at the end of 6 the input string one by one until int.TryParse()
accepts 5 it as a valid number:
for (int p = input.Length; p > 0; p--)
{
int num;
if (int.TryParse(input.Substring(0, p), out num))
return num;
}
throw new Exception("Malformed integer: " + input);
Of course, this will 4 be slow if input
is very long.
ADDENDUM (March 2016)
This could be 3 made faster by chopping off all non-digit/non-space 2 characters on the right before attempting 1 each parse:
for (int p = input.Length; p > 0; p--)
{
char ch;
do
{
ch = input[--p];
} while ((ch < '0' || ch > '9') && ch != ' ' && p > 0);
p++;
int num;
if (int.TryParse(input.Substring(0, p), out num))
return num;
}
throw new Exception("Malformed integer: " + input);
I'm not sure why you would avoid Regex in 4 this situation.
Here's a little hackery 3 that you can adjust to your needs.
" 3 -.X.-".ToCharArray().FindInteger().ToList().ForEach(Console.WriteLine);
public static class CharArrayExtensions
{
public static IEnumerable<char> FindInteger(this IEnumerable<char> array)
{
foreach (var c in array)
{
if(char.IsNumber(c))
yield return c;
}
}
}
EDIT: That's 2 true about the incorrect result (and the 1 maintenance dev :) ).
Here's a revision:
public static int FindFirstInteger(this IEnumerable<char> array)
{
bool foundInteger = false;
var ints = new List<char>();
foreach (var c in array)
{
if(char.IsNumber(c))
{
foundInteger = true;
ints.Add(c);
}
else
{
if(foundInteger)
{
break;
}
}
}
string s = string.Empty;
ints.ForEach(i => s += i.ToString());
return int.Parse(s);
}
private string GetInt(string s)
{
int i = 0;
s = s.Trim();
while (i<s.Length && char.IsDigit(s[i])) i++;
return s.Substring(0, i);
}
0
Might as well add mine too.
string temp = " 3 .x£";
string numbersOnly = String.Empty;
int tempInt;
for (int i = 0; i < temp.Length; i++)
{
if (Int32.TryParse(Convert.ToString(temp[i]), out tempInt))
{
numbersOnly += temp[i];
}
}
Int32.TryParse(numbersOnly, out tempInt);
MessageBox.Show(tempInt.ToString());
The message box 2 is just for testing purposes, just delete 1 it once you verify the method is working.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.