是否有库函数可以确定字符串的哪一部分是数字?

Is there library function to determine which part of a string is number?

是否有任何库函数可以使用字符串的字符并将它们解析为双精度 - 即使不是整个字符串都是数字 - 并且 return 使用的字符数 and 解析结果?

我想象像 int ConsumeDouble(string text, out double value) 这样的东西。假设我有一个 string s = "12.42;3.14",该函数将读取“12.42”,在分号处停止,将 12.42 写入值和 return 5,因为它消耗了 5 个字符。

我依稀记得在C中有这样的东西,但我在C#中找不到类似的东西。 dot net框架中有这样的功能吗?还是有什么方法可以在不自己编写解析器且不使用正则表达式的情况下实现这一目标?


上面的字符串 s 只是一个例子,在我的用例中,没有明确的指示我可以期待数字的地方和不可以期待数字的地方。


如果不存在这样的函数,那么编写这样的函数的最佳方法是什么?我想到了状态机来检查哪些字符属于一个数字,然后使用 double.Parse() 来解析它。

假设效率不是太重要,并且假设您总是希望数字从字符串的 START 开始而不是中途:

public static (double result, int consumed) ParseLongestNumber(string s)
{
    for (int n = s.Length; n > 0; --n)
    {
        string t = s.Substring(0, n);

        if (double.TryParse(t, out var r))
            return (r, n);
    }

    return (double.NaN, 0);
}

这应该可以处理所有数字格式,例如ParseLongestNumber("-1.42e3;3.14") 将 return (-1420, 7).

如果无法解析数字,它将return (NaN, 0)

(注意:您没有说您使用的是旧版本的 C# - 如果您使用的是旧版本,则必须通过 out 参数或显式 return 结果 Tuple 而不是通过新式元组。)

一个可能的优化是找到最后一个可能的数字字符并只解析到那个:

public static (double result, int consumed) ParseLongestNumber(string s)
{
    const string NUMBER_CHARS = "+-.,e0123456789";

    int n = 0;

    while (n < s.Length)
        if (NUMBER_CHARS.IndexOf(s[n]) < 0)
            break;
        else
            ++n;

    for (; n > 0; --n)
    {
        string t = s.Substring(0, n);

        if (double.TryParse(t, out var r))
            return (r, n);
    }

    return (double.NaN, 0);
}

此优化是否实际上有用只能通过经验测试来确定。