C#中IndexOf出现了错误

4

我显然在这里漏掉了什么...

我正在编写一个函数,该函数返回由特定字符串分隔的子字符串数量。以下是相当简单的函数 -

public static FuncError DCount(String v1, String v2, ref Int32 result) {
        result = 0;
        if (String.IsNullOrEmpty(v1)) {
            return null;
        }
        if (String.IsNullOrEmpty(v2)) {
            return null;
        }

        int ct = 1;
        int ix = 0;
        int nix = 0;

        do {
            nix = v1.IndexOf(v2, ix);
            if (nix >= 0) {
                ct++;

                System.Diagnostics.Debug.Print(
string.Format("{0} found at {1} count={2} result = {3}",
v2, nix, ct, v1.Substring(nix,1)));
                ix = nix + v2.Length;
            }
        } while (nix >= 0);
        result = ct;
        return null;
    }

当我使用一个在特定情况下作为分隔符使用的特殊字符进行调用时,问题就出现了。它返回了很多错误的结果。从Debug.Print中可以看出,第一个和最后一个参数应该总是相同的。

þ found at 105 count=2 result = t
þ found at 136 count=3 result = t
þ found at 152 count=4 result = þ
þ found at 249 count=5 result = t
þ found at 265 count=6 result = t
þ found at 287 count=7 result = t
þ found at 317 count=8 result = t
þ found at 333 count=9 result = þ
þ found at 443 count=10 result = þ
þ found at 553 count=11 result = þ
þ found at 663 count=12 result = þ
þ found at 773 count=13 result = þ
þ found at 883 count=14 result = þ
þ found at 993 count=15 result = þ

如果我将þ作为字符传递,它可以正常工作。如果我使用þ作为分隔符来分割字符串,则会返回正确数量的元素。至于错误识别的“t”,结果中有其他未被捕获的“t”,因此这不是字符转换问题。
感到困惑...
谢谢

尽量给变量起适当的名称,这不仅有助于您自己,也有助于我们。 - Sachin
1
你能在这里发布用于测试的实际代码吗?也就是调用那个函数的代码?最好是通过转义特殊字符来避免我们依赖于网络编码来传达正确的字符。 - Lasse V. Karlsen
字符串比较容易产生意想不到的结果。在比较规则上一定要明确。这里可能应该使用StringComparison.Ordinal。 - Hans Passant
3个回答

6
这里的问题在于不同文化如何表示字符,有时候会将它们组合起来。
你正在寻找的字母Thorn,显然可以用th字母代替。
LINQPad中尝试以下代码:
void Main()
{
    string x = "uma thurman";
    x.IndexOf("þ").Dump();
}

它将输出4

(请注意,我在挪威的计算机上运行此程序,这可能会对结果产生影响)

这与德语字母双S - ß - 在一些文化中出现两个s的单词中的问题相同。


附注:这不是原帖作者和您使用的Sho,而是Thorn字母。前者源自古希腊,不等同于“th”,而后者是一种北欧字母(古诺尔斯语、冰岛语等),相当于一个无声的“th”,类似于希腊字母Theta(Θ)。 - Jeppe Stig Nielsen
最糟糕的是,当我进行比较时,我对文本长度进行了检查:string text = "ß"; text.IndexOf("s") => 0 text.Length => 1因此,s和ß的长度也相同...到目前为止唯一的解决方案是 text.IndexOf('s') => -1 - Developer

4

我发现使用 'þ' 而不是 "þ" 也可以。此外,如果搜索的字符是一个字符串,我们可以通过 search[0] 进行强制转换为 char,它也会给出 -1。谢谢。 - Developer

0

您正在使用 IndexOf 的重载版本,它:

使用当前区域设置执行单词(区分大小写和区域设置)搜索

因此结果取决于您线程的CurrentCulture。大多数文化认为字母thorn等同于th。请参见Lasse的答案。

例如,古老的北欧神话中的Þórr通常在英语中写作Thor,其首字母发音类似于“星期四”(Thor's day)中的“Th”。

要解决问题,请将v1.IndexOf(v2, ix)更改为:

v1.IndexOf(v2, ix, StringComparison.Ordinal)

请参阅该重载的文档

顺序比较是一种天真的方法,简单地比较它们的数值,逐个比较char值。相比之下,与文化相关的比较会进行大量规范化,包括对重音字母的不同表示以及文化认为等效的不同字母的规范化。这在排序中也非常重要,例如,在顺序比较中,字符串"naïve"在排序中排在字符串"nasty"之后(因为System.Char'ï'的数值高于's')。


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