Windows核心编程<读书笔记二>Unicode和ANSI

本文是Windows核心编程读书笔记的第二部分,主要讨论了Unicode和ANSI字符集的区别。早期Windows系统中,CharNext、CharPrev和IsDBCSLeadByte等函数用于处理双字节字符。Unicode的引入统一使用16位字符,提供了wcscat等对应函数。为了兼容性,Windows定义了如CreateWindowEx这样的宏。此外,还介绍了IsTextUnicode用于检测文本类型,以及MultiByteToWideChar和WideCharToMultiByte进行字符集转换的方法。
 

【文起】蟹儿的爱一直激励着我,爱蟹儿,爱编码

 

单字节和双字节字符集

1、早期

在双字节字符集中,字符串中的每个字符可以包含一个字节或者两个字节。如:日文中的汉字,第一个字符在0x81与0x9F之间或者在0xE0与0xFC之间,那么必须观察下一个字节才能确定字符串的这个完整字符。如果只是调用strlen函数,无法真正了解字符串中究竟有多少个字符,只能给出到达结尾的0之前有多少字节。

所以早期的windows系统,提供了三个函数来使用。CharNext,CharPrev,IsDBCSLeadByte.

PTSTR CharNext(PCTSTR pszCurrentChar):返回字符串的下一个字符的地址;

PTSTR CharPrev(PCTSTR pszStart,PCTSTR pszCurrentChar)返回字符串的上一个字符的地址;

BOOL IsDBCSLeadByteTrue(BYTE bTestChar);如果该字节是DBCS字符的第一个字节,返回TRUE

2、Unicode出现

Unicode全部使用16位的字符,定义就为 typedef unsigned short wchar_t;

如定义一个100个16位字符组成的Unicode字符串:

Wchar_t szBuffer[100];

这样的话,之前用户ANSI的字符串就无法使用了,如strcat,strchr,strcmp,strcpy

不过windows还是提供了对应的Unicode函数,wcscat,wcschr,wcscmp,wcscpy

3、Unicode与ANSI共存

有时候调用函数时,并不想去了解到底是8为字符串还是16位字符串。那么我们就提供了这样一个“兼容的”函数。比如CreateWindowEx,在WinUser.h中是这样定义的

#ifdef UNICODE

#define CreateWindowEx CreateWindowExW

#else

#define CreateWindowEx CreateWindowWxA

#endif

4、转换

A)可以通过这样一个函数DWORD IsTextUnicode(CONST PVOID pvBuffer,int cb,PINT pResult)来判断文本是Unicode还是ANSI类型的

B)提供两个函数用户Unicode和ANSI之间的转换。

int MultiByteToWideChar(...)

int WideCharToMultiByte(…)

转换时,一般将cchMultiByte = -1,pWideCharStr = NULL,cchWideChar = 0,这样函数返回Unicode的length。

然后申请一个如此大小的Unicode值,再调用函数。

按照书上的例子,自己写了一个案例测试了下,用VS2008写的。可以通过将项目分别调整为Unicode和多字节符分别运行。

#ifdef UNICODE
#define StringReverse StringReverseW
#else
#define StringReverse StringReverseA
#endif

BOOL StringReverseW(PWSTR pWideCharStr)
{
	PWSTR pWideCharEnd = pWideCharStr + wcslen(pWideCharStr) - 1;
	wchar_t wc_temp;
	while ( pWideCharStr < pWideCharEnd )
	{
		wc_temp = *pWideCharStr;
		*pWideCharStr = *pWideCharEnd;
		*pWideCharEnd = wc_temp;

		pWideCharStr++;
		pWideCharEnd--;

	}
	return TRUE;

}

BOOL StringReverseA(PSTR pMultiByteStr)
{
	PWSTR pWideCharStr;
	int iWideCharLength;
	BOOL bOk = FALSE;

	/* 获取转化为Unicode后Unicode长度 */
	iWideCharLength = MultiByteToWideChar(CP_ACP,0,pMultiByteStr,-1,NULL,0);

	pWideCharStr = (PWSTR)HeapAlloc(GetProcessHeap(),0,iWideCharLength * sizeof(wchar_t));

	if (NULL == pWideCharStr)
	{
		cout<<"分配资源失败"<<endl;
	}

	/* 转换为Unicode */
	MultiByteToWideChar(CP_ACP,0,pMultiByteStr,-1,pWideCharStr,iWideCharLength);

	bOk = StringReverseW(pWideCharStr);

	/* 转换为ANSI */
	if( TRUE == bOk )
	{
		WideCharToMultiByte(CP_ACP,0,pWideCharStr,-1,pMultiByteStr,strlen(pMultiByteStr),NULL,NULL);
	}

	HeapFree(GetProcessHeap(),0,pWideCharStr);

	return(TRUE);

}

int _tmain(int argc, _TCHAR* argv[])
{

#ifdef UNICODE
	wchar_t wc_buffer[] = _T("Doujiang loves Xiexie!");
	cout<<"Length of wc_buffer is:"<<wcslen(wc_buffer)<<endl;
	wcout<<_T("Before Reverse wc_buffer:")<<wc_buffer<<endl;
	StringReverse(wc_buffer);
	wcout<<_T("After  Reverse wc_buffer:")<<wc_buffer<<endl;
#else
	char c_buffer[] = "Xiexie loves Doujiang!";
	cout<<"Length of c_buffer is:"<<strlen(c_buffer)<<endl;
	cout<<"Before Reverse c_buffer:"<<c_buffer<<endl;
	StringReverse(c_buffer);
	cout<<"After Reverse c_buffer:"<<c_buffer<<endl;
#endif

	return 0;
}


如果文章对您有作用,请留下你对我和蟹儿的祝福,谢谢~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值