2

UTF-8文字列のバイト位置からObjective-Cの対応する文字位置に変換する必要があります。これを行うにはライブラリが必要だと確信していますが、ライブラリを見つけることができません。誰でもできます(ただし、CまたはC ++ライブラリならどれでもここで機能します)。

必要な文字でUTF-8文字列を切り捨て、それをNSStringに変換し、NSStringの長さを読み取って答えを得ることができることに気付きましたが、それはかなり解決できる問題に対するややハッキーな解決策のようです。 Cの小さなFSMを使用するだけです。

ご協力いただきありがとうございます。

4

2 に答える 2

1

「キャラクター」はややあいまいな用語で、異なる文脈では異なるものを意味します。あなたの例と同じ結果が欲しいと思います[NSString length].

NSStringドキュメントはこれについて正確に述べているわけではありませんが、文字列内のUTF-16 コード単位[NSString length]の数を数えています。したがって、U+0000..U+FFFF はそれぞれ 1 つとしてカウントされますが、U+10000..U+10FFFF はそれぞれ 2 つとしてカウントされます。また、サロゲート ペアを分割しないでください。

各 UTF-8 文字の先頭バイトに基づいて、UTF-16 コード ポイントの数をカウントできます。末尾のバイトはばらばらな値のセットを使用するため、文字列内の位置を除いて、状態を追跡する必要はまったくありません(良いニュース: 有限状態マシンはやり過ぎです)。

static const unsigned char BYTE_WIDTHS[256] = {
    // 1-byte: 0xxxxxxx
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    // Trailing: 10xxxxxx
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    // 2-byte leading: 110xxxxx
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
    // 3-byte leading: 1110xxxx
    // 4-byte leading: 11110xxx
    // invalid: 11111xxx
    1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0
};

size_t utf8_utf16width(const unsigned char *string, size_t len)
{
    size_t i, utf16len = 0;
    for (i = 0; i < len; i++)
        utf16len += BYTE_WIDTHS[string[i]];
    return utf16len;
}

表は、1 バイト、2 バイト、および 3 バイトの UTF-8 先頭文字の場合は 1、4 バイト UTF-8 の先頭文字の場合は 2 です。これらは に変換すると 2 文字になるためNSStringです。

Haskellでテーブルを生成しました:

elems $ listArray (0,256) (repeat 0) //
    [(n,1) | n <- ([0x00..0x7f] ++ [0xc0..0xdf] ++ [0xe0..0xef])] //
    [(n,2) | n <- [0xf0..0xf7]]
于 2013-02-23T09:06:47.483 に答える
0

UTF-8 エンコーディングを見て、コード ポイントが次の 8 ビット パターンで始まることに注意してください。

76543210 <- bit
0xxxxxxx <- ASCII chars
110xxxxx \
1110xxxx  } <- more byte(s) (of form 10xxxxxx) follow
11110xxx /

これは、コード ポイントの先頭を検索するときに探す必要があるものです。

しかし、それだけでは解決策の一部にすぎません。文字の組み合わせを考慮する必要があります。分音記号は、その前にある主な文字と組み合わせて使用​​する必要があります。それらを単に分離して独立した文字として扱うことはできません。

おそらくそれ以上のものがあります。

于 2013-02-23T08:48:13.023 に答える