2010-07-08 32 views
10

我正在处理.NET项目,我试图从字符串中解析数字值。例如,从一个非数字字符串中解析数字

string s = "12ACD"; 
int t = someparefun(s); 
print(t) //t should be 12 

一对夫妇的假设是

  1. 的字符串模式将永远是由字符数如下。
  2. 数字部分始终是一个或两个数字值。

是否有任何C#预定义函数来解析字符串的数值?

+0

的可能的复制[查找并从字符串中提取一些(http://stackoverflow.com/questions/4734116/查找和提取一个字符串中的数字) – 2016-08-08 06:43:01

回答

26

有没有这样的功能,至少我没有知道。但是,一个方法是使用正则表达式来删除一切,是不是数字:

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

此功能将产生1212ABC,所以如果你需要能够处理负数,则需要不同的解决方案。这也是不安全的,如果你通过它只有非数字它将产生FormatException。下面是一些示例数据:

"12ACD" => 12 
"12A5" => 125 
"CA12A" => 12 
"-12AD" => 12 
""  => FormatException 
"AAAA" => FormatException 

一点点冗长,但更安全的办法是使用int.TryParse():再次

using System; 
using System.Text.RegularExpression; 

public static int ConvertToInt(String input) 
{ 
    // Replace everything that is no a digit. 
    String inputCleaned = Regex.Replace(input, "[^0-9]", ""); 

    int value = 0; 

    // Tries to parse the int, returns false on failure. 
    if (int.TryParse(inputCleaned, out value)) 
    { 
     // The result from parsing can be safely returned. 
     return value; 
    } 

    return 0; // Or any other default value. 
} 

一些示例数据:

"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.TryParse()没有一些额外的魔法并在失败时通知用户输入不理想(并可能再次提示输入有效数字)。

+8

危险威尔罗宾逊!危险!正规表达提前!破坏!破坏! – Randolpho 2010-07-08 14:39:32

+10

@Randoplho:我知道,我知道......我知道他现在有两个问题,但他们都不是我的。 ; P – Bobby 2010-07-08 14:57:25

0

您可以使用RegEx.Match(正则表达式) 阅读他们的MSDN文章。很简单。

0

Int32.Parse()

有当量为其它数目的类型也。

编辑:重读后,我看到你的字符串不只是这个数字。在这种情况下,在使用解析之前,您需要首先使用正则表达式提取数字。

1

既然你知道你关心的唯一字符是前2或只是第一个,你可以在前2个字符上使用int.TryParse和SubStringing。

如果返回false(即第二个字符不是数字),那么只需在第一个字符上执行int.Parse和Substring。

有可能是一种更干净的方式,但根据您的假设,应该完成这项工作。

15

正则表达式是一种方法,如demonstrated by Bobby

另一种方法,因为你的假设,就是以这种方式使用TakeWhile(用TryParse额外的安全性):

string input = "12ACD"; 
string digits = new string(input.TakeWhile(c => Char.IsDigit(c)).ToArray()); 
int result; 
if (Int32.TryParse(digits, out result)) 
{ 
    Console.WriteLine(result); 
} 

诚然,代码的目的并不立即蹦出读者因为他们大部分的时间都会花在破译TakeWhile部分,转换为string

+4

如果将TakeWhile调用封装到一个额外的GetStartingDigits函数中,则应该很容易通读代码。 – 2010-07-08 15:25:59

+0

为什么你将'Int32.TryParse'放入if?如果解析失败,原始的“结果”将保持不变。此外,你不应该使用try catch吗?因此内置函数'TryParse'?如果你使用'.Parse',那么这是有道理的。仍然是非常有用的代码。谢谢 – ppumkin 2014-02-13 20:50:02

+0

@ppumkin'TryParse'用于避免显式的try/catch。因为它返回一个布尔值,所以我把它放在一个'if'中,所以通过使用它,你马上知道解析是否成功,并且可以继续使用'result'。如果你不想在解析尝试失败时依赖默认的'result',那么这会给你更多的控制权。这取决于场景。如果我选择使用'int.Parse',我会使用try/catch。同样的想法,但'TryParse'给了我们更可读性和避免额外的工作。感谢您的评论! – 2014-02-13 20:59:45

3

由鲍比描述的正则表达式的方法可能是处理这种最好的方式,但如果你是特别警惕的正则表达式,你可以使用LINQ的组合和Convert.ToInt32方法:

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

'ToCharArray'调用是不必要的,因为'string'实现了'IEnumerable '。另外,我可能会用'TakeWhile'而不是'Where',以便例如“12ACD3”不会变成“123”。但显然需要明确说明。 – 2010-07-08 15:01:59

+0

@丹涛 - 我听说字符串实现IEnumerable ,但由于intellisense在VS2008的副本中没有给我这个选项,所以我不确定它会起作用。刚刚测试它编译o.k.所以我编辑了我的答案。欢呼的信息,只是去显示你不能总是相信你的工具。 – 2010-07-08 15:34:21

+0

很多人使用'ToCharArray'来强制它在IntelliSense中显示,但它没有它。您可能也对这篇文章感兴趣:为什么VS 2008不在Intellisense中为String类显示扩展方法(http://stackoverflow.com/questions/345883/why-doesnt-vs-2008-display-extension-methods-在-智能感知换串级)。 – 2010-07-08 15:39:37

-1

的根据您的假设,最直接的代码将如下所示...

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

如果您的假设得到保证,这是最可行的方法。无需正则表达式或花哨的LINQ的东西。 LINQ很棒,但它似乎过于频繁地使用过。

+0

你是不是指's.substring(0,2);'?但是,如果只有一位数字,它将不起作用。 (使用上面的代码,“12ACD”会失败,因为's.Length-2'为'3','12A'不能解析为Int32。) – sunside 2010-07-08 15:20:06

+0

由于格式化,我误解了这个问题。他有一个列表,但没有格式化。我以为他有1或2个字符后跟正好2个字符,因为2列表项不看起来像列表项。事实上,他的字符数是任意的,所以正则表达式选项(当前最高的投票数)可能是最好的,正如答案的海报中明确指出的那样。 – 2010-07-08 21:06:22

+0

哦,'Substring(0,2);'是不够的,因为他可以有一个或两个数字。这部分不能保证。 – 2010-07-08 21:06:52

0

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

任何这些情况都可以通过正则表达式处理得相当充分。我建议将你的解决方案广泛地包装成可读的,有详细记录的功能,无论你选择哪个好的建议。

0

Ahmads溶液使我这个 - 假设字符串总是一个或两个数字,随后通过至少一个非数字字符:

int number = Int32.Parse(
    Char.IsDigit(foo, 1) ? foo.Substring(0, 2) : foo.Substring(0, 1), 
    CultureInfo.InvariantCulture); 

的逻辑如下:如果索引1处的字符(位置2)是一个数字,得到前两个字符,然后解析它们。如果索引1处的字符不是数字,则获取第一个字符,然后解析它。

0

如何只:

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

可读性的代价非常低,您也可以简单地在经典的“i”中使用普通循环,并在第一个非数字处打破。 – 2010-07-08 15:38:34

3

使用Sprache

int t = Parse.Number.Select(int.Parse).Parse("12ACD"); 
print(t) //t should be 12 and type of int32.