字符串格式转化
来源:互联网 发布:async await js 编辑:程序博客网 时间:2024/06/08 07:49
UniCode 下 CString 转 char* 的方法
点击打开链接
今天进行文件操作时,将CString的GetBuffer()后直接倒到char数组后写入文件发现 每个字符与字符之间都有一个空格存在,而且有内容丢失。原来CString类对象GetBuffer(),后以后还是unicode编码,所以必须将宽字符转换成char类型那就必须用到一个函数
网上查了下解决方法如下:
在Visual C++.NET2005中,默认的字符集形式是Unicode,但在VC6.0等工程中,默认的字符集形式是多字节字符集(MBCS:Multi-Byte Character Set),这样导致在VC6.0中非常简单实用的各类字符操作和函数在VS2005环境下运行时会报各种各样的错误,这里总结了在Visual C++.NET2005环境中Unicode字符集下CString和char *之间相互转换的几种方法,其实也就是Unicode字符集与MBCS字符集转换。
1、Unicode下CString转换为char *
方法一:使用API:WideCharToMultiByte进行转换
CString str = _T("D://校内项目//QQ.bmp");
//注意:以下n和len的值大小不同,n是按字符计算的,len是按字节计算的
int n = str.GetLength(); // n = 14, len = 18
//获取宽字节字符的大小,大小是按字节计算的
int len = WideCharToMultiByte(CP_ACP,0,str,str.GetLength(),NULL,0,NULL,NULL);
//为多字节字符数组申请空间,数组大小为按字节计算的宽字节字节大小
char * pFileName = new char[len+1]; //以字节为单位
//宽字节编码转换成多字节编码
WideCharToMultiByte(CP_ACP,0,str,str.GetLength(),pFileName,len,NULL,NULL);
pFileName[len+1] = '/0'; //多字节字符以'/0'结束
方法二:使用函数:T2A、W2A
CString str = _T("D://校内项目//QQ.bmp");
//声明标识符
USES_CONVERSION;
//调用函数,T2A和W2A均支持ATL和MFC中的字符转换
char * pFileName = T2A(str);
//char * pFileName = W2A(str); //也可实现转换
注意:有时候可能还需要添加引用#include <afxpriv.h>
2、Unicode下char *转换为CString
方法一:使用API:MultiByteToWideChar进行转换
char * pFileName = "D://校内项目//QQ.bmp";
//计算char *数组大小,以字节为单位,一个汉字占两个字节
int charLen = strlen(pFileName);
//计算多字节字符的大小,按字符计算。
int len = MultiByteToWideChar(CP_ACP,0,pFileName,charLen,NULL,0);
//为宽字节字符数组申请空间,数组大小为按字节计算的多字节字符大小
TCHAR *buf = new TCHAR[len + 1];
//多字节编码转换成宽字节编码
MultiByteToWideChar(CP_ACP,0,pFileName,charLen,buf,len);
buf[len] = '/0'; //添加字符串结尾,注意不是len+1
//将TCHAR数组转换为CString
CString pWideChar;
pWideChar.Append(buf);
//删除缓冲区
delete []buf;
方法二:使用函数:A2T、A2W
char * pFileName = "D://校内项目//QQ.bmp";
USES_CONVERSION;
CString s = A2T(pFileName);
//CString s = A2W(pFileName);
方法三:使用_T宏,将字符串转换为宽字符
//多字节字符集,在vc6和vc7种可以编译通过的语句,但VS2005不能通过,默认为Unicode字符集
//AfxMessageBox("加载数据失败",0);
//书写代码使用TEXT("")或_T(""),文本在UNICODE和非UNICODE程序里都通用
AfxMessageBox(_T("加载数据失败"),0);
注意:直接转换在基于MBCS的工程可以,但在基于Unicode字符集的工程中直接转换是不可行的,CString会以Unicode的形式来保存数据,强制类型转换只会返回第一个字符。
Unicode下CString和char *之间的互相转换
一、CString转换为char *
(1)方法一:使用wcstombs()
- #include <iostream>
- using namespace std;
- #include <atlstr.h>
- int main()
- {
- CString str = L"liuxijiao计算机网络";
- wchar_t *pWChar = str.GetBuffer(); //获取str的宽字符用数组保存
- str.ReleaseBuffer();
- int nLen = str.GetLength(); //获取str的字符数
- char *pChar = new char[nLen * 2 + 1];
- memset(pChar, 0, nLen * 2 + 1);
- int rtnVal = (int)wcstombs(pChar, pWChar, nLen * 2 + 1); //宽字符转换为多字节字符
- cout<<pChar<<endl;
- delete[] pChar;
- return 0;
- }
#include <iostream>using namespace std;#include <atlstr.h>int main(){CString str = L"liuxijiao计算机网络";wchar_t *pWChar = str.GetBuffer(); //获取str的宽字符用数组保存str.ReleaseBuffer();int nLen = str.GetLength(); //获取str的字符数char *pChar = new char[nLen * 2 + 1]; memset(pChar, 0, nLen * 2 + 1);int rtnVal = (int)wcstombs(pChar, pWChar, nLen * 2 + 1); //宽字符转换为多字节字符cout<<pChar<<endl; delete[] pChar;return 0;}
输出结果:
注意到结果没有输出“计算机网络”,那是因为wcstombs()不支持中文。
(2)方法二:使用WideCharToMultiByte();
- #include <iostream>
- using namespace std;
- #include <atlstr.h>
- int main()
- {
- CString str = L"liuxijiao计算机网络";
- int n = str.GetLength(); //获取str的字符数
- int len = WideCharToMultiByte(CP_ACP, 0, str, n, NULL, 0, NULL, NULL); //获取宽字节字符的大小,大小是按字节计算的
- char *pChar = new char[len + 1]; //以字节为单位
- WideCharToMultiByte(CP_ACP, 0, str, n, pChar, len, NULL, NULL); //宽字节编码转换成多字节编码
- pChar[len + 1] = '\0'; //多字节字符以'\0'结束
- cout<<pChar<<endl;
- delete[] pChar;
- return 0;
- }
#include <iostream>using namespace std;#include <atlstr.h>int main(){CString str = L"liuxijiao计算机网络";int n = str.GetLength(); //获取str的字符数int len = WideCharToMultiByte(CP_ACP, 0, str, n, NULL, 0, NULL, NULL); //获取宽字节字符的大小,大小是按字节计算的char *pChar = new char[len + 1]; //以字节为单位WideCharToMultiByte(CP_ACP, 0, str, n, pChar, len, NULL, NULL); //宽字节编码转换成多字节编码pChar[len + 1] = '\0'; //多字节字符以'\0'结束cout<<pChar<<endl; delete[] pChar;return 0;}
输出结果:
二、char *转换为CString
(1)方法一:使用_T()宏
- CString str = _T("liuxijiao计算机网络");
CString str = _T("liuxijiao计算机网络");
(2)方法二:使用API的函数MultiByteToWideChar()
- #include <iostream>
- using namespace std;
- #include <atlstr.h>
- #include <stdio.h>
- #include <string.h>
- int main()
- {
- //将char数组转换为wchar_t数组
- char *pChar = "liuxijiao计算机网络";
- int charLen = strlen(pChar); //计算pChar所指向的字符串大小,以字节为单位,一个汉字占两个字节
- int len = MultiByteToWideChar(CP_ACP, 0, pChar, charLen, NULL, 0); //计算多字节字符的大小,按字符计算
- wchar_t *pWChar = new wchar_t[len + 1]; //为宽字节字符数申请空间,
- MultiByteToWideChar(CP_ACP, 0, pChar, charLen, pWChar, len); //多字节编码转换成宽字节编码
- pWChar[len] = '\0';
- //将wchar_t数组转换为CString
- CString str;
- str.Append(pWChar);
- delete[] pChar;
- delete[] pWChar;
- return 0;
- }
#include <iostream>using namespace std;#include <atlstr.h>#include <stdio.h>#include <string.h>int main(){//将char数组转换为wchar_t数组char *pChar = "liuxijiao计算机网络";int charLen = strlen(pChar); //计算pChar所指向的字符串大小,以字节为单位,一个汉字占两个字节int len = MultiByteToWideChar(CP_ACP, 0, pChar, charLen, NULL, 0); //计算多字节字符的大小,按字符计算wchar_t *pWChar = new wchar_t[len + 1]; //为宽字节字符数申请空间,MultiByteToWideChar(CP_ACP, 0, pChar, charLen, pWChar, len); //多字节编码转换成宽字节编码pWChar[len] = '\0';//将wchar_t数组转换为CStringCString str;str.Append(pWChar);delete[] pChar;delete[] pWChar;return 0;}
在str.Append(pWChar);这条语句处设断点,调试运行,可查看到str的内容为"liuxijiao计算机网络"。
(三)方法三:使用A2T()、A2W()
- char *pChar = "liuxijiao计算机网络";
- USES_CONVERSION;
- CString str = A2T(pChar);
char *pChar = "liuxijiao计算机网络";USES_CONVERSION;CString str = A2T(pChar);
- char *pChar = "liuxijiao计算机网络";
- USES_CONVERSION;
- CString str = A2W(pChar);
CString 和 LPCTSTR 可以说通用。 原因在于CString定义的自动类型转换,没什么奇特的,最简单的C++操作符重载而已。
常量字符串ansi和unicode的区分是由宏_T来决定的。但是用_T( "abcd ")时, 字符串 "abcd "就会根据编译时的是否定一_UNICODE来决定是char* 还是 w_char*。 同样,TCHAR 也是相同目的字符宏。 看看定义就明白了。简单起见,下面只介绍 ansi 的情况,unicode 可以类推。
ansi情况下,LPCTSTR 就是 const char*, 是常量字符串(不能修改的)。
而LPTSTR 就是 char*, 即普通字符串(非常量,可修改的)。
这两种都是基本类型, 而CString 是 C++类, 兼容这两种基本类型是最起码的任务了。
由于const char* 最简单(常量,不涉及内存变更,操作迅速), CString 直接定义了一个类型转换函数
operator LPCTSTR() {......}, 直接返回他所维护的字符串。
当你需要一个const char* 而传入了CString时, C++编译器自动调用 CString重载的操作符 LPCTSTR()来进行隐式的类型转换。
当需要CString , 而传入了 const char* 时(其实 char* 也可以),C++编译器则自动调用CString的构造函数来构造临时的 CString对象。
因此CString 和 LPCTSTR 基本可以通用。
但是 LPTSTR又不同了,他是 char*, 意味着你随时可能修改里面的数据,这就需要内存管理了(如字符串变长,原来的存贮空间就不够了,则需要重新调整分配内存)。
所以 不能随便的将 const char* 强制转换成 char* 使用。
楼主举的例子
LPSTR lpstr = (LPSTR)(LPCTSTR)string;
就是这种不安全的使用方法。
这个地方使用的是强制类型转换,你都强制转换了,C++编译器当然不会拒绝你,但同时他也认为你确实知道自己要做的是什么。因此是不会给出警告的。
强制的任意类型转换是C(++)的一项强大之处,但也是一大弊端。这一问题在 vc6 以后的版本(仅针对vc而言)中得到逐步的改进(你需要更明确的类型转换声明)。
其实在很多地方都可以看到类似
LPSTR lpstr = (LPSTR)(LPCTSTR)string;
地用法,这种情况一般是函数的约束定义不够完善的原因, 比如一个函数接受一个字符串参数的输入,里面对该字符串又没有任何的修改,那么该参数就应该定义成 const char*, 但是很多初学者弄不清const地用法,或者是懒, 总之就是随意写成了 char* 。 这样子传入CString时就需要强制的转换一下。
这种做法是不安全的,也是不被建议的用法,你必须完全明白、确认该字符串没有被修改。
CString 转换到 LPTSTR (char*), 预定的做法是调用CString的GetBuffer函数,使用完毕之后一般都要再调用ReleaseBuffer函数来确认修改 (某些情况下也有不调用ReleaseBuffer的,同样你需要非常明确为什么这么做时才能这样子处理,一般应用环境可以不考虑这种情况)。
同时需要注意的是, 在GetBuffer 和 ReleaseBuffer之间,CString分配了内存交由你来处理,因此不能再调用其他的CString函数。
LPSTR、LPWSTR、LPCSTR、LPCWSTR、LPTSTR、LPCTSTR的区分与转化(转)
首先在编译程序时经常会遇到这种问题:
错误 1 error C2664: “CWnd::MessageBoxW”: 不能将参数 1 从“const char [3]”转换为“LPCTSTR”
1、觉得很烦,一般的做法就是不管三七二十一,在字符串前面加一个‘L’:
如调用函数FUN(LPCTSTR str)时,不能 FUN("HELLO"); 而是FUN(L"HELLO");
通常这样做都比较能解决问题。
2、或者还可以用_T(), 即 FUN(_T("HELLO")); _T() 的别名还有 _TEXT(), TEXT()。
稍微研究了下,BSTR,LPSTR,LPWSTR,LPCTSTR,LPTSTR等这些让人头晕的东东。(还是C#里简单啊,直接tostring)
BSTR:是一个OLECHAR*类型的Unicode字符串,是一个COM字符串,带长度前缀,与VB有关,没怎么用到过。
LPSTR:即 char *,指向以'/0'结尾的8位(单字节)ANSI字符数组指针
LPWSTR:即wchar_t *,指向'/0'结尾的16位(双字节)Unicode字符数组指针
LPCSTR:即const char *
LPCWSTR:即const wchar_t *
LPTSTR:LPSTR、LPWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI
LPCTSTR: LPCSTR、LPCWSTR两者二选一,取决于是否宏定义了UNICODE或ANSI,如下是从MFC库中拷来的:
#ifdef UNICODE
typedef LPWSTR LPTSTR;
typedef LPCWSTR LPCTSTR;
#else
typedef LPSTR LPTSTR;
typedef LPCSTR LPCTSTR;
#endif
3、相互转换方法:
LPWSTR->LPTSTR: W2T();
LPTSTR->LPWSTR: T2W();
LPCWSTR->LPCSTR: W2CT();
LPCSTR->LPCWSTR: T2CW();
ANSI->UNICODE: A2W();
UNICODE->ANSI: W2A();
另外,CString转为CStringW方法(通过一个wchar_t数组来转)
CString str;
CStringW strw;
wchar_t *text = new wchar_t[sizeof(wchar_t) * str.GetLength()];
MultiByteToWideChar(CP_ACP,0,str,-1,text,str.GetLength());
strw = text;
4、另外,还可以强行转换,不过不一定能成功
5、还有_bstr_t ( 对BTSTR的封装,需要#include<comdef.h> ),也可将单字节字符数组指针转为双字节字符数组指针,还没怎么没用到过。
- 字符串格式转化
- 字符串格式转化
- Win32字符串编码格式转化
- 将日期格式转化成字符串
- 时间获取,以及时间格式字符串转化
- 简单的字符串日期格式转化
- json格式字符串到json对象转化
- 将时间格式转化为字符串
- 表达式字符串转化为后缀表达式格式
- C# 字符串转化为时间格式
- C# 字符串转化为时间格式
- 如何将字符串转化为json格式
- js字符串和json格式互相转化
- 字符串时间转化成time_t格式
- 数字转化为特定格式的字符串
- json格式字符串转化为list
- oracle时间格式字符串转化为时间
- 将对象转化为JSON格式字符串
- Object Serialization using C#
- 2013 ACM 通化邀请赛D.D-City 并查集
- Android File类 根据官方文档理解
- stl排序
- Deep Learning论文笔记之(二)Sparse Filtering稀疏滤波
- 字符串格式转化
- user agent stylesheet 处理
- struts2-core-2.0.14更新到2.3.15
- ubuntu 下ssh xrdp ftp jdk等软件安装
- DEDE去掉会员登录及注册验证码的方法
- WIN7(64)下memcached安装使用
- 字节流格式(Annex B)和RTP格式流浅析
- 深入了解字符集和编码
- Qt VTK ITK安装与测试(一) Qt的安装与测试