EntryNavi : « 可変個引数の関数 | メイン | WindowsCE5.0でパラレルポートを使用する »

CategoryNavi : メイン -> コンピューター -> 開発 -> C/C++

Windowsにおけるマルチバイト文字とワイド文字の変換

Win2kやXPとかCEでは、基本的にワイド文字を扱っていますのでインターフェースなどで入力された 文字列を使う時にマルチバイト文字へ変換しないといけないと思います。
で、変換関数についてです。

ワイド→マルチの変換では
・wcstombs
・WideCharToMultiByte
マルチ→ワイドの変換では
・mbstowcs
・MultiByteToWideChar
があります。
それぞれ上はCのランタイムで下はWin32 APIです。

結論から申しまして、少なくともマイクロソフトの提供するランタイムは役に立ちません。
必ずAPIを使用しましょう。
環境は「Visual C++ 2005 ExpressEdition + PlatformSDK」です。
使用方法のサンプルがてらソースとその実行結果です。


#include <stdlib.h>
#include <windows.h>

void CheckCharConvert()
{
char string_m[256];
wchar_t string_w[256];
wchar_t string_w2[256];

wcscpy(string_w,_T("ワイド→マルチ / Wide to Multi"));
wprintf(_T("Wide :%s\n"),string_w);

ZeroMemory(string_m,sizeof(string_m));
if(wcstombs(string_m,string_w,sizeof(string_m)-1) == -1){ //ワイド文字→マルチバイト文字
printf("wcstombs :変換エラー\n");
}else{
printf( "wcstombs :%s\n",string_m);
}

ZeroMemory(string_m,sizeof(string_m));
if(WideCharToMultiByte(CP_ACP,0,string_w,wcslen(string_w),string_m,sizeof(string_m)-1,0,0) == 0){ //ワイド文字→マルチバイト文字
printf("WideCharToMultiByte:変換エラー\n");
}else{
printf( "WideCharToMultiByte:%s\n",string_m);
}


strcpy(string_m,"マルチ→ワイド / Multi to Wide");
printf( "Multi :%s\n",string_m);

ZeroMemory(string_w,sizeof(string_w));
if(mbstowcs(string_w,string_m,sizeof(string_w)) == -1){ //マルチバイト文字→ワイド文字
printf("mbstowcs :変換エラー\n");
}else{
wprintf(_T("mbstowcs :%s\n"),string_w);
}

ZeroMemory(string_w2,sizeof(string_w2));
if(MultiByteToWideChar(CP_ACP,0,string_m,-1,string_w2,(int)(sizeof(string_w2)/sizeof(wchar_t))-1) == 0){ //マルチバイト文字→ワイド文字
printf("MultiByteToWideChar:変換エラー\n");
}else{
wprintf( _T("MultiByteToWideChar:%s\n"),string_w2);
}

printf("\n");
printf("mbstowcs:\n");
dump((unsigned char*)string_w);
printf("MultiByteToWideChar:\n");
dump((unsigned char*)string_w2);
}

void dump(unsigned char *data)
{
while(*data != 0 || *(data+1) != 0){
printf("%02x ",*data);
data++;
}
printf("\n\n");
}


以下が実行結果です。
Wide :??????? / Wide to Multi
wcstombs :変換エラー
WideCharToMultiByte:ワイド→マルチ / Wide to Multi
Multi :マルチ→ワイド / Multi to Wide
mbstowcs :マルチ→ワイド / Multi to Wide
MultiByteToWideChar:??????? / Multi to Wide

mbstowcs:
ffffff83 00000000 0000007d 00000000 ffffff83 00000000 ffffff8b 00000000
ffffff83 00000000 00000060 00000000 ffffff81 00000000 ffffffa8 00000000
ffffff83 00000000 ffffff8f 00000000 ffffff83 00000000 00000043 00000000
ffffff83 00000000 00000068 00000000 00000020 00000000 0000002f 00000000
00000020 00000000 0000004d 00000000 00000075 00000000 0000006c 00000000
00000074 00000000 00000069 00000000 00000020 00000000 00000074 00000000
0000006f 00000000 00000020 00000000 00000057 00000000 00000069 00000000
00000064 00000000 00000065

MultiByteToWideChar:
ffffffde 00000030 ffffffeb 00000030 ffffffc1 00000030 ffffff92 00000021
ffffffef 00000030 ffffffa4 00000030 ffffffc9 00000030 00000020 00000000
0000002f 00000000 00000020 00000000 0000004d 00000000 00000075 00000000
0000006c 00000000 00000074 00000000 00000069 00000000 00000020 00000000
00000074 00000000 0000006f 00000000 00000020 00000000 00000057 00000000
00000069 00000000 00000064 00000000 00000065


DOSプロンプト上では、ワイド文字が表示できないようなので出力時に?になっていますがデバッグモードでは正しくデータがあるのを確認しています。
wcstombsは、変換できない文字にあたった時点でエラーになります。
逆に、mbstowcsは、DOSプロンプト上では変換できたように見えます。が、MultiByteToWideCharと変換結果が違います。最後にダンプを出力してみましたがぜんぜん違います。デバッガ上では後者の方が正しく見えます。
まったく持ってよくわかりません。

自分の使い方が悪いのでしょうか?


<Category : C/C++>

コメント (2)

匿名:

setlocaleはどうなってますか

理音:

すっごい今更ですが・・・匿名さんありがとうございます^^


_wsetlocale(LC_ALL, TEXT("japanese"));

で、対応可能です。
ちゃんと変換できるようになります。
_tprintfでプロンプトへの出力可能です。

コメントを投稿

検索

Google

サイドフィード

track feed 理ろぐ
人気ブログランキング - 理ろぐ
Powered by
Movable Type 3.34