0

CoreFoundation フレームワークの CFString オブジェクトに格納されている文字数 (基になる Unicodeコード ポイントで表される) を取得する方法はありますか?

CFStringGetLength利用可能な機能があります:

例: 2 番目の (SMP) Unicode プレーンにある1 文字 ( Shavian Alphabetの文字「peep」) を含む文字列の長さを取得しようとしています。

UInt8 arr[] = {0xf0, 0x90, 0x91, 0x90}; //UTF8
CFStringRef r = CFStringCreateWithBytes(0, arr, sizeof(arr),
                                        kCFStringEncodingUTF8, false);
CFIndex length = CFStringGetLength(r);

ドキュメントには、次のものが返されると記載されています。

theString に格納されている文字数 (UTF-16 コード ペア)。

ご覧のとおり、この文は矛盾しています。文字数は必ずしも UTF-16 コード ポイントの数と同じではありません。ただし、中括弧内の部分はより正確です。関数の実際の結果は、UTF-16 シーケンスの数です。私の例では、関数の結果は2 (UTF-16 で文字をエンコードするために必要なシーケンスの長さ) ですが、関数名は結果が1であることを示唆しています(私の意見では)。

Unicode コード ポイントで文字数を取得する方法を見つけたいと思います。CoreFoundation でそれを行う方法はありますか?

4

3 に答える 3

1

回避策を見つけました。おそらく UTF-32 への追加の変換が必要になるため、これは完全ではありません。

UInt8 arr[] = {0xf0, 0x90, 0x91, 0x90}; //UTF8, 
CFStringRef r = CFStringCreateWithBytes(0,
                                        arr,
                                        sizeof(arr),
                                        kCFStringEncodingUTF8,
                                        false);
CFIndex length = CFStringGetLength(r);
CFRange range = CFRangeMake(0, length);
CFIndex bytes;
CFStringGetBytes(r, range, kCFStringEncodingUTF32, 0, false, nullptr,
                 0, &bytes);
CFIndex characterCount = bytes/4;

回避策は、UTF-16 とは対照的に、UTF-32は定義上、単一のエンティティに単一のコード ポイントを含むという事実を利用します。また、エンティティは 4 バイト サイズで定義されてCFStringGetBytesおり、変換後に文字列を格納するのに必要なバイト数を取得する機能があるため、バイト数を 4 で割ることでコード ポイント数を取得できます。

とにかく、実際の変換を行うことが主な目的なので、引数としてCFStringGetBytes渡す場合でも、少なくとも主要な部分の変換が実際に行われる可能性があります。このため、この問題の別の解決策を聞くことができれば幸いです。nullptrbuffer

于 2013-03-23T01:16:22.403 に答える
1

正規化に関係なく、ユーザーに表示される「文字」の数を知りたい場合は、返された範囲を使用して構成された文字シーケンスをループしCFStringGetRangeOfComposedCharactersAtIndex、反復を数えます。

于 2014-12-15T11:52:14.827 に答える