这是some other question中讨论的衍生产品。
假设我必须解析大量非常长的字符串。每个字符串包含由空格分隔的double
s序列(当然是文本表示形式)。我需要将double
解析为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
的重载,只在给定的子字符串中搜索,但是我找不到从子字符串解析double的方法,而没有先实际提取该子字符串。
有没有人有想法?
答案 0 :(得分:7)
没有托管API 来解析子字符串中的double。我的猜测是,与double.Parse中的所有浮点运算相比,分配字符串是无关紧要的。
无论如何,您可以通过创建长度为100的“缓冲区”字符串来保存分配,该字符串仅由空格组成。然后,对于要解析的每个字符串,使用不安全代码将字符复制到此缓冲区字符串中。用空格填充缓冲区字符串。对于解析,您可以使用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 *的特殊语法。
答案 1 :(得分: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);
}
}