C# 奇怪的string.IndexOf行为

C# 奇怪的string.IndexOf行为,c#,infinite-loop,indexof,C#,Infinite Loop,Indexof,我编写了以下代码片段,以消除文本块中过多的空格 int index = text.IndexOf(" "); while (index > 0) { text = text.Replace(" ", " "); index = text.IndexOf(" "); } 一般来说,这种方法很好用,但相当复杂,可能效率低下 问题 当文本由于某种奇怪的原因包含“-”时,indexOf返回一个匹

我编写了以下代码片段,以消除文本块中过多的空格

int index = text.IndexOf("  ");
while (index > 0)
{
    text = text.Replace("  ", " ");
    index = text.IndexOf("  ");
}
一般来说,这种方法很好用,但相当复杂,可能效率低下

问题 当文本由于某种奇怪的原因包含“-”时,indexOf返回一个匹配! Replace函数没有删除任何内容,然后它就陷入了一个无休止的循环中

你知道字符串是怎么回事吗。IndexOf?

啊,文本的乐趣

你最有可能在那里看到的是一个“软连字符”,但在发布时丢失了

为了重现该问题,我尝试了以下代码:

果然,上面的代码陷入了一个循环

请注意,根据CharMap的说法,
\u00ad
是软连字符的Unicode符号。您也可以随时从CharMap复制和粘贴字符,但如果将其发布在此处,则会将其替换为更常见的表亲,即减号连字符,Unicode符号
u002d
(键盘上的一个)

您可以阅读的文档中的一小部分对该主题进行了说明:

字符串搜索方法,如String.StartsWith和String.IndexOf,也可以执行区域性敏感或顺序字符串比较。下面的示例说明了使用IndexOf方法进行顺序比较和区域性敏感比较之间的差异。一个对文化敏感的搜索,其中当前文化为英语(美国),认为子字符串“oe”与连字“œ”匹配由于软连字符(U+00AD)是零宽度字符,搜索将软连字符视为等同于空字符,并在字符串开头找到匹配项。另一方面,顺序搜索在这两种情况下都找不到匹配项

我已经强调了相关部分,但我也记得不久前有一篇关于这个问题的博客文章,但我的Google Fu今晚让我失望

这里的问题是IndexOf和Replace使用不同的方法来定位文本

而索引则将软连字符视为“实际上不存在”,因此将其两侧的两个空间发现为“两个连接空间”,替换方法不会,因此不会删除其中任何一个。因此,存在循环继续迭代的条件,但由于Replace不会删除符合条件的空格,因此它永远不会结束。毫无疑问,Unicode符号空间中还有其他类似的字符显示出类似的问题,但这是我见过的最典型的情况

至少有两种处理方法:

  • 您可以使用Regex.Replace,它似乎没有这个问题:

    text = Regex.Replace(text, "  +", " ");
    
    就我个人而言,我可能会在正则表达式中使用空格特殊字符,即
    \s
    ,但是如果您只需要空格,上面的方法就可以了

  • 您可以显式要求IndexOf使用顺序比较,这样不会因为文本的行为像。。。好。。。正文:

    index = text.IndexOf("  ", StringComparison.Ordinal);
    

  • Regex替代替换函数我试过这个,它看起来很有效,有2和3个空格和连字符。这是我的字符串text=“A B C-更多东西-,嘿,看工作”;你能发布你的字符串吗?在这里发布字符串可能不起作用,因为这样会用一个更常见的字符替换有问题的字符。试试这个。打开CharMap,找到软连字符(位于注册商标字符的R-in-circle旁边),复制,然后将其粘贴到代码中,然后再试一次。哇!我今天学到了一些东西。IndexOf behavior与顺序比较是否存在其他不同的情况?好吧,在任何可以指定
    CultureInfo
    对象的地方,如果使用不带该参数的重载,观察默认值总是值得的,而文本只是其中的一个领域,其回报通常是工作-非工作。软连字符?哇,多好的回答啊-谢谢你的回答!请注意,软连字符通常在源代码中可见,但通常不应出现在显示的文本中。它的目的是标记一个可以破坏作品的地方。你可以将它添加到一个长单词中允许破译的地方,因为你知道显示这个单词不会带来很多小的“负号”
    index = text.IndexOf("  ", StringComparison.Ordinal);