1

文字列の最初の文字を取得する必要がある C# メソッドがあり、特定の Unicode 文字 (すべて右から左の文字) を含む HashSet に存在するかどうかを確認します。

だから私はやっている

var c = str[0];

次に、ハッシュセットを確認します。

問題は、最初の char のコード ポイントが 65535 より大きい文字列に対して、このコードが機能しないことです。

実際に、0 から 70,000 までのすべての数値を通過するループを作成し (最高の RTL コード ポイントは約 68,000 であるため、切り上げました)、数値からバイト配列を作成し、

Encoding.UTF32.GetString(intValue);

この文字で文字列を作成します。次に、HashSet を検索するメソッドにそれを渡しますが、そのメソッドは失敗します。

str[0]

その値は決してあるべきものではありません。

私は何を間違っていますか?

4

3 に答える 3

5

AStringは一連の UTF-16 コード単位で、1 つまたは 2 つが Unicode コードポイントをエンコードします。文字列からコードポイントを取得したい場合は、文字列内のコードポイントを反復する必要があります。「文字」は、基本コードポイントであり、その後に 0 個以上の結合コードポイント (「結合文字」) のシーケンスが続きます。

// Use a HashSet<String>

var itor = StringInfo.GetTextElementEnumerator(s);
while (itor.MoveNext()) {
    var character = itor.GetTextElement();
    // find character in your HashSet
}

コードポイントの結合を考慮する必要がない場合は、それらを消去できます。(しかし、一部の言語では非常に重要です。)

于 2016-10-18T16:39:52.537 に答える
1

将来この質問を見て、私が最終的に得た解決策に興味がある人には、文字列の最初の文字に基づいて文字列を RTL または LTR で表示するかどうかを決定する私の方法です。UTF-16 サロゲート ペアが考慮されます。

私を正しい方向に向けてくれた Tom Blodget に感謝します。

if (string.IsNullOrEmpty(str)) return null;

var firstChar = str[0];
if (firstChar >= 0xd800 && firstChar <= 0xdfff)
{
    // if the first character is between 0xD800 - 0xDFFF, this is the beginning
    // of a UTF-16 surrogate pair. there MUST be one more char after this one,
    // in the range 0xDC00-0xDFFF. 
    // for the very unreasonable chance that this is a corrupt UTF-16 string
    // and there is no second character, validate the string length
    if (str.Length == 1) return FlowDirection.LeftToRight;

    // convert surrogate pair to a 32 bit number, and check the codepoint table
    var highSurrogate = firstChar - 0xd800;
    var lowSurrogate = str[1] - 0xdc00;
    var codepoint = (highSurrogate << 10) + (lowSurrogate) + 0x10000;

    return _codePoints.Contains(codepoint)
        ? FlowDirection.RightToLeft
        : FlowDirection.LeftToRight;
}
return _codePoints.Contains(firstChar)
    ? FlowDirection.RightToLeft
    : FlowDirection.LeftToRight;
于 2016-10-25T10:03:21.430 に答える
0

あなたの質問を理解しているかどうかわかりません。短いコードが役立つかもしれません。「var c = str[0]」のような行がある場合、「str」が文字列であると仮定すると、c は UTF16 でエンコードされた char になります。このため、c が (2^16 - 1) より大きくなることはありません。Unicode 文字はそれよりも大きくなる可能性がありますが、それが発生すると、複数の「文字」位置にまたがるようにエンコードされます。UTF-16 の場合、「最初の」文字は 1 つまたは 2 つの 16 ビット値を占める場合があります。

于 2016-10-18T16:39:59.900 に答える