11

後でLinuxプラットフォームにも移行することを目的として、Windowsでテキストサポートを実装しようとしています。国際言語を統一的にサポートすることが理想的ですが、問題の2つのプラットフォームを考慮すると、それは簡単には達成できないようです。UNICODE、UTF-8(およびその他のエンコーディング)、widecharsなどについてかなりの時間を費やしてきましたが、これまでに理解したことは次のとおりです。

UNICODEは、標準として、マップ可能な文字のセットとそれらが出現する順序を記述します。私はこれを「何」と呼んでいます。UNICODEはが利用可能になるかを指定します。

UTF-8(およびその他のエンコーディング)は、次の方法を指定します。各文字をバイナリ形式で表現する方法。

現在、Windowsでは、元々UCS-2エンコーディングを選択していましたが、要件を満たせなかったため、UTF-16があり、必要に応じて複数文字も使用できます。

だからここにデレンマがあります:

  1. Windowsは内部的にUTF-16のみを実行するため、国際文字をサポートする場合は、それに応じてOS呼び出しを使用するためにwidecharバージョンに変換する必要があります。マルチバイトのUTF-8文字列を使用してCreateFileA()のようなものを呼び出し、適切に表示されるようにするためのサポートはないようです。これは正しいです?
  2. Cには、いくつかのマルチバイトサポート関数(_mbscat、_mbscpyなど)がありますが、Windowsでは、文字タイプはそれらの関数のunsignedchar*として定義されます。_mbsシリーズの関数が完全なセットではない(つまり、マルチバイト文字列をlongに変換する_mbstolがない)という事実を考えると、ランタイム関数のchar*バージョンの一部を使用する必要があります。これらの関数間の符号付き/符号なしの型の違いにより、コンパイラの問題が発生します。誰かがそれらを使用していますか?エラーを回避するために、大量のキャストを行うだけですか?
  3. C ++では、std :: stringにイテレータがありますが、これらはコードポイントではなく、char_typeに基づいています。したがって、std :: string :: iteratorで++を実行すると、次のコードポイントではなく、次のchar_typeが取得されます。同様に、std :: string :: operator []を呼び出すと、char_typeへの参照が取得されます。これは、完全なコードポイントではない可能性が非常に高くなります。では、コードポイントごとにstd :: stringをどのように繰り返すのでしょうか?(Cには_mbsinc()関数があります)。
4

3 に答える 3

10

UTF-8を実行するだけです

すべてのプラットフォームにUTF-8のサポートライブラリがたくさんあり、マルチプラットフォームもあります。Win32のUTF-16APIは制限されており、すでに述べたように一貫性がないため、すべてをUTF-8に保持し、最後にUTF-16に変換することをお勧めします。WindowsAPI用の便利なUTF-8ラッピングもいくつかあります。

また、アプリケーションレベルのドキュメントでは、UTF-8が標準としてますます受け入れられるようになっています。すべてのテキスト処理アプリケーションはUTF-8を受け入れるか、最悪の場合「いくつかの絵記号を含むASCII」として表示しますが、UTF-16ドキュメントをサポートするアプリケーションはごくわずかであり、サポートしないアプリケーションは「たくさん」と表示します。空白の!」

于 2012-10-26T16:07:09.807 に答える
8
  1. 正しい。Windows API呼び出し用に、UTF-8をUTF-16に変換します。

  2. ほとんどの場合、UTF-8には通常の文字列関数を使用します- strlenstrcpy(ick)snprintf、、strtol。UTF-8文字で正常に動作します。UTF-8を使用するかchar *、すべてをキャストする必要があります。

    のようなアンダースコアバージョン_mbstowcsは標準ではないことに注意してください。通常、のようにアンダースコアなしで名前が付けられmbstowcsます。

  3. Unicode文字列で実際に使用したい例を思い付くのは難しいのでoperator[]、私のアドバイスはそれを避けることです。同様に、文字列を反復処理する用途は驚くほど少ないです。

    • 文字列を解析している場合(たとえば、文字列がCまたはJavaScriptコードである場合、構文を強調表示したい場合)、ほとんどの作業をバイト単位で実行し、マルチバイトの側面を無視できます。

    • 検索を行う場合は、これもバイトごとに行います(ただし、最初に正規化することを忘れないでください)。

    • 単語の区切りや書記素クラスターの境界を探している場合は、ICUなどのライブラリを使用することをお勧めします。アルゴリズムは単純ではありません。

    • 最後に、テキストのチャンクをいつでもUTF-32に変換して、そのように操作できます。照合や解読などのUnicodeアルゴリズムのいずれかを実装している場合、これが最も適切なオプションだと思います。

    参照:C ++はUTF-8文字列をシンボルの配列に反復または分割しますか?

于 2012-10-26T16:05:38.013 に答える
2
  1. Windowsは内部的にUTF-16のみを実行するため、国際文字をサポートする場合は、それに応じてOS呼び出しを使用するためにwidecharバージョンに変換する必要があります。マルチバイトのUTF-8文字列を使用してCreateFileA()のようなものを呼び出し、適切に表示されるようにするためのサポートはないようです。これは正しいです?

それは正解です。関数バリアントは*A、現在アクティブなコードページ(米国および西ヨーロッパのほとんどのコンピューターではWindows-1252ですが、他のコードページである場合もあります)に従って文字列パラメーターを解釈し、UTF-16に変換します。UTF-8コードページがありますが、アクティブなコードページをプログラムで設定する方法はありません(アクティブなコードページGetACPを取得する方法はありますが、対応していませんSetACP)。

  1. Cには、いくつかのマルチバイトサポート関数(_mbscat、_mbscpyなど)がありますが、Windowsでは、文字タイプはそれらの関数のunsignedchar*として定義されます。_mbsシリーズの関数が完全なセットではない(つまり、マルチバイト文字列をlongに変換する_mbstolがない)という事実を考えると、ランタイム関数のchar*バージョンの一部を使用する必要があります。これらの関数間の符号付き/符号なしの型の違いにより、コンパイラの問題が発生します。誰かがそれらを使用していますか?エラーを回避するために、大量のキャストを行うだけですか?

私の経験では、関数のmbs*ファミリーはほとんど使用されていません。、、、およびを除いてmbstowcs、これらの関数は標準のCではありません。mbsrtowcsmbsinit

  1. C ++では、std :: stringにイテレータがありますが、これらはコードポイントではなく、char_typeに基づいています。したがって、std :: string :: iteratorで++を実行すると、次のコードポイントではなく、次のchar_typeが取得されます。同様に、std :: string :: operator []を呼び出すと、char_typeへの参照が取得されます。これは、完全なコードポイントではない可能性が非常に高くなります。では、コードポイントごとにstd :: stringをどのように繰り返すのでしょうか?(Cには_mbsinc()関数があります)。

mbrtowc(3)マルチバイト文字列の単一のコードポイントをデコードするには、これがここでの最良のオプションだと思います。

全体として、クロスプラットフォームのUnicode互換性のための最善の戦略は、UTF-8のすべてを内部でシングルバイト文字を使用して実行することだと思います。Windows API関数を呼び出す必要がある場合は、それをUTF-16に変換し、常に*Wバリアントを呼び出します。Windows以外のほとんどのプラットフォームはすでにUTF-8を使用しているため、これらを簡単に使用できます。

于 2012-10-26T16:04:49.607 に答える