字符串.IndexOf()不能识别修改后的字符

8

当使用 IndexOf 查找一个后面跟着一个大值字符(例如,字符700是ʼ)的字符时,则 IndexOf 无法识别您要查找的字符。

例如:

string find = "abcʼabcabc";   
int index = find.IndexOf("c");

在这段代码中,索引应该是2,但它返回了6。
有没有什么办法可以解决这个问题?

3
这段代码的作用是在字符串 find 中查找第一个字符 "c" 的位置,并将其索引值赋值给变量 indexStringComparison.Ordinal 表示使用当前文化的排序规则进行比较。 - Sriram Sakthivel
2个回答

14
Unicode字母700是一个修饰符撇号:换句话说,它修改了字母c。同样地,如果你使用一个'e'后面跟着字符769(0x301),那么它就不再是一个'e'了:e已经被修改成带有重音的e。即:é。你会发现这个字母实际上是两个字符:将它复制到记事本中,然后按退格键(很神奇,对吧?)。
你需要进行“序数”比较(逐字节比较),而不进行任何语言比较。这将找到'c',并忽略它被下一个字母修改的语言事实。在我的'e'示例中,字节为(65)(769),因此如果您逐字节搜索65,您将找到它,并忽略(65)(769)在语言上等同于(233)的事实:é。如果您在语言上搜索(233),它会找到“等效”的(65)(769):
string find = "abéabcabc";
int index = find.IndexOf("é"); //gives you '2' even though the "find" has two characters and the the "indexof" is one

希望这不会太令人困惑。如果您在实际编程中使用此方法,应该在注释中详细解释您正在做的事情:例如,在我的“e”示例中,通常您会希望对用户数据进行语义等价处理,对于常量(例如)进行序数等价处理(这种情况下不应该有差异,否则您的后继者将用斧头追捕你)。请保留HTML标签。

7
您可以告诉 indexOf 查找字符:int index = find.IndexOf('c'); - varocarbas
3
啊,说得好。这会是一个非常恶毒的面试问题:IndexOf('c')IndexOf("c")有什么区别? - Mark Sowul

7

构造被视为与简单字节有语言上的区别。使用 Ordinal 字符串比较来强制进行字节比较。

        string find = "abcʼabcabc";

        int index = find.IndexOf("c", StringComparison.Ordinal);

1
为了澄清,Ordinal排序规则之所以有效,是因为它基于字符串中每个Char的数字值(Unicode代码点)进行比较 - 请参阅文档,这正是OP所要求的。 - James
2
或者直接使用 find.IndexOf('c') 而不是提供一个字符串。 - Gene
StringComparison.Ordinal会让代码变慢吗? - puser
不过,如果你担心的话可以进行测试。过早地优化是一些问题的根源。 - Loofer
2
@puser 不,事实上它在技术上应该是更快的。 - James

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接