2011-06-29 9 views
6

最初に、ANSI C(C++およびMS CRTやglibcなどの非標準のライブラリではありません)を使用して独立したプラットフォームライブラリを開発します。ANSI C UTF-8の問題

いくつかの検索を行った結果、ANSI Cの国際化に最適な方法の1つが、UTF-8エンコーディングを使用していることがわかりました。 UTF-8で

  • STRLEN(複数可):常にバイトの数をカウントします。
  • mbstowcs(NULL、s、0):文字の文字数をカウントできます。

しかし、私はutf-8文字列の要素(文字)のランダムアクセスをしたいときにいくつかの問題があります。 ASCIIエンコーディングで

// What is the return type? 
// Because sizeof(utf-8 char) is 8 or 16 or 24 or 32. 
/*?*/ get_char(char* utf8str, int n) 
{ 
    // I can found Nth character of string by using for. 
    // But it is too slow. 
    // What is the best way? 
} 

ありがとう:UTF-8エンコーディングで

wchar_t get_char(wchar_t* wstr, int n) 
{ 
    // It is very FAST. 
    return wstr[n]; 
} 

そして、ここに私の問題:UTF-32分の16エンコーディングで

char get_char(char* assci_str, int n) 
{ 
    // It is very FAST. 
    return assci_str[n]; 
} 

+1

"N番目の文字"を使用する例がありますか? –

+0

'mbstowcs'はあなたが主張することを保証しません。あなたのロケール設定に依存します( ''を参照)、一般的にエンコードには依存しません。明確なエンコーディングを扱う場合は、 'iconv'などを使用してください。 –

+0

@R: 'replace(char * str){...(get_char(i)...} ') –

答えて

7

おそらく、あなたはこれについて少し誤って考えているでしょう。 UTF-8は、符号化であり、データをシリアル化するのに有用である。それをファイルまたはネットワークに書き込む。これは非常に重要ではないエンコーディングですが、Unicodeのコードポイントの生の文字列は任意の数のエンコードされたバイトで終わる可能性があります。

テキストを扱いたい場合は(説明に応じて)の固定幅の文字列を内部的に格納します。 Unicodeを使う場合は、コードポイントごとに21ビットが必要なので、最も近い整数型はuint32_tです。つまり、すべての文字列を整数の配列として内部的に格納します。次に、各コードポイントにランダムアクセスできます。

ファイルまたはコンソールに書き込むときにのみエンコードし、読み取り時にはUTF-8からデコードします。

ところで、Unicodeコードポイントはまだ文字から遠くにあります。キャラクターの概念は、単純な一般的な整備士を持つためには、はるかに高いレベルにまで達しています。 (例: "a" + "accent grave" - 2つのコードポイント、何文字ですか?)

+0

はい、そうです。utf-8エンコーディングを使用する代わりに、固定長の文字を使用する方が良いです。 UNICODE文字列の方が良いかどうかを知りたいですか? whar_tまたはuint32_t?私の答えはwchar_tです。しかし、それは正しいか間違った選択ですか? –

+1

間違っています。 'uint32_t'を使います。あなたの 'wchar_t'にはサイズ保証はありません。あなたがこの主題について一般に興味があるなら、[私の最近の暴言](http://stackoverflow.com/questions/6300804/wchars-encodings-standards-and-portability)をチェックしてください。 –

+0

しかし、なぜマイクロソフトではUnicodeにwchar_tを使用していますか? –

4

あなたは単純にできません。このようなクエリがたくさん必要な場合は、UTF-8文字列の索引を作成するか、UTF-32を先頭に変換できます。 UTF-32はメモリ上の表現が優れていますが、UTF-8はディスク上で優れています。

ところで、あなたがUTF-16用にリストアップしたコードは正しくありません。あなたは代理キャラクターの世話をしたいかもしれません。

+0

UTF-32は、個々の文字を処理する必要がある場合に便利です。ほとんどの場合、気にしないで、前後に文字列を移動したいだけなので、UTF-8が拡張されています。 – ninjalj

1

何を数えますか? Kerrek SBは、グリフを分解することができます。つまり、「é」は単一の文字(LATIN SMALL LETTER E WITH ACUTE U + 00E9)、または2つの文字(LATIN SMALL LETER E U + 0065 COMBINING ACUTE ACCENT U + 0301)として表すことができます。 Unicodeは正規化フォームを作成し、分解しました。あなたはおそらくカウントに興味がある何

文字ではありませんが、書記素クラスタ。これに対処し、正規化形式、適切な(ロケール依存の)照合、適切な改行、適切な大文字小文字の変換(例えばドイツ語β→SS)、適切な双方向のサポートなどに対処するには、より高いレベルのライブラリが必要です。リアルI18Nは複雑です。

+1

ユニコードの話題は、伝統的にこのような理由で「文字」を使用する可能性のある「コードポイント」を使用します。歴史的な手荷物は、 graphemes/glyphs/grapheme clusters/ligatures /を区別したいときはあいまいです。 –

0

UTF-8の代わりにUTF-32を使用すると、他の人が言っていたのとはまったく違いがありません。テキストを処理するときには、graphemeクラスタ(または「ユーザーが知覚する文字」) UTF-32であっても、可変長コーディングとして扱われなければならない。

専用ライブラリを使用したくない場合は、オンディスク、エンディアンに依存しない表現、変更されたUTF-8(UTF-8とは異なり、ゼロ文字を2 -byteシーケンス)をASCIIZと互換性のあるメモリ内表現として使用します。

文字列を書記素クラスタに分割するために必要な情報は、annex 29character databaseにあります。

関連する問題