1

だから私は標準のC文字列を持っています:

char* name = "Jakub";

そして、それをUTF-16に変換したいと思います。UTF-16の長さは2倍になることがわかりました。1文字で2文字かかります。
だから私は別の文字列を作成します:

char name_utf_16[10];  //"Jakub" is 5 characters

今、私はASCII文字では下位バイトのみを使用すると信じているので、それらすべてについては74 00forJなどのようになります。その信念で、私はそのようなコードを作ることができます:

void charToUtf16(char* input, char* output, int length) {
    /*Todo: how to check if output is long enough?*/
    for(int i=0; i<length; i+=2)  //Step over 2 bytes
    {
        //Lets use little-endian - smallest bytes first
        output[i] = input[i];
        output[i+1] = 0;  //We will never have any data for this field
    }
}

しかし、このプロセスで、私はで終わりました"Jkb"。これを正しくテストする方法がわかりません。文字列をMinecraftBukkitサーバーに送信しました。そして、これは切断時にそれが言ったことです:

13:34:19[情報] jkbを切断していますか?? [/127.0.0.1:53215]:古いサーバーです!

注: Minecraftがビッグエンディアンを使用していることは承知しています。上記のコードは単なる例です。実際、私は変換をクラスに実装しています。

4

3 に答える 3

6

私があなたの質問に答える前に、これを考慮してください:

プログラミングのこの領域は、人間の罠でいっぱいです。ASCII、UTF7 / 8、およびANSI /「マルチバイト文字列(MBCS)」の違いを理解することは非常に理にかなっています。これらはすべて、英語を話すプログラマーにとっては見た目も感じも同じですが、ヨーロッパまたはアジアのユーザーに紹介されました。

ASCII:文字の範囲は32〜127です。たった1バイト。手がかりはその名のとおりであり、アメリカ人にとっては素晴らしいものですが、世界の他の地域では目的に適合していません。

ANSI / MBCS:これが「コードページ」の理由です。文字32〜127はASCIIと同じですが、128〜255の範囲の文字を追加文字として使用することもできます。また、128〜255の範囲の一部を、文字が継続することを示すフラグとして使用できます。 2番目、3番目、さらには4番目のバイトに。文字列を正しく処理するには、文字列バイトと正しいコードページの両方が必要です。間違ったコードページを使用して文字列を処理しようとすると、正しい文字が得られず、文字が1バイト、2バイト、または4バイトの文字であるかどうかを誤って解釈します。

UTF7 / 8:これらは21ビットのUnicode文字ポイントの8ビット幅のフォーマットです。UTF-7およびUTF-8では、Unicode文字の長さは1〜4バイトです。UTFエンコーディングがANSI/MBCSに勝る利点は、コードページによって引き起こされるあいまいさがないことです。すべてのスクリプトの各グリフには一意のユニコードコードポイントがあります。つまり、地域の設定が異なる別のコンピューター上のデータを解釈して文字セットをマングルすることはできません。

だからあなたの質問に答え始めるために:

  1. char *がASCII文字列のみを指すと想定している間、これは非常に危険な選択ですが、ユーザーはプログラマーではなく、入力されたデータを制御できます。Windowsプログラムは、これをデフォルトでMBCSとして保存します。

  2. 2番目の仮定は、UTF-16エンコーディングが8ビットエンコーディングの2倍のサイズになるということです。これは一般的に安全な仮定ではありません。ソースエンコーディングによっては、UTF-16エンコーディングのサイズが2倍になる場合と、サイズが2倍未満になる場合があります。極端な例では、実際には長さが短くなる場合があります。

それで、安全な解決策は何ですか?

安全なオプションは、アプリケーションをユニコードとして内部的に実装することです。Windowsでは、これはコンパイラオプションであり、Windowsコントロールがすべてデータ型にwchar_t*文字列を使用することを意味します。Linuxでは、いつでも統一されたグラフィックスとOSライブラリを使用できるかどうか確信が持てません。また、wcslen()関数を使用して、文字列の長さなどを取得する必要があります。外部と対話するときは、使用する文字エンコードを正確に指定してください。

あなたの質問に答えるには、質問を次のように変更します。UTF-16以外のデータを受け取った場合はどうすればよいですか?

まず、フォーマットについてどのような仮定をしているのかを明確にしますか?次に、UTF-16への変換が失敗する場合があるという事実を受け入れます。

ソースのフォーマットが明確な場合は、適切なwin32またはstlコンバーターを選択してフォーマットを変換し、結果を使用する前に変換が失敗した証拠を探す必要があります。たとえば、Windowsのmbstowcs inまたはMultiByteToWideChar()。ただし、これらのアプローチの両方を安全に使用することは、上記のすべての答えを理解する必要があることを意味します。

他のすべてのオプションはリスクをもたらします。mbcs文字列を使用すると、1つのコードページを使用して入力し、別のコードページを使用してデータ文字列を処理することができます。ASCIIデータを想定すると、ASCII以外の文字に遭遇すると、コードが壊れ、ユーザーの短所を「非難」します。

于 2013-09-04T09:08:07.863 に答える
5

mbstowcs()に含まれているような既存のC/C ++関数があるのに、なぜ独自のUnicode変換機能を作成したいのですか<cstdlib>

それでも独自のものを作成したい場合は、Unicodeコンソーシアムのオープンソースコードをご覧ください。これは次の場所にあります。

CのWindowsおよびLinuxでUTF-16をUTF-8に変換する

于 2013-03-16T13:39:36.477 に答える
0
output[i] = input[i];

これにより、2ずつインクリメントされるため、入力の1バイトおきに割り当てられますi。したがって、を取得するのも不思議ではありません"Jkb"。あなたはおそらく書きたかったでしょう:

output[i] = input[i / 2];
于 2013-03-16T13:26:03.823 に答える