Win32/64技術 003 ワイド文字列→マルチバイト文字列変換

提供:yonewiki

Win32/64_アプリケーション開発に戻る。

前の記事:Win32/64技術 002 WinUser.hファイルを読み込んでもGWL_HINSTANCEが使えない

次の記事:Win32/64技術 004 文字列グローバル変数にHGLOBALを使う一例

概要

 この記事はC++(Cpp)言語での技術説明です。ワイド文字のUTF-16から変換してマルチバイトのSJIS(Shift_JIS、Microsoft提唱のコードページcp932とも呼ばれる)やUTF-8に変換する方法です。MultiByteToWideChar関数にあい対する関数WideCharToMultiByteを使います。


    wchar_t pwchstr[] = L"Win32/64アプリケーション";

    int icharLen = WideCharToMultiByte(932, 0, pwchstr, -1, nullptr, 0, nullptr, nullptr);
    char* chstr = new char[icharLen];
    WideCharToMultiByte(932, 0, pwchstr, -1, chstr, icharLen, nullptr, nullptr);


標準string型 wstring型を使う場合(推奨)

    wchar_t pwchstr[] = L"Win32/64アプリケーション";
    std::wstring wstringUTF16str = std::wstring(pwchstr);

    int icharLen = WideCharToMultiByte(932, 0, wstringUTF16str.c_str(), -1, nullptr, 0, nullptr, nullptr);
    std::string stringSJISstr(icharLen, 0);
    WideCharToMultiByte(932, 0, wstringUTF16str.c_str(), -1, stringSJISstr.c_str(), stringSJISstr.size(), nullptr, nullptr);


WideCharToMultiByte

■WideCharToMultiByte(UINT, DWORD, LPCWCH, int, LPSTR, int, LPCCH, LPBOOL)

第1引数:UINT CodePage

 文字コードの変換もできます。この関数では変換先の文字コードを指定します。逆変換では、変換元の文字コードを指定していました。


第2引数:DWORD dwFlags

  • WC_COMPOSITECHECK:合成文字を検査するためのフラグです。正準分解形の0x0065(e) 0x0301(´)を検出し、きちんと合成文字のéを得ます。指定しない場合は、0x0065(e)と0x0301(´)を別々の文字として処理します。処理速度を犠牲にするので、そのような文字が含まれない場合は指定する必要はないでしょう。


  • WC_DEFAULTCHAR:変換中に、変換できない文字をデフォルトの文字(通常は?が使われます)に置き換えるためのフラグです。変換できない文字は、指定したコードページに存在しない場合などに発生することがあります。


  • WC_DISCARDNS:ノンスパース文字(Non-Spacing Character)を無視するためのフラグです。ノンスパース文字は、文字コード内で文字を修飾するために使用される文字で、変換中にこれらを無視することができます。合成文字の後ろの文字を無視して、情報が欠落するように変換されます。例えば、
  • é(eと´が組み合わさった合成文字)
  • â(aと^が組み合わさった合成文字)
  • ñ(nと~が組み合わさった合成文字)
  • ç(cと,が組み合わさった合成文字)
  • ü(uと¨が組み合わさった合成文字)
  • ß(sとβの合成)
  • ą(aとoストロークの組み合わせ)
  • Ż(Zと点付きコンビニング・フックの組み合わせ)
  • Œ(OとE合成)
  • ę(eとogonekの組み合わせ)
  • Ł(Lとbarの組み合わせ)
  • ș(sとcedillaの組み合わせ)
  • ș(tとcedillaの組み合わせ)
  • ǂ(2つの縦線の組み合わせ)
  • Č(Cとhacekの組み合わせ)
  • Š(Sとhacekの組み合わせ)
  • Ž(Zとhacekの組み合わせ)
  • ƒ(fとcrossの組み合わせ)
  • ₹(RとIndian Rupeeの組み合わせ)
  • ☺(smiley faceアイコン)

とかがあります。


  • WC_SEPCHARS:パススルー文字を処理するためのフラグです。パススルー文字は、変換されずにそのまま出力される特定の文字です。このフラグを指定すると、パススルー文字が正しく処理されます。パススルー文字とは制御文字やエスケープシーケンスや特殊文字のことを差します。ANSIエスケープシーケンスの\x1B[31m(テキストの色を赤に変更するエスケープ シーケンス)やVT100エスケープ シーケンス"\x1B[2J"(画面クリア)があります。\u00E9のようなユニコードエスケープシーケンスも該当します。\n、\r、\t、\a(ベル音)、\b(カーソルを前に移動)、\0(ヌル文字)、'、"、\エスケープシーケンス程度ならコードページの変換をしても情報が失われることは少ないので、フラグを指定する必要はありません。


  • WC_NO_BEST_FIT_CHARS:このフラグを指定すると、ベストフィット文字が使用されず、文字が失われる可能性があります。ワイド文字のé(U+00E9)を変換する場合、ISO 8859-1(Latin-1)ではベストフィット文字として "é"(0xE9)が使われ、 ISO 8859-5(Cyrillic)の場合、ベストフィット文字として "?"(0x3F)が使用されるかもしれないです。このようなベストフィットを使用しないで文字を喪失する方法を選ぶことができます。


  • WC_ERR_INVALID_CHARS フラグを指定すると、変換中に無効な文字が検出された場合にエラーを発生させることができます。UTF-16はUnicodeという広範囲な文字セットですので、より小さな文字セットに変換する場合は存在しない文字コードもあります。その場合処理を止める必要があるなら、このフラグが必要です。


第3引数:LPCWCH lpWideCharStr

 変換元のワイド文字列型変数の先頭アドレスです。


第4引数:int cchWideChar

 変換元の文字列の先頭からの変換する文字数を指定します。\0終端の文字列であれば-1を指定すれば、最後までが変換対象になります。


第5引数:LPSTR lpMultiByteStr

 変換先マルチバイト文字列変数の先頭アドレスを指定します。


第6引数:int cbMultiByte

 第5引数の変換先マルチバイト文字列変数が確保しているメモリのバイト数を指定します。


第7引数:LPCCH lpDefaultChar

 変換先の文字が無い時のデフォルト変換文字を指定します。このデフォルト変換文字を使うという場合には第二引数のFlagは0でも大丈夫です。


第8引数:LPBOOL lpUsedDefaultChar

 BOOL usedDefaultChar = FALSE;のようにしておいたBOOL変数のアドレスを指定します。&usedDefaultCharとなります。デフォルト文字が使われたらTRUEが格納されます。

 

前の記事:Win32/64技術 002 WinUser.hファイルを読み込んでもGWL_HINSTANCEが使えない

次の記事:Win32/64技術 004 文字列グローバル変数にHGLOBALを使う一例

Win32/64_アプリケーション開発に戻る。