C# 从非数字之间的字符串中解析数字

C# 从非数字之间的字符串中解析数字,c#,C#,我正在处理.NET项目,我试图只解析字符串中的数值。比如说, string s = "12ACD"; int t = someparefun(s); print(t) //t should be 12 有几个假设是正确的 字符串模式始终是数字后跟字符 数字部分始终为一位或两位数字值 是否有任何C#预定义函数来解析字符串中的数值?您可以使用RegEx.Match(正则表达式) 阅读msdn关于它们的文章。这很简单。没有这样的函数,至少我知道没有。但有一种方法是使用正则表达式删除所有不是数字的内

我正在处理.NET项目,我试图只解析字符串中的数值。比如说,

string s = "12ACD";
int t = someparefun(s); 
print(t) //t should be 12
有几个假设是正确的

  • 字符串模式始终是数字后跟字符
  • 数字部分始终为一位或两位数字值
  • 是否有任何C#预定义函数来解析字符串中的数值?

    您可以使用RegEx.Match(正则表达式)
    阅读msdn关于它们的文章。这很简单。

    没有这样的函数,至少我知道没有。但有一种方法是使用正则表达式删除所有不是数字的内容:

    using System;
    using System.Text.RegularExpressions;
    
    int result =
        // The Convert (System) class comes in pretty handy every time
        // you want to convert something.
        Convert.ToInt32(
            Regex.Replace(
                "12ACD",  // Our input
                "[^0-9]", // Select everything that is not in the range of 0-9
                ""        // Replace that with an empty string.
        ));
    
    此函数将为
    12ABC
    生成
    12
    ,因此如果您需要能够处理负数,则需要另一种解决方案。它也是不安全的,如果只传递非数字,则会产生
    格式异常
    。以下是一些示例数据:

    "12ACD"  =>  12
    "12A5"   =>  125
    "CA12A"  =>  12
    "-12AD"  =>  12
    ""       =>  FormatException
    "AAAA"   =>  FormatException
    
    更详细但更安全的方法是使用:

    下面是一些示例数据:

    "12ACD"  =>  12
    "12A5"   =>  125
    "CA12A"  =>  12
    "-12AD"  =>  12
    ""       =>  0
    "AAAA"   =>  0
    
    或者,如果你只想要字符串中的第一个数字,基本上在遇到非数字的东西时停止,我们突然也可以轻松地处理负数:

    using System;
    using System.Text.RegularExpression;
    
    public static int ConvertToInt(String input)
    {
        // Matches the first numebr with or without leading minus.
        Match match = Regex.Match(input, "-?[0-9]+");
    
        if (match.Success)
        {
            // No need to TryParse here, the match has to be at least
            // a 1-digit number.
            return int.Parse(match.Value);
        }
    
        return 0; // Or any other default value.
    }
    
    我们再次测试它:

    "12ACD"  =>  12
    "12A5"   =>  12
    "CA12A"  =>  12
    "-12AD"  =>  -12
    ""       =>  0
    "AAAA"   =>  0
    

    总体上,如果我们讨论用户输入,我会考虑不接受无效的输入,只使用<代码> int .TyPARSESER()/<代码>而不需要额外的魔法,并且在失败时通知用户输入是次优的(并且可能再次提示一个有效的数字)。

    还有其他数字类型的等价物


    编辑:重读之后,我发现你的字符串不仅仅是那个数字。在这种情况下,在使用parse之前,您需要先用正则表达式取出数字。

    因为您知道您关心的唯一字符是前2个或仅是前2个,所以可以在前2个字符上使用int.TryParse和substring

    如果返回false(即第二个字符不是数字),则只需对第一个字符执行int.Parse和Substring

    可能有一种更干净的方法,但基于您的假设,它应该可以完成这项工作。

    Regex是一种方法,如图所示

    根据您的假设,另一种方法是以这种方式使用(使用
    TryParse
    以获得额外的安全性):


    当然,代码的用途不会立即显示给读者,因为他们的大部分时间都花在破译
    TakeWhile
    部分,而
    部分被转换成
    字符串

    Bobby描述的正则表达式方法可能是处理这一问题的最佳方法,但如果您特别小心正则表达式,则可以使用它LINQ和Convert.ToInt32方法的组合:

        string test = "12ACD";
        int number = Convert.ToInt32(new String(test.Where(x => char.IsNumber(x)).ToArray()));
    

    基于您的假设,最直接的代码如下

    string s = "13AD";
    string s2 = s.Substring(0, s.Length - 2);
    int i = int.Parse(s2);
    

    如果你的假设是有保证的,这是最可读的方法。不需要regex或别致的LINQ。LINQ很好,但它似乎被过度使用了。

    即使CLI中有这样一个内在函数;您可能会发现它只在特定的表单上起作用,或者必须告诉它要与所述表单一起使用的表单和/或行为。换句话说,您希望您的解决方案如何处理“AB123CD456EF”?只解析第一个匹配项,将所有数字字符连接在一起并进行解析,还是将每个匹配项解析为可枚举结果的一个元素


    这些情况中的任何一种都可以通过正则表达式得到充分的处理。我建议将您的解决方案广泛地包装到可读的、有良好文档记录的函数中,无论您从已经给出的好建议中选择哪一个。

    Ahmads解决方案让我想到了这一点-假设字符串始终是一个或两个数字,后跟至少一个非数字字符:

    int number = Int32.Parse(
        Char.IsDigit(foo, 1)  ?  foo.Substring(0, 2)  :  foo.Substring(0, 1), 
        CultureInfo.InvariantCulture);
    
    逻辑如下:如果索引1(位置2)处的字符是数字,则获取前两个字符,然后解析它们。如果索引1处的字符不是数字,则获取第一个字符,然后对其进行分析。

    如何:

        public int ReadStartingNumber(string text)
        {
            if (string.IsNullOrEmpty(text) || !char.IsDigit(text[0]))
                throw new FormatException("Text does not start with any digits");
    
            int result = 0;
            foreach (var digit in text.TakeWhile(c => char.IsDigit(c)))
            {
                result = 10*result + (digit - '0');
            }
    
            return result;
        }
    
    使用:


    鲁宾逊会有危险的!危险!前面是正则表达式!毁灭!毁灭@兰多普洛:我知道,我知道……我知道他现在有两个问题,但都不是我的问题;p由于
    string
    实现了
    IEnumerable
    ,因此不需要调用
    ToCharray
    。另外,我可能会选择
    TakeWhile
    而不是
    Where
    ,这样,例如,“12ACD3”就不会变成“123”。但这显然需要指定。@Dan Tao-我听说字符串实现IEnumerable,但由于intellisense在我的VS2008副本中没有给我这个选项,我不确定它是否能工作。刚测试过,编译的不错,所以我编辑了我的答案。为这些信息干杯,只是想表明你不能总是相信你的工具。许多人使用
    ToCharArray
    来强制它以IntelliSense的形式出现,但它没有它也能工作。您可能还对这篇文章感兴趣:为什么VS2008不在Intellisense中为String类()显示扩展方法?不过,如果只有一个数字,它也不会起作用。(对于上面的代码,“12ACD”将失败,因为
    s.Length-2
    3
    并且
    12A
    不能解析为Int32。)由于格式问题,我误读了这个问题。他有一个列表,但它的格式不是这样的。我认为他有1或2个字符,后面紧跟着2个字符,因为2个列表项看起来不像列表项。事实上,他有任意的字符,所以regex选项(目前投票最多)可能是最好的,正如答案的海报敏锐地指出的那样不足,因为他可以有一个或两个数字。这部分不保证。如果您将TakeWhile调用封装到一个额外的GetStartingDigits函数中,代码应该很容易阅读。为什么要将
    Int32.TryParse
    int括起来
    int number = Int32.Parse(
        Char.IsDigit(foo, 1)  ?  foo.Substring(0, 2)  :  foo.Substring(0, 1), 
        CultureInfo.InvariantCulture);
    
        public int ReadStartingNumber(string text)
        {
            if (string.IsNullOrEmpty(text) || !char.IsDigit(text[0]))
                throw new FormatException("Text does not start with any digits");
    
            int result = 0;
            foreach (var digit in text.TakeWhile(c => char.IsDigit(c)))
            {
                result = 10*result + (digit - '0');
            }
    
            return result;
        }
    
    int t = Parse.Number.Select(int.Parse).Parse("12ACD");
    print(t) //t should be 12 and type of int32.