10
string s = "Gewerbegebiet Waldstraße"; //other possible input "Waldstrasse"

int iFoundStart = s.IndexOf("strasse", StringComparison.CurrentCulture);
if (iFoundStart > -1)
    s = s.Remove(iFoundStart, 7);

CultureInfo 1031 (ドイツ語) を実行しています。

IndexOf は、'straße' または 'strasse' を定義済みの 'strasse' と一致させ、位置として 18 を返します。

Remove も Replace も、カルチャを設定するためのオーバーロードはありません。

入力文字列が「strasse」で「straße」が機能する場合、Remove を使用して 6 文字を削除すると、1 文字が残ります。入力文字列が「straße」で、7 文字を削除すると、ArgumentOutOfRangeException が発生します。

見つかった文字列を安全に削除する方法はありますか? IndexOf の最後のインデックスを提供するメソッドはありますか? 私は IndexOf に近づきましたが、それは予想どおり内部のネイティブ コードです。

4

1 に答える 1

5

ネイティブの Win32 API は、見つかった文字列の長さを公開します。P/Invoke を使用してFindNLSStringEx直接呼び出すことができます。

static class CompareInfoExtensions
{
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
    private static extern int FindNLSStringEx(string lpLocaleName, uint dwFindNLSStringFlags, string lpStringSource, int cchSource, string lpStringValue, int cchValue, out int pcchFound, IntPtr lpVersionInformation, IntPtr lpReserved, int sortHandle);

    const uint FIND_FROMSTART = 0x00400000;

    public static int IndexOfEx(this CompareInfo compareInfo, string source, string value, int startIndex, int count, CompareOptions options, out int length)
    {
        // Argument validation omitted for brevity
        return FindNLSStringEx(compareInfo.Name, FIND_FROMSTART, source, source.Length, value, value.Length, out length, IntPtr.Zero, IntPtr.Zero, 0);
    }
}

static class Program
{
    static void Main()
    {
        var s = "<<Gewerbegebiet Waldstraße>>";
        //var s = "<<Gewerbegebiet Waldstrasse>>";
        int length;
        int start = new CultureInfo("de-DE").CompareInfo.IndexOfEx(s, "strasse", 0, s.Length, CompareOptions.None, out length);
        Console.WriteLine(s.Substring(0, start) + s.Substring(start + length));
    }
}

純粋に BCL を使用してこれを行う方法は見当たりません。

于 2015-11-05T19:32:26.153 に答える