普段使うのは MultiByteToWideChar とかな自分です。
変換関数は CのランタイムとWin32 API が用意されているけど、確か挙動が違うとどっかに書いてあったんだよね。
ぐぐったら出てきました -> 理ろぐ
自分で調べてなかったので、調べたくなりました。コードは 理ろぐ のを改造。
結論から言うと、locale 設定するだけでどちらでも正しい結果が出ます。
まぁ、ここまでが序章。
locale 設定しなくても Win32 API の方は正しく動いているように見えますので確認します。
-
#include <iostream>
-
#include <locale>
-
#include <iomanip>
-
#include <stdlib .h>
-
#include <windows .h>
-
-
using namespace std;
-
const int ARRAY_SIZE = 64;
-
-
std::ostream& couthex(const int n) {
-
return cout <<"Ox" <<setw(n) <<setfill('0') <<setbase(16);
-
}
-
-
-
void dump(unsigned char *data) {
-
for (int i=0; ; i++) {
-
if (i%16 == 0 && i != 0) cout <<endl;
-
couthex(2) <<static_cast<int>(*(data+i)) <<" " <<flush;
-
-
if ((*(data+i) == 0) && (*(data+i+1) == 0)) break;
-
}
-
-
cout <<endl <<endl;
-
}
-
-
-
bool charToWchar(const char* src, wchar_t* dst1, wchar_t* dst2) {
-
::ZeroMemory(dst1, sizeof(wchar_t) * ARRAY_SIZE);
-
::ZeroMemory(dst2, sizeof(wchar_t) * ARRAY_SIZE);
-
-
bool retval = true;
-
if (::mbstowcs(dst1, src, sizeof(wchar_t) * ARRAY_SIZE) == -1) {
-
cout <<"mbstowcs : error" <<endl;
-
retval = false;
-
}
-
-
if (::MultiByteToWideChar(CP_ACP, 0, src, -1, dst2, sizeof(wchar_t)* ARRAY_SIZE) == 0) {
-
cout <<"MultiByteToWideChar : error" <<endl;
-
retval = false;
-
}
-
-
return true;
-
}
-
-
-
bool wcharToChar(const wchar_t* src, char* dst1, char* dst2) {
-
::ZeroMemory(dst1, sizeof(char) * ARRAY_SIZE);
-
::ZeroMemory(dst2, sizeof(char) * ARRAY_SIZE);
-
-
bool retval = true;
-
-
if (::wcstombs(dst1, src, sizeof(char) * ARRAY_SIZE) == -1) {
-
cout <<"wcstombs : error" <<endl;
-
retval = false;
-
}
-
-
-
if (::WideCharToMultiByte(CP_ACP, 0, src, -1, dst2, sizeof(char)* ARRAY_SIZE, 0, 0) == 0) {
-
cout <<"WideCharToMultiByte : error" <<endl;
-
retval = false;
-
}
-
-
return true;
-
}
-
-
-
int main(int argc, char** argv)
-
{
-
const char csrc[] = "Mrブギータンブリンマン";
-
const wchar_t wsrc[] = L"Mrブギータンブリンマン";
-
char cdst1[ARRAY_SIZE] = "";
-
char cdst2[ARRAY_SIZE] = "";
-
wchar_t wdst1[ARRAY_SIZE] = L"";
-
wchar_t wdst2[ARRAY_SIZE] = L"";
-
-
// 1ループ目はロケール設定なし
-
// 2ループ目はロケール設定あり
-
for (int i=0; i<2; i++) {
-
// マルチバイト文字 -> ワイド文字
-
{
-
charToWchar(csrc, wdst1, wdst2);
-
cout <<"mbstowcs : " <<endl;
-
dump(reinterpret_cast<unsigned char*>(wdst1));
-
cout <<"MultiByteToWideChar : " <<endl;
-
dump(reinterpret_cast<unsigned char*>(wdst2));
-
}
-
// ワイド文字 -> マルチバイト文字
-
{
-
wcharToChar(wsrc, cdst1, cdst2);
-
cout <<"wcstombs : " <<endl;
-
dump(reinterpret_cast<unsigned char*>(cdst1));
-
cout <<"WideCharToMultiByte : " <<endl;
-
dump(reinterpret_cast<unsigned char*>(cdst2));
-
}
-
-
// locale 設定
-
cout <<"-- set locale --" <<endl;
-
locale::global(std::locale("japanese"));
-
}
-
-
return 0;
-
}
実行結果
mbstowcs :
Ox4d Ox00 Ox72 Ox00 Ox83 Ox00 Ox75 Ox00 Ox83 Ox00 Ox4d Ox00 Ox81 Ox00 Ox5b Ox00
Ox83 Ox00 Ox5e Ox00 Ox83 Ox00 Ox93 Ox00 Ox83 Ox00 Ox75 Ox00 Ox83 Ox00 Ox8a Ox00
Ox83 Ox00 Ox93 Ox00 Ox83 Ox00 Ox7d Ox00 Ox83 Ox00 Ox93 Ox00MultiByteToWideChar :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00wcstombs : error
wcstombs :
Ox4d Ox72 Ox00WideCharToMultiByte :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00-- set locale --
mbstowcs :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00MultiByteToWideChar :
Ox4d Ox00 Ox72 Ox00 Oxd6 Ox30 Oxae Ox30 Oxfc Ox30 Oxbf Ox30 Oxf3 Ox30 Oxd6 Ox30
Oxea Ox30 Oxf3 Ox30 Oxde Ox30 Oxf3 Ox30 Ox00wcstombs :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00WideCharToMultiByte :
Ox4d Ox72 Ox83 Ox75 Ox83 Ox4d Ox81 Ox5b Ox83 Ox5e Ox83 Ox93 Ox83 Ox75 Ox83 Ox8a
Ox83 Ox93 Ox83 Ox7d Ox83 Ox93 Ox00
VS2008 st でコンパイルしました。
cl /EHsc /DWIN32 /MD /D_NODEBUG /D_CONSOLE convert.cpp
ちとソースが長いですが、結果を見ると locale 設定前でも Win32 API の方の変換は正しいことが確認できます。
ランタイムの方は locale を設定しないと、変換エラー出てますね。 (wcstombs)
windows で文字列の変換を行うときは Win32 API がよさそうですね。 Continue reading ‘VisualStudio でのマルチバイト文字とワイド文字の変換’ »

