C/C++中char*与wchar_t*的几种转换方法

原创文章,转载请注明出处https://blog.csdn.net/aaron_lyn1985/article/details/80053910


多字节(char*)和宽字符(wchar_t*)之间的转换有几种方式,下面按照从通用到特殊的顺序逐一介绍。

1.C库函数

1.1 关键函数

(1)setlocale() 
功能:配置地域化信息
头文件:

函数原型:

char *setlocale (int category, const char * locale); 
函数参数: 
category:表示对本地化的某项内容进行设置,可取如下值: 
LC_ALL 包括下面的全部选项都要
LC_COLLATE 配置字符串比较
C_CTYPE 配置字符类别及转换,例如全变大写 strtoupper()
LC_MONETARY 配置金融货币
LC_NUMERIC 配置小数点后的位数
LC_TIME 配置时间日期格式,与 strftime() 合用

locale:表示本地域代号
返回值:如果为NULL,则返回当前的locale名称(一般为C);如果非空,则根据category和locale进行设置,如果成功,则返回新的locale名称(地域名称),如果失败,则返回 NULL。

(2)wcstombs_s() 
功能:将宽字符编码字符串转换成多字节编码字符串 
头文件: < stdlib.h> 

函数原型:

errno_t __cdecl wcstombs_s(size_t * _PtNumOfCharConverted, char * _Dst, size_t _DstSizeInBytes, const wchar_t * _Src, size_t _MaxCountInBytes);

函数参数: 
PtNumOfCharConverted:指向转换后的字符串的长度加上结束符(单位字节)
Dst:指向转换后的字符串首地址
DstSizeInBytes:目的地址最大字节空间(单位字节) 
_Src:源宽字符串首地址
_MaxCountInBytes:最多可存入多字节字符串缓冲最的字节数,用于裁剪转换后的字符串
返回值:成功返回0, 失败则返回失败代码

(3)mbstowcs_s () 
函数功能:将多字节编码字符串转换成宽字符编码字符串 
头文件: 

函数原型:

errno_t __cdecl mbstowcs_s(size_t * _PtNumOfCharConverted, wchar_t * _DstBuf, size_t _SizeInWords, const char * _SrcBuf, size_t _MaxCount );

参数说明: 
PtNumOfCharConverted:指向转换后的字符串的长度加上结束符(单位wchar_t)
_DstBuf:指向转换后的字符串首地址
_SizeInWords:目的地址最大字符空间大小(单位wchar_t)
_SrcBuf:源多字节字符串首地址
_MaxCount:最多可存入宽字符串缓冲中的字符个数,用于裁剪转换后的宽字符串

返回值:成功返回0, 失败则返回失败代码

1.2 实例

实例用C++实现,是为了使用string和wstring作为参数或返回值,内部仍然是把string转换为char*,把wstring转换为wchar_t*

如需C版本只要截取函数内部char*和wchar_t*互相转换部分即可

#include 
#include 
#include 
using namespace std;

string ws2s(const wstring& ws)
{
    size_t convertedChars=0;
    string curLocale=setlocale(LC_ALL,NULL); //curLocale="C"
    setlocale(LC_ALL,"chs");
    const wchar_t* wcs = ws.c_str();
    size_t dByteNum=sizeof(wchar_t)*ws.size()+1;
    cout<<"ws.size():"<


2.Windows API

在Windows平台下,可以使用Windows提供的API进行转换。

2.1 关键函数

(1)WideCharToMultiByte() 
功能:将宽字符串转换成多字节字符串 
头文件: 

函数原型:

WINAPI
WideCharToMultiByte(
    _In_ UINT CodePage,
    _In_ DWORD dwFlags,
    _In_NLS_string_(cchWideChar) LPCWCH lpWideCharStr,
    _In_ int cchWideChar,
   _Out_writes_bytes_to_opt_(cbMultiByte, return) LPSTR lpMultiByteStr,
    _In_ int cbMultiByte,
    _In_opt_ LPCCH lpDefaultChar,
    _Out_opt_ LPBOOL lpUsedDefaultChar
);

函数参数: 
CodePage:指定执行转换的代码页字符集,可以为操作系统已安装或有效的任何代码页字符集,也可以指定其为下面的任意一值: 
CP_ACP:ANSI代码页;CP_ACP:ANSI代码页;CP_MACCP:Macintosh代码页;CP_OEMCP:OEM代码页;CP_SYMBOL:符号代码页;CP_THREAD_ACP:当前线程ANSI代码页;CP_UTF7:使用UTF-7转换;CP_UTF8:使用UTF-8转换。使用最多的就是CP_ACP和CP_UTF8; 
dwFlags:指定如何处理没有转换成功的字符,也可以不设此参数(设置为0),函数会运行的更快一些。对于UTF-8,dwflags必须为0或者WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,可以调用GetLastError获得
lpWideCharStr:待转换为宽字符串
cchWideChar:待转换的宽字符串的长度(字符个数),-1表示转换到字符串结尾
lpMultiByteStr:转换后目的字符串缓冲区
cbMultiByte:目的字符串缓冲区大小(单位字节)。如果设置为0,函数将返回所需缓冲区大小而忽略lpMultiByteSt 
lpDefaultChar:指向字符的指针,在指定编码里找不到相应字符时使用此字符作为默认字符替代。如果为NULL,则使用系统默认字符。使用dwFlags时不能使用此参数,否则报ERROR_INVLID_PARAMETER错误
lpUsedDefaultChar:开关变量的指针,表明是否使用过默认字符。对于要求此参数为NULL的dwflags而使用此参数,函数将失败返回,并设置错误码ERROR_INVLID_PARAMETER。lpDefaultChar和lpUsedDefaultChar都设为NULL,函数会更快一些

返回值:如果函数运行成功,并且cbMultiByte不为零,返回值是由 lpMultiByteStr指向的缓冲区中写入的字节数;如果函数运行成功,并且cbMultiByte为零,返回值是接存放目的字符串缓冲区所必需的字节数。如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

(2)MultiByteToWideChar() 
功能:多字节字符串到款字节字符串的转换; 
头文件: 

函数原型:

int WINAPI MultiByteToWideChar(
    _In_ UINT CodePage,
    _In_ DWORD dwFlags,
    _In_NLS_string_(cbMultiByte) LPCCH lpMultiByteStr,
    _In_ int cbMultiByte,
    _Out_writes_to_opt_(cchWideChar, return) LPWSTR lpWideCharStr,
    _In_ int cchWideChar
);

函数参数: 
CodePage:同上; 
dwFlags:指定是否转换成预制字符或合成的宽字符,是否使用象形文字替代控制字符,以及如何处理无效字符。对于UTF-8,dwflags必须为0或者WC_ERR_INVALID_CHARS,否则函数都将失败返回并设置错误码ERROR_INVALID_FLAGS,可以调用GetLastError获得
lpMultiByteStr:多字节字符串
cbMultiByte:待转换的多字节字符串长度,-1表示转换到字符串结尾
lpWideCharStr:存放转换后的宽字符串缓冲
cchWideChar:宽字符串缓冲的大小(单位字符数)

返回值:如果函数运行成功,并且cchWideChar不为零,返回值是由 lpWideCharStr指向的缓冲区中写入的字符数;如果函数运行成功,并且cchWideChar为零,返回值是接存放目的字符串缓冲区所必需的字符数。如果函数运行失败,返回值为零。若想获得更多错误信息,请调用GetLastError函数。

2.2 实例

#include 
#include 
using std::cout;
using std::wcout;
using std::locale;
using std::endl;

int main()
{
    //宽字符转多字节
    wchar_t *pws = L"我是宽字符串ABC";
    //第五个参数置NULL,用来计算多字节字符串需要的空间大小(单位字节,包括结束符)
    int bufSize = WideCharToMultiByte(CP_ACP,NULL,pws,-1,NULL,0,NULL,FALSE);
    cout<

2.3 关于locale设置

locale(即系统区域设置即国家或地区设置)将决定程序所使用的当前语言编码、日期格式、数字格式及其它与区域有关的设置,locale设置的正确与否将影响到程序中字符串处理(wchar_t如何输出、strftime()的格式等)。

C locale和C++ locale是独立的。C locale用setlocale(LC_CTYPE, “”)初始化。

C++ locale用std::locale::global(std::locale(“”))初始化。这样就可以根据当前运行环境正确设置locale。

其他更具体的介绍请参考C++中的locale设置。


3.Winidows ATL

ATL定义了两个转换宏A2W()和W2A(),可以更方便的在char*和wchar_t*之间转换。

头文件

USES_CONVERSION;  

char sz[] = "我是多字节string";
wchar_t *pWChar = A2W(sz);  

wchar_t wsz[] = L"我是宽字符string";
char *pChar = W2A(wsz);

备注:1. 需要先调用USES_CONVERSION宏,因为参数定义都在这里

          2. 转换宏内部使用栈空间内存,最大2M,所以不要循环调用防止溢出; 建议把A2W()和W2A()放到大括号里调用




你可能感兴趣的:(字符编码,原创)