7

这是从其他一些问题的讨论中衍生出来的。

假设我必须解析大量非常长的字符串。每个字符串都包含一个double由空格分隔的 s 序列(当然是在文本表示中)。我需要将doubles 解析为List<double>.

标准解析技术(使用string.Split+ double.TryParse)似乎很慢:对于每个数字,我们需要分配一个字符串。

我试图使它成为类似 C 的旧方式:计算包含数字的子字符串的开头和结尾的索引,并“就地”解析它,而不创建额外的字符串。(见http://ideone.com/Op6h0,下面显示了相关部分。)

int startIdx, endIdx = 0;
while(true)
{
    startIdx = endIdx;
    // no find_first_not_of in C#
    while (startIdx < s.Length && s[startIdx] == ' ') startIdx++;
    if (startIdx == s.Length) break;
    endIdx = s.IndexOf(' ', startIdx);
    if (endIdx == -1) endIdx = s.Length;
    // how to extract a double here?
}

有一个重载string.IndexOf,仅在给定的子字符串中搜索,但我找不到从子字符串中解析双精度的方法,而没有先实际提取该子字符串。

有人有想法吗?

4

2 回答 2

7

没有托管 API可以从子字符串中解析双精度。我的猜测是,与 double.Parse 中的所有浮点运算相比,分配字符串将是微不足道的。

无论如何,您可以通过创建一个长度为 100 的仅包含空格的“缓冲区”字符串来保存分配。然后,对于要解析的每个字符串,使用unsafe code将字符复制到此缓冲区字符串中。您用空格填充缓冲区字符串。对于解析,您可以使用 NumberStyles.AllowTrailingWhite 这将导致尾随空格被忽略。

获取指向字符串的指针实际上是一个完全受支持的操作:

    string l_pos = new string(' ', 100); //don't write to a shared string!
    unsafe 
    {
        fixed (char* l_pSrc = l_pos)
        {               
              // do some work
        }
    }

C# 具有将字符串绑定到 char* 的特殊语法。

于 2012-04-15T11:54:59.763 回答
2

如果你想做得很快,我会使用状态机

这可能看起来像:

enum State
{
    Separator, Sign, Mantisse etc.
}
State CurrentState = State.Separator;
int Prefix, Exponent, Mantisse;
foreach(var ch in InputString)
{
    switch(CurrentState)
    { // set new currentstate in dependence of ch and CurrentState
        case Separator:
           GotNewDouble(Prefix, Exponent, Mantisse); 


    }

}
于 2012-04-15T13:12:08.410 回答