wchar_t*和char*的转换

时间:2021-06-30 20:13:34
wchar_t *WStr = L"string to convert";
size_t len = wcslen(WStr) + 1;
size_t converted = 0;
char *CStr;
CStr=(char*)malloc(len*sizeof(char));
wcstombs_s(&converted, CStr, len, WStr, _TRUNCATE);
 

这时WStr中的内容将被转化为char版本储存在CStr中。



wcstombs和mbstowcs是C/C++的实现,WideCharToMultiByte和MultiByteToWideChar是Windows API的实现。



一、UNICODE转ANSI
char* WideChartoAnsi(wchar_t * pWideChar)
 {
      if (NULL == pWideChar)
           return NULL;
      char* pAnsi = NULL;
      int needBytes = WideCharToMultiByte(CP_ACP,0,pWideChar,-1, NULL,0, NULL, NULL);
      if (needBytes >0)
      {
           pAnsi = new char[needBytes + 1];
           ZeroMemory(pAnsi, needBytes + 1);
           WideCharToMultiByte(CP_ACP, 0, pWideChar, -1, pAnsi,needBytes, NULL, NULL);
      }
      return pAnsi;
 }

二、ANSI转UNICODE

wchar_t* MultiByteToWide(char* pMultiChar)
 {
       if (!pMultiChar)
            return NULL;
       wchar_t* pWideBuf = NULL;
       int needWideBytes = MultiByteToWideChar(CP_ACP, 0, pMultiChar, -1, NULL, NULL);
       if (needWideBytes >0)
       {
           pWideBuf = new wchar_t[needWideBytes + 1];
           ZeroMemory(pWideBuf, (needWideBytes+1) * sizeof(wchar_t));
          MultiByteToWideChar(CP_ACP, 0, pMultiChar, -1, pWideBuf, needWideBytes);
        }
        return pWideBuf;
 }


还需要注意缓冲的释放。否则内存泄露。





关于C++中的char*wchar_t*这两种类型的相互转换,网上说的大多很繁琐,可行性也不高。下面这个方法是在MSDN里面找到的,个人认为还比较不错:

 

char*转换为wchar_t*

stdlib.h中的mbstowcs_s函数,可以通过下面的例子了解其用法:

 

char *CStr = "string to convert";

size_t len = strlen(CStr) + 1;

size_t converted = 0;

wchar_t *WStr;

WStr=(wchar_t*)malloc(len*sizeof(wchar_t));

mbstowcs_s(&converted, WStr, len, CStr, _TRUNCATE);

 

其结果是WStr中储存了CStrwchar_t版本。

 

wchar_t*转换为char*

和上面的方法类似,用stdlib.h中的wcstombs_s函数,例子:

 

wchar_t *WStr = L"string to convert";

size_t len = wcslen(WStr) + 1;

size_t converted = 0;

char *CStr;

CStr=(char*)malloc(len*sizeof(char));

wcstombs_s(&converted, CStr, len, WStr, _TRUNCATE);

 

这时WStr中的内容将被转化为char版本储存在CStr中。

 

另外还可以通过流的方法来char*类型转换为wchar_t*类型,但这样的转换得到的结果将是const类型,而类似的方法不能将wchar_t*类型转换为char*类型。

 

把(constchar*转换为const wchar_t*

需要用到 sstream 头文件:

 

char *cstr="string to convert";

wstringstream wss;

wss<<cstr;

 

再调用wss.str().c_str(); 即可得到 const wchar_t* 类型的返回值。

 

虽然stringstream流不能将wchar_t*转换成char*,但可以用来进行数值类型和字符串之间的转换,例如:

 

double d=2734792.934f;

stringstream ss;

ss<<d;








  • CString和char*的转换及汉字乱码的解决 - [Windows\C++编程]

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://www.blogbus.com/hx1987-logs/211009970.html

    在VS2005及以上版本的编译器中,默认开启了宽字符UNICODE,这就增加了CString和char*之间的转换难度,在转换到到CString类型时,尤其是涉及到汉字等字符的操作时,有可能会出现乱码的形式。经过测试找到了几种比较简便的转换方式。CString主要包含三个部分:一个是指向某个数据缓冲区的指针,一个是该缓冲区中有效字符的个数,一个是该缓冲区的大小,其中有效字符的个数为0到缓冲区大小减1之间的任何一个整数,(CString也是C风格字符串形式,最后一个字符以\0结尾)。

    (1)     char*转换成CString类型

     

    方法一

    对于仅包括英语字符的字符串,只需要强制类型转换即可,可以使用static_cast完成,例

    char * pca = “hello”;

    CString cstr = static_cast(pca);

    注:1、这里可以直接相等来赋值是因为CString类里面重载了赋值操作符。

          2、若含有汉字等,则可能会出现乱码,但是单纯转换英文字符时则比较方便


    方法二

    对于含有汉字的字符串,可以采用A2W或者A2T函数

    char * pca = “测试”;

    USES_CONVERSION;

    CString cstr = A2W( pca );

    Or

    USES_CONVERSION;

    CString cstr = A2T( pca );

    注:该方法对于直接初始化的char *可以较好的转换,若对于经过其他处理后的char*可能会出现乱码的情况,比如说你的 char* 是经过strncpy拷贝过来的,则有可能出现问题(没有分析出原因),对于const char*,会尽可能的避免乱码的出现


    方法三

    采用MultiByteToWideChar函数进行转换

    MultiByteToWideChar可以将多字节字符串转换为宽字节字符,具体参数可以参考MSDN。

    例:

    char * pca = “Test”;

    size_t pcaLen = strlen(pca);

    //获取多字节字符串的字节数,不包括’\0’截止符

    int len = MultiByteToWideChar(CP_ACP, 0, cpc1, pcaLen, NULL, 0 );

    //申请UNICODE字符串的存储区

    TCHAR * ptChar = new TCHAR[len + 1];//加1包括进’\0’截止符

    MultiByteToWideChar r(CP_ACP, 0, pca , pcaLen, ptChar, len );

    ptChar[len] = ‘\0’;//单独添加’\0’截止符

    CString cstr( ptChar );

    Or

    CString cstr;

    Cstr.Append( ptChar );

    注:和方法二一样,该方法对于直接初始化的char *可以较好的转换,若对于经过其他处理后的char*可能会出现乱码的情况,对于const char*,会尽可能的避免乱码的出现

     


    (2)     VS2008中CString转换成char*类型

    在VS2005之前的编译器中,都是默认关闭UNICODE的,在VS2005以后,打开了对UNICODE的支持。在基于UNICODE的编译系统中,CString存储的字符是wchar_t类型的,因而不能直接进行类似(1)中的强制类型转换,否则编译过程中会报错。


    方法一

    可以使用宽字节转多字节的函数来实现,函数wcstombs_s(wide char string to multiple byte string)可以实现这个功能,函数声明:

    wcstombs_s

               size_t * pReturnValue     //转换后的字符个数

                    char * mbstr,                 //转换后的多字节字符串的存储区

                    size_t sizeInBytes,        //转换后的多字节字符串的字节个数,即缓冲区mbstr的大小

                    const wchar_t *wcstr,  //需要转换的宽字符

                    size_t count                //缓冲区的截断方式,常使用_TRUNCATE

    )

    注:这里的截断方式是指由于缓冲区大小的不同,并不能保证将wchar_t*全部转换成char*,用_TRUNCATE截断功能,当wchar_t*和char*的存储区字节数目相同时,可以完全复制并成功返回;当char*存储区字节长度小于wchar_t*时,复制到最后一个存储字节时,填充\0并成功返回;当char*存储区的长度大于wchar_t*时,会将wchar_t*的字符完全复制并成功返回,(一般情况下都要先计算好wchar_t*的大小并使得char*的大小和其一致)。

    例:

    CString cstr = _T(“test”);

    const size_t pcaSize = cstr.GetLength() *2;

    //CString中的GetLength函数获取的是字符的个数,不包括'\0'截止符

    char * pca = new char[pcaSize + 1];

    size_t sz = 0;

    wcstombs_s( &sz, pc, pcaSize, cstr, _TRUNCATE);

    pca[pcaSize] = '\0';//单独添加'\0'

    Or

    CString cstr = _T(“test”);

    const size_t pcaSize = (cstr.GetLength() + 1)*2;//包'\0'包括进去

    //CString中的GetLength函数获取的是字符的个数

    char * pca = new char[cstrsize];

    size_t sz = 0;

    //这里利用_TRUNCATE功能,多申请了'\0'的存储空间,使得char*pca自动添加'\0'

    wcstombs_s( &sz, pca, pcaSize, cstr, _TRUNCATE );

    注:

    1、char * c = (LPSTR)(LPCTSTR)cstr;只会获取第一个字符

    2、有时上述方法不能够获得字符串,例如有时不能获得非根目录下面的文件路径、

    3、用这种方法不可以正确显示带有汉字字符的字符串,我在获取文件路径时发现的这个问题

     

    方法二

    使用宽字节转ANSI字符形式的函数W2A和T2A函数,他们可以正确转换含有汉字的字符串

    例:

    CString cstr(  _T(“test”)  );

    USES_CONVERSION;

    char * pca = W2A( cstr );

    or

    USES_CONVERSION;

    char * pcb = T2A( cstr );

    注:ANSI字符为每个字节表示一个字符,因而可以有256个字符,ASCII码为7位表示一个字符,可以表示128个字符。


    方法三

    使用宽字节转换为多字节的函数WideCharToMultiByte,具体参数可以查找MSDN。

    例:

    CString cstr( TEXT(“Test”) );

    size_t cstrLen = cstr.GetLenth();//获取的是字符数

    int pcaLen = WideCharToMultiChar(CP_ACP, 0, cstr, cstrLen, NULL, 0, 0, 0 );//len为字节数

    char * pca = new char[pcaLen + 1];

    WideCharToMultiChar(CP_ACP, 0, cstr, cstrLen, pca, pcaLen, 0, 0 );

    pca[pcaLen] = ‘\0’;//添加’\0’截止符

    以上方法都是在通过搜索论坛和博客并整理而成,同时自己写程序测试过,其中添加了自己的理解,如有不正确,还请见谅。