From:https://www.cnblogs.com/leanee/articles/2940088.html
char [] 到 LPWSTR转换的一个具体应用:http://www.cppblog.com/lateCpp/articles/153358.html
CString详细讲解:https://blog.csdn.net/qq_41786318/article/details/81989217
CString 应用操作指南【转】:https://blog.csdn.net/iteye_13411/article/details/82092838
VS2010/MFC编程入门之四十二(MFC常用类:CString类)
http://www.jizhuomi.com/software/228.html
因为 C++ 支持两种字符串 :
- 1. 常规的 ANSI 编码(使用 "" 包裹)
- 2. Unicode 编码(使用 L"" 包裹)
UNICODE 宏 和 _UNICODE 宏 (Windows 核心编程 第五版 2.4 节)
这样对应的就有了两套字符串字符串处理函数,比如:strlen 和 wcslen,分别用于处理两种字符串。微软将这两套字符集及其操作进行了统一,通过条件编译(通过 _UNICODE 和 UNICODE 宏)控制实际使用的字符集,这样就有了 _T("") 这样的字符串,对应的就有了_tcslen 这样的函数。为了存储这样的通用字符,就有了TCHAR:
- 当 没有定义 _UNICODE宏 时,TCHAR = char,_tcslen = strlen
- 当 定义 _UNICODE宏 时,TCHAR = wchar_t , _tcslen = wcslen[1]
当我们定义了 UNICODE宏,就相当于告诉了编译器:我准备采用 UNICODE 版本。这个时候,TCHAR 就会摇身一变,变成了wchar_t 。而未定义 UNICODE宏 时,TCHAR 摇身一变,变成了unsigned char。这样就可以很好的切换宽窄字符集。
tchar 可用于双字节字符串,使程序可以用于中日韩等国 语言文字处理、显示。使编程方法简化。
C++ 中的 wchar_t 数据类型
标准里面是这样解释的:Wide character ( 宽字节字符 )
Type whose range of values can represent distinct codes for all members of the largest extended character set specified among the supported locales.
In C++, wchar_t is a distinct fundamental type (and thus it is not defined in <cwchar> nor any other header).
在 C++ 中,wchar_t 是一个特有的基本类型( 因此它并没有在 <cwchar> 或其他 header 中被定义)
In C, this is a typedef of an integral type.( 在 C 中,wchar_t 是一个整数类型的 typedef )
wchar_t 是 C/C++ 的字符类型,一种扩展的存储方式,主要用在国际化程序的实现中。
char 是8位字符类型,最多能包含256种字符,许多的外文字符集所包含的字符数目超过256个,char 型不能表示。比如对于汉字,韩文以及日文这样的字符,它们的每一个文字都占据两个字节,所以 C++ 提出了 wchar_t 类型,也称为双字节类型,或宽字符类型。
截图来自:windows 核心编程 第五版 第二章 2.2 ANSI字符和Unicode字符与字符串数据类型
示例代码:
#include <iostream>
#include <locale> //setlocale函数在locale头文件中定义
using namespace std;
int main()
{//使用setlocale函数将本机的语言设置为中文简体//LC_ALL表示设置所有的选项(包括金融货币、小数点,时间日期格式、语言字符串的使用习惯等),chs表示中文简体setlocale(LC_ALL, "chs");wchar_t wt[] = L"中国伟大复兴梦"; //大写字母L告诉编译器为"中"字分配两个字节的空间wcout << wt << endl; //使用wcout来代替cout输出宽字符return 0;
}
LPSTR、LPCSTR、LPTSTR 和 LPCTSTR 的意义及区别
- 1、ANSI( 即 MBCS ):为 多字节字符集,它是不定长表示世界文字的编码方式。ANSI 表示英文字母时就和 ASCII 一样,但表示其他文字时就需要用多字节。
- 2、Unicode:用两个字节表示一个字符的编码方式。比如 字符 'A' 在 ASCII 下面用一个字节表示,而在 Unicode 下面用两个字节表示,其中高字节用 “0” 填充;中文字符 '程' 在 ASCII 下面用两个字节表示,而在 Unicode下面也是用两个字节表示。Unicode 的用处就是定长表示世界文字,据统计,用两个字节可以编码现存的所有文字而没有二义。
- 3、Windows 下的程序设计可以支持 ANSI 和 Unicode 两种编码方法的字符串,具体使用哪种就要看定义了 MBCS宏 还是Unicode宏。MBCS宏 对应的字符串指针为 LPSTR( 即 char* ),Unicode 对应的指针为 LPWSTR( 即 unsigned char* )。为了写程序的方便,微软定义了类型 LPTSTR,在 MBCS 下它表示 char*,在 Unicode 下它表示 unsigned char*,这就可以重定义一个宏进行不同字符集的转换了。
- 4、关系。
LPSTR: LPSTR = char*; 指向一个字符串的32位指针,每个字符占1个字节。
LPCSTR: LPCSTR = const char*;指向一个常量字符串的32位指针,每个字符占1个字节。
LPTSTR:指向一个字符串的32位指针,每个字符可能占1个字节或2个字节。
LPCTSTR:指向一个常量字符串的32位指针,每个字符可能占1个字节或2个字节。
LPWSTR = wchar_t*;L PCWSTR = const wchar_t*;
多字节 编码: char,string,CStringA。
Unicode 编码:wchar_t,wstring,CStringW。
注意:如果项目是 Unicode,那么 CString 就被定义为 CStringW,否则就是 CStringA。至于 LPCTSTR 也是根据项目字符集来定义为 LPCWSTR(Unicode)或 LPCSTR(多字节)。
OK,上面的定义很明显了,注意用的时候别弄混了,最好的方式是使用 wchar_t 和 wstring( api大多使用 unicode,即使是多字节版本也是把多字节转成 unicode 再去调用 unicode 版 api ) - 5、Windows 使用两种字符集 ANSI 和 Unicode,前者在处理英文字符时使用单字节方式,在处理中文字符时使用双字节方式。后者不管是英文字符还是中文字符都是采用双字节方式表示。Windows NT的所有与字符有关的函数都提供了两种方式的版本,而 Windows 9x 只支持 ANSI 方式。_T 一般同字符常量相关,如 _T("你好!"); 。如果编码方式为 ANSI,_T 不起任何作用;如果编码方式为 Unicode,编译器会把 "你好!" 以 Unicode 方式进行保存。 _T 和 _L 的区别在于,_L 不管你是以什么方式编译,一律以 Unicode 方法保存。
- 6、L 表示 字符串 采用 Unicode 编码方式,
示例如下:wchar_t Str[] = L"Hello World!"; // 每个字符都用2个字节来存储 - 7、_T 是一个适配宏。当定义了 _UNICODE 时,_T 和 L 相同;否则,_T 的字符串采用 ANSI 编码方式。
示例如下:
LPTSTR lptStr = new TCHAR[32];
TCHAR* szBuf = _T("Hello");
以上两个语句,无论是在 ANSI 编码方式,还是在 Unicode 编码方式下都是正确的。 - 8、微软推荐使用相匹配的字符串函数。例如,在处理 LPTSTR 或 LPCTSTR 的时候,应该使用 _tcslen 来替代 strlen 函数。否则,在 Unicode 编码方式下,strlen 不能处理 wchar_t* 的字符串。
- 9、T 是一个非常重要的符号(TCHAR、LPTSTR、LPCTSTR、_T() 和 _TEXT() 等 ),它表示使用一个中间类型,既不明确表示使用 MBCS,也不明确表示使用 Unicode。到底使用哪种字符集,在编译的时候才决定。
- 10、注意 L 和 _T 的使用方法。
LPTSTR,LPCTSTR,及 _T(常量字符串) 受 _T 影响。
介绍字符串类型:char, wchar_t,TCHAR, CHAR, WCHAR。
TCHAR 的定义:
#ifdef UNICODE
typedef wchar_t TCHAR;
#else
typedef unsigned char TCHAR;
#endif
typedef unsigned char CHAR;
typedef unsigned wchar_t WCHAR;
由此可以看出,unsigned char 和 wchar_t 都是基本数据类型,CHAR 实施上就是 unsigned char, WCHAR 为 wchar_t ,而 TCHAR 根据是否支持 unicode 而不同。在程序中,可以用的名称有5种,unsigned char(CHAR),wchar_t(WCHAR),TCHAR,但为了扩展性和兼容性,推荐使用 TCHAR。 - 11、CString 类型到 LPTSTR 类型的转换
CString path1;
LPTSTR path2 = path1.GetBuffer(path1.GetLenght());
字符串 的 ASCII 和 UNICODE 之间的转换
Win32 提供了 API 函数 MultiByteToWideChar 和 WideCharToMultiByte 来提供这种功能
char* 转换成 LPCTSTR。代码如下:
int MultiByteToWideChar()函数。根据 MSDN 描述,这个方法:This function maps a character string to a wide-character (Unicode) string。
char text[20] = "hello world";
TCHAR buffer[50];
MultiByteToWideChar(0, 0, text, -1, buffer, 20);char ch[1024] = "hello world";
int num = MultiByteToWideChar(0,0,ch,-1,NULL,0);
wchar_t *wide = new wchar_t[num];
MultiByteToWideChar(0,0,ch,-1,wide,num);解析:
num 获得长字节所需的空间
MultiByteToWideChar() 表示将 ch 中的字符传递到 wide 指向的内存中。
-1 表示传输至ch中的'\0'处,
num 表示传递的字节个数。
总结:MultiByteToWideChar()函数,首先得用 TCHAR 来定义一个数组
另外:网上有另外推荐将项目的 unicode 环境关掉,就可避免这个问题。不推荐,这实际上是回避问题。现在已经是 Unicode 的应用已经越来越广,程序不支持 Unicode 环境,走的了一时,走不了一世。
LPCTSTR 转换成 char *
wchar_t widestr[1024] = L"hello world";
int num = WideCharToMultiByte(CP_OEMCP, NULL, widestr, -1, NULL, 0, NULL, FALSE);
char *pchar = new char[num];
WideCharToMultiByte (CP_OEMCP, NULL, widestr, -1, pchar, num, NULL, FALSE);
一. CString 与 LPCWSTR
两者的不同:LPCWSTR 是 Unicode 字符串指针,初始化时串有多大,申请空间就有多大,以后存贮若超过则出现无法预料的结果,这是它与 CString 的不同之处。而 CString 是一个 字符串类,内存空间类会自动管理。
CString 转换成 LPCWSTR
方法 1:
CString strFileName;
LPCWSTR lpcwStr = strFileName.AllocSysString();
方法 2:CString str=_T("TestStr");
CString str=_T("TestStr");
USES_CONVERSION;
LPCWSTR lpcwStr = A2CW((LPCSTR)str);
MFC 中 CString 和 LPSTR 是可以通用,其中 A2CW 表示 (LPCSTR) -> (LPCWSTR),USER_CONVERSION 表示用来定义一些中间变量,在使用 ATL 的转换宏之前必须定义该语句。
LPCWSTR 转换成 CString
LPCWSTR lpcwStr = L"TestWStr";
CString str(lpcwStr);
二. CString 与 LPSTR 转换
CString 转换成 LPSTR
方法一:
CString strFileName;
LPSTR lpStr = strFileName.GetBuffer();
strFileName.ReleaseBuffer();
方法二:
CString strFileName;
LPSTR lpStr = (LPSTR)(LPCSTR)strFimeName;
LPSTR 转换成 CString
LPSTR lpStr = L"TestStr";
CString str(lpStr);
注意:CString 和 LPCSTR 可直接转换,如下:
CString str;
LPCSTR lpcStr = (LPCSTR)str;
三. CString 和 char* 转换
CString 转换成 char*
方法 1:
CString str;
char* p = str.GetBuffer();
方法 2:
CString str;
char* p = (LPSTR)(LPCSTR)str;
char* 转换成 CString
char* p = "test";
CString str = ("%s",p);
四. String 和 int、float 的转换
可以使用 atoi、atof、atol 等函数来完成。
五. LPSTR (char*) 和 LPWSTR 的转换
可以使用下面的ATL宏来进行,最好是将变量定义成 TCHAR、LPTSTR 等T类型,可以避免转换。
ATL宏介绍:
A2BSTR OLE2A T2A W2A
A2COLE OLE2BSTR T2BSTR W2BSTR
A2CT OLE2CA T2CA W2CA
A2CW OLE2CT T2COLE W2COLE
A2OLE OLE2CW T2CW W2CT
A2T OLE2T T2OLE W2OLE
A2W OLE2W T2W W2T
A :ANSI 字符串,也就是 MBCS。
W、OLE 宽字符串,也就是 UNICODE。
T 中间类型T。如果定义了 _UNICODE,则T表示W;如果定义了 _MBCS,则T表示A
C const 的缩写
利用这些宏,可以快速的进行各种字符间的转换。使用前必须包含头文件,并且申明USER_CONVERSION;使用 ATL 转换宏,由于不用释放临时空间,所以使用起来非常方便。但是考虑到栈空间的尺寸(VC 默认2M),使用时要注意几点:
1、只适合于进行短字符串的转换;
2、不要试图在一个次数比较多的循环体内进行转换;
3、不要试图对字符型文件内容进行转换,因为文件尺寸一般情况下是比较大的;
4、对情况 2 和 3,要使用 MultiByteToWideChar() 和 WideCharToMultiByte();
void Func1(LPSTR lpStr);
void Func2(LPWSTR lpwStr);
TCHAR name[256];
TCHAR* pName = new TCHAR[256];
Func1(name); // Func1(pName);
Func2(name); // Func2(pName);
注意在VS2005中上面用红色标记的代码已经不成立。
VS2005中CString已经改为宽字符型,一些转换如下:
char name[10];
TCHAR sex[5] ;
char *p = name;
TCHAR *pw = sex;
LPSTR lpstr = name;
LPCSTR lpcstr = name;
lpcstr = lpstr;
lpstr = p;
p = (char*)sex;
pw = (WCHAR*)name;
LPWSTR lpwstr = (LPWSTR)lpstr;
lpwstr = (LPWSTR)lpcstr;
LPCWSTR lpcwstr = (LPCWSTR)lpstr;
lpcwstr = (LPCWSTR)name;
CString str(lpstr);
CString str1(lpcstr);
CString str2(lpwstr);
CString str3(lpcwstr);
CString str4(name);
CString str5(sex);
lpwstr = (LPWSTR)(LPCWSTR)str;
lpstr = (LPSTR)(LPCWSTR)str;
lpcstr = (LPCSTR)(LPCWSTR)str;
p = (char*)str.GetBuffer();
pw = str.GetBuffer();
可以看出转换更加简单了,基本上可以直接转换,A2W 等宏基本上不需要啦。
接下来就是转换:
// C++
char* 到 string:string str("char"); 或者 string str = "char";
string 到 char*: const char* ch = str.c_str();
wchar_t* 和 wstring 与上相同。
// MFC
char* 到 CStringA:CStringA str("char");
CStringA 到 char*:const char* ch = str.operator LPCSTR();
注意:反对使用 GetBuffer,因为使用这个,必须要 ReleaseBuffer,而且很多时候没必要去分配空间
wchar_t* 和 CStringW 与上相同。
// 字符集之间转换
char* 到 wchar_t*:CA2W a2w("char"); const wchar_t* wch = a2w.operator LPCWSTR();
wchar_t* 到 char*:CW2A w2a(L"wchar_t"); const char* ch = w2a.operator LPCSTR(); (注意:反对使用_T("chs")这种方式,程序字符集在一开始就该确定,而且最好选择Unicode)
关于 CA2W 和 CW2A 这两个类,可以在 atlconv.h 中找到源代码,其实就是对 WideCharToMultiByte 和 MultiByteToWideChar 的封装。