Win32/64技術 001 マルチバイト文字列→ワイド文字列変換
概要
マルチバイト文字列をワイド文字列に変換する手法についてです。
char pchstr[] = "Win32/64アプリケーション";
int iwcharLen = MultiByteToWideChar(932, 0, pchstr, -1, nullptr, 0);
wchar_t* wchstr = new wchar_t[iwcharLen];
MultiByteToWideChar(932, 0, pchstr, -1, wchstr, iwcharLen);
標準string型 wstring型を使う場合(推奨)
char pchstr[] = "Win32/64アプリケーション";
std::string stringSJISstr = std::string(pchstr);
int iwcharLen = MultiByteToWideChar(932, 0, stringSJISstr.c_str(), -1, nullptr, 0);
std::wstring wstringUTF16str(iwcharLen, 0);
MultiByteToWideChar(932, 0, stringSJISstr.c_str(), -1, &wstringUTF16str[0], iwcharLen);
※エラー処理、例外処理は適宜挿入されたし。
■MultiByteToWideChar(UINT, DWORD, LPCCH, int, LPWSTR, int)
第1引数: UINT CodePage
文字コードの変換もできます。この関数では元の文字コードを指定します。この変換では規模の小さいコードセットであるSJIS系から大規模なコードセットUTF-16への変換によく使われますので、変換先が無いということにはならないです。逆変換のときはUTF-16から任意の文字コードに変換出来ます。VisualStudioは主にShiftJISで処理されています。MicrosoftのShiftJISである932を指定しないと、文字化けが発生します。変換後はワイド文字はUTF-16を使います。UTF-8は可変バイトの1バイトか3バイトで主に表され、ごく稀に4バイトになります。UTF-16も万能ではありません。サロゲートペアを駆使しないとU+10000以降の文字は表せません。例えばU+13001を表現したいときは、0xD830 0xDC01 となります。ユニコード値から10000を引いて3001ですから、0xD8に続けて3001の上位8バイト30を挿入し、0xDCの後ろに下位8バイトの01を挿入します。これがサロゲートペアね。UTF-32こそが全ての文字をそのまま表せる4バイト文字の集まりなのです。万能は言い過ぎたわ。容量は喰いますからね。それにUTF-32に対応したエディタはほぼ存在しません。char型でデバッグ時にも変数にカーソルを当てて表示されるポップアップのクイックウォッチでも文字化けが発生しますし、開発期間中はマルチバイト文字は932文字コードセットの範囲で試すのがおすすめだな。でも意識出来ないんなら危険な使い方ですね。変数の内容を確認するデバッグビューにある自動、ローカル、クイックタブでも文字化けした状態になります。主にCP_UTF8を使う場合はVisualStudioの設定を変更しないといけませんかね。そんなやり方があるのかさえ知りませんけど。今度暇な時にでも調べてみるかな。ファイルに出力したり、試しにUTF-8が元々の値として確かめる場合はリテラルはu8プレフィックス使ったりするんでしょう。ShiftJISだけでは、表現できない文字はありますからね。ファイルにそのまま出力して、UTF-8の文字コードを閲覧できるビューワで開くといった作業が必要です。WindowsもUTF-8を標準にしたらいいのにとも思いますがUTF-8はほぼ3バイト文字になるのでハードディスクの空き容量減るかも知れませんね。Microsoftも簡単には舵を切れないところなのかな。
第2引数: DWORD dwFlags
変換の種類を示すフラグ。
MB_PRECOMPOSED (0x0001): 正準分解形ではなく、eの上にアクセント´が付いたりするようなéといった合成済み文字を返します。合成済み文字は、文字の形を正準分解形よりも既定で合成された形にします。
MB_COMPOSITE (0x0002): 文字列を正準分解形ではなく合成済み文字で返します。正準分解形とは、複数の合成可能な文字から構成された文字をそれらの基本的な形に変換するものです。
MB_USEGLYPHCHARS (0x0004): 一般的な標準文字(GLYPHCHAR)を使用するためのものです。これにより、標準文字として扱われる特定の文字を返します。
MB_ERR_INVALID_CHARS (0x0008): 無効な文字(マルチバイト文字として表現できない文字)が見つかった場合にエラーを発生させます。
MB_PRECOMPOSED | MB_ERR_INVALID_CHARS (0x0009)の2つのフラグを組み合わせたもの:無効な文字の検出と合成済み文字の使用が可能になります。
MB_COMPOSITE | MB_ERR_INVALID_CHARS (0x0010)の合成済み文字と無効な文字の検出を組み合わせたもの:
第3引数: LPCCH lpMultiByteStr
変換する文字列(char配列)へのポインター。
第4引数: int cbMultiByte
-1の場合は元の文字列の終端に\0があるところまで変換します。0の場合は変換が失敗します。正の数の場合は指定されたバイト数まで変換をします。
第5引数: LPWSTR lpWideCharStr
変換後の文字列(wchar_t配列)へのポインター。
第6引数: int cchWideChar
第5引数の文字列のバイト数を設定します。\0の1バイトも含めた値です。第6引数が0のときは、変換後必要になる文字列のバイト数を戻り値にします。
関数が成功した場合は、バッファーに書き込まれた文字数が返却されます。
この関数はWINAPIの関数です。<windows.h>を読み込んでおけば使えます。良く似た関数にはmbstowcs_sという関数が有ります。逆変換はWideCharToMultiByteが対応していて良く似た関数もwcstombs_sというのがあります。