从具有尾随垃圾的字符串中解析整数

时间:2009-10-13 16:13:09

标签: c# .net parsing

我需要解析出现在字符串开头的十进制整数。

十进制数后面可能有尾随垃圾。这需要被忽略(即使它包含其他数字。)

e.g。

"1" => 1
" 42 " => 42
" 3 -.X.-" => 3
" 2 3 4 5" => 2

.NET框架中是否有内置方法来执行此操作?

int.TryParse()不合适。它允许尾随空格但不允许其他尾随字符。

实现这一点很容易,但如果存在,我宁愿使用标准方法。

10 个答案:

答案 0 :(得分:22)

您可以使用Linq执行此操作,不需要正则表达式:

public static int GetLeadingInt(string input)
{
   return Int32.Parse(new string(input.Trim().TakeWhile(c => char.IsDigit(c) || c == '.').ToArray()));
}

这适用于您提供的所有示例:

string[] tests = new string[] {
   "1",
   " 42 ",
   " 3 -.X.-",
   " 2 3 4 5"
};

foreach (string test in tests)
{
   Console.WriteLine("Result: " + GetLeadingInt(test));
}

答案 1 :(得分:17)

foreach (var m in Regex.Matches(" 3 - .x. 4", @"\d+"))
{
    Console.WriteLine(m);
}

每条评论更新

不确定为什么你不喜欢正则表达式,所以我只发布我认为最短的解决方案。

获得第一个int:

Match match = Regex.Match(" 3 - .x. - 4", @"\d+");
if (match.Success)
    Console.WriteLine(int.Parse(match.Value));

答案 2 :(得分:5)

没有标准的.NET方法可以做到这一点 - 虽然我不会惊讶地发现VB在Microsoft.VisualBasic程序集中有一些东西(随.NET一起提供,因此即使从中使用它也不是问题C#)。

结果总是非负面的(这会使事情变得更容易)?

老实说,正则表达式是最简单的选择,但是......

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);
}

然后你只需要在int.TryParse的结果上调用RemoveCruftFromNumber(不要忘记整数可能太大而无法存储在int中)。

答案 3 :(得分:2)

我喜欢@ Donut的方法。

我想补充一点,char.IsDigitchar.IsNumber也允许使用其他语言和脚本(see here)中的数字的unicode字符。
如果您只想检查数字0到9,可以使用"0123456789".Contains(c)

三个示例实现:

要删除尾随的非数字字符:

var digits = new string(input.Trim().TakeWhile(c =>
    ("0123456789").Contains(c)
).ToArray());

删除前导非字母字符:

var digits = new string(input.Trim().SkipWhile(c =>
    !("0123456789").Contains(c)
).ToArray());

删除所有非数字字符:

var digits = new string(input.Trim().Where(c =>
    ("0123456789").Contains(c)
).ToArray());

当然:int.Parse(digits)int.TryParse(digits, out output)

答案 4 :(得分:1)

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");

答案 5 :(得分:1)

这就是我在Java中的表现:

int parseLeadingInt(String input)
{
    NumberFormat fmt = NumberFormat.getIntegerInstance();
    fmt.setGroupingUsed(false);
    return fmt.parse(input, new ParsePosition(0)).intValue();
}

我希望在.NET中能有类似的东西。

这是我目前正在使用的基于正则表达式的解决方案:

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;
}

答案 6 :(得分:1)

这并没有真正回答你的问题(关于内置的C#方法),但你可以尝试逐个删除输入字符串末尾的字符,直到int.TryParse()接受它作为有效数字:

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);

当然,如果input很长,这将会很慢。

ADDENDUM (2016年3月)

在尝试每次解析之前,可以通过切断右边的所有非数字/非空格字符来加快速度:

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);

答案 7 :(得分:0)

我不确定为什么你会在这种情况下避免使用正则表达式。

这是一个可以根据您的需求调整的小问题。

“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;
        }
    }
}

编辑: 对于不正确的结果(以及维护开发人员:),这是真的。

以下是修订版:

    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);
    }

答案 8 :(得分:0)

也可以加我的。

        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());

消息框仅用于测试目的,只需在验证方法正常工作后将其删除即可。

答案 9 :(得分:-1)

    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);
    }