0

例如,字符串可以包含整数、浮点数和十六进制数。

“这个字符串可以有 -345 和 57,也可以有 35.4656 或微妙的 0xF46434 等等”

我可以用什么在 C# 中找到这些数字?

4

4 回答 4

3

使用这些方面的东西:(我自己写的,所以我不会说它对于您要查找的任何类型的数字都是包罗万象的,但它适用于您的示例)

var str = "123 This a string than can have -345 and 57 and could also have 35.4656 or a subtle 0XF46434 and more like -0xf46434";
var a = Regex.Matches(str, @"(?<=(^|[^a-zA-Z0-9_^]))(-?\d+(\.\d+)?|-?0[xX][0-9A-Fa-f]+)(?=([^a-zA-Z0-9_]|$))");
foreach (Match match in a)
{
    //do something
}

正则表达式似乎是一种只写的语言,(即非常难以阅读)所以我将把它分解,以便你能理解:(?<=(^|[^a-zA-Z0-9_^]))是一种通过单词边界打破它的回顾。我不能使用\b,因为它考虑-了边界字符,所以它只会匹配345而不是-345. -?\d+(\.\d+)?匹配十进制数,可选负数,可选小数位数。 -?0[xX][0-9A-Fa-f]+匹配十六进制数,不区分大小写,可选负数。最后,(?=([^a-zA-Z0-9_]|$))是一个前瞻,再次作为一个词的边界。请注意,在第一个边界中,我允许字符串的开头,在这里我允许字符串的结尾。

于 2012-05-27T12:12:58.807 回答
2

只需尝试将每个单词解析为double和s 。returnarraydouble

这是从 a 获取s 的一种array方法:doublestring

double[] GetNumbers(string str)
{
    double num;
    List<double> l = new List<double>();
    foreach (string s in str.Split(' '))
    {
        bool isNum = double.TryParse(s, out num);
        if (isNum)
        {
            l.Add(num);
        }
    }
    return l.ToArray();
}

double.TryParse() 关于这里的更多信息。

于 2012-05-27T12:13:59.037 回答
1

鉴于您在此表达式上方的输入匹配那里存在的每个数字

string line = "This a string than can have " + 
                      "-345 and 57 and could also have 35.4656 " +
                      "or a subtle 0xF46434 and more";

Regex r = new Regex(@"(-?0[Xx][A-Fa-f0-9]+|-?\d+\.\d+|-?\d+)");
var m = r.Matches(line);
foreach(Match h in m)
    Console.WriteLine(h.ToString());

编辑:对于替换,您使用采用 MatchEvaluator 重载的 Replace 方法

string result = r.Replace(line, new MatchEvaluator(replacementMethod));
public string replacementMethod(Match match)
{
   return "?????";
}

解释正则表达式模式

首先,序列"(pattern1|pattern2|pattern3)"意味着我们可以在字符串中找到三种可能的模式。其中一个就足以匹配

第一种模式-?0[Xx][A-Fa-f0-9]+表示可选的减号,后跟零,后跟 X 或 x 字符,然后是 AF af 或 0-9 范围内的一系列一个或多个字符

第二种模式-?\d+\.\d+表示可选的减号,后跟一系列 1 或多个数字,后跟小数点,后跟一系列 1 或多个数字

第三种模式-?\d+表示可选的减号后跟一系列 1 个或多个数字。

模式的顺序至关重要。如果您反转模式并将整数匹配放在十进制模式之前,结果将是错误的。

于 2012-05-27T12:32:53.370 回答
1

除了往往有其自身问题的正则表达式之外,您还可以构建一个状态机来进行处理。您可以决定机器将接受哪些输入作为“数字”。与正则表达式不同,状态机将具有可预测的良好性能,并且还会为您提供可预测的结果(而正则表达式有时可以匹配相当令人惊讶的事情)。

当您考虑时,这并不是那么困难。状态很少,您可以明确定义特殊情况。

编辑:以下是对评论的回应。
在 .NET 中,Regex 被实现为NFA(非确定性有限自动机)。一方面,它是一个非常强大的解析器,但另一方面,它有时可以回溯很多。当您接受不安全的输入(来自用户的输入,几乎可以是任何东西)时尤其如此。虽然我不确定您将使用哪种正则表达式来解析结果,但您几乎可以在任何事情上导致性能下降。尽管在大多数情况下性能不是问题,但正则表达式的性能可以随输入呈指数增长。这意味着,在某些情况下,它确实可能成为瓶颈。还有一个相当出乎意料的。

Regex 的贪婪特性导致的另一个潜在问题是,它有时会匹配意想不到的东西。您可能会使用相同的 Regex 表达式数天,它可能工作正常,等待被忽略的字符的正确组合被解析,并且您最终会将垃圾写入数据库。


通过状态机,我的意思是使用确定性有限自动机或类似的东西解析输入。我会告诉你我的意思。这是一个用于解析正十进制整数或字符串中的浮点数的小型DFA 。我很确定您可以使用ANTLR 之类的框架构建 DFA ,尽管我敢肯定周围还有一些功能较弱的框架。

于 2012-05-27T14:29:10.710 回答