博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
编写符合ANSI和Unicode的应用程序
阅读量:5154 次
发布时间:2019-06-13

本文共 3822 字,大约阅读时间需要 12 分钟。

世界真的很奇妙,分久必合,合久必分。

计算机发展到今天,多国之间的交流日益广泛,软件本地化是重大趋势。如果减少本地化工作就是一件值得考虑的事情。

软件本地化要解决的真正问题就是如何来处理不同的字符集。要知道,单字节字符是一个8位的数据来表示的。 因此,它最多能表示256个字符。 全世界那么多个国家,256个怎么够。 因此人们提出了双字节(DBCS)来解决这个问题。

单字节与双字节字符集 ----->多字符集

当表示英文或某些符号的时候,就采用一个字节来表示,而当表示日文,中文等字符的时候,就采用两个位来表示。 可想而知,我们不可以再像操作单字节字符那样通过 pChar++;来遍历每一个字符。

为此,MS提供了CharNext,CharPre作为遍历工具。 不过这些函数让人头疼。

Unicode应运而生。它采用了两个字节来表示一个字符,不管是汉字还是英文。 统一一样。 两个字节即为16位,表示的数有65536个。 而世界各国的符号加起来才用了35000个左右,困此,足够了。

为什么我们要使用Unicode

 当开发应用程序时,当然应该考虑利用Unicode的优点。即使你不打算让你的程序本地化,开发时也应该将Unicde放在心上,肯定可以简化你将来的代码转换工作。此外,Unicde还有以下功能。

   1、可以很容易地在不同语言之彰进行数据交换。

   2、使你能够分配支持所有语言的单个二进制.exe文件或dll文件。

   3、提高应用程序的运行效率。

WINDOWS 2000上的Unicode

WINDOWS 2000是采用Unicode从头开发的。 所有与字符串相关的操作都会用到Unicode。当然,WINDOWS 2000的API都接受多字符集和Unicode字符集的参数。但是,只有Unicode的函数是实现了的。而多字符集的函数则是先将Unicode字符集转换成Unicode,然后再交给Unicode的函数处理。可知,采用Unicode调用API,速度会快不少。 同样,返回字符串的API函数也做同样的转换工作。

系统中会存在两套API 拿CreateFile为例。则有如下定义

#ifdef UNICODE

#define CreateFileW CreateFile

#else

#define CreateFileA  CreateFile

#endif

当我们调用 CreateFile的时候,系统便会根据你是否要UNICODE而选择正常的函数。

而当你调用CreateFileA时,则有

调用CreateFileA---> 将多字符集参数转换为Unicode ---> 调用 CreateFileW

白白地多了转换工作。因此,采用Unicode编程,可以提高效率。  

还有一些关于WINDOWS 98的就不介绍了。。需要知道的就是,WIN 98不支持Unicode,所以,强制调用W结尾的函数再用GetLastError()取得错误信息,你会发现提示你此函数没有实现。

WINDOWS CE则是完完全全的Unicode操作系统,不支持ANSI.....

如何使用UNICODE

数据类型

    为了和ANSI有所区别,UNICODE版本的数据类型显然会不一样.

char   wchar_t

而wchar_t的定义为 typedef unsigned shot wchar_t

可见,它是16位的。

而对于常用的字符串操作函数,对比如下

strcpy  wcscpy

strcat wcscat

。。。

str 被换成了wcs 即 wide  character string的缩写

 

上面是C运行期库的定义,由于MS提供的C运行期库与ANSI标准是一样的。所以上面的宽字符操作依然对WIN 98有效。

 

对于UNICODE的使用,我们则不能直接使用上面的函数,因为这样的话,ANSI/Unicode源码转换时你会哭掉。

于是,我们应该使用像

 

#ifdef UNICODE

#define _strcpy  wcscpy

#else

#define _strcpy  strcpy

#endif

 

这样的宏来使用每一个函数,而 TChar.h 头文件已经帮我们做到了。只需包含它,并使用正确的经过宏控制的函数名和类型。就可以很轻松地实现。。。

对于字符串的赋值。

 

char* p = "ook";

wchar_t *p = "ook";//错误

 

而应该是

wchart_t *P = L"ook";//L表示宽字符。

 

当然,我们也不能直接这样用。而是要用 TEXT 宏

用法如下 TCHAR *P = TEXT("ook");

定义类似于下面这样。

#ifdef UNICODE

typedef wchar_t TCHAR

#define TEXT(X)  L##X

#else

typedef char TCHAR

#define TEXT(X)

#endif

这样就能正确对应了。

总结一下编写支持ANSI/UNICODE编译的原码规则。

 

#将文本串视为字符数组,而不是char数组或BYTE数组。(因为TCHAR的长度不固定)

#将通用数据类型(TCHAR,PTSTR)用于文本字符和字符串

#将显式数据类型(BYTE,PBYTE)用于字节,字节指针和数据缓存

#将TEXT宏用于原义字符和字符串。

#执行全局性替换(例如用PTSTR替换PSTR)

#修改字符串运算问题。例如计算数组大小时,应该用sizeof(szBubffer)/szBuffer[0] ;

#include <Windows.h> #include <tchar.h> #include <Shlwapi.h> #include <stdio.h> //宽字节 BOOL StringReversW(PWSTR pWchar) { PWSTR pEndStr = pWchar+wcslen(pWchar)-1; WCHAR pChar; while(pWchar<pEndStr) { pChar = *pWchar; *pWchar = *pEndStr; *pEndStr = pChar; pWchar++; pEndStr--; } return TRUE; } //多字节 //转换后交给宽字节,再将结果转换回多字节 BOOL StringReversA(PSTR pchar) { PWSTR pWchar; int nLenOfWideChar; BOOL ok = FALSE; nLenOfWideChar = MultiByteToWideChar(CP_ACP,0,pchar,-1,NULL,0); pWchar = (WCHAR*)HeapAlloc(GetProcessHeap(),0,nLenOfWideChar*sizeof(WCHAR)); if(!pWchar) return FALSE; MultiByteToWideChar(CP_ACP,0,pchar,-1,pWchar,nLenOfWideChar); ok= StringReversW(pWchar); if(ok) { WideCharToMultiByte(CP_ACP,0,pWchar,-1,pchar,strlen(pchar),NULL,NULL); } HeapFree(GetProcessHeap(),0,(LPVOID)pWchar); return ok; } //未经转换函数转换。。。。 BOOL StringRevers_(TCHAR* pWchar) { TCHAR* pEndStr = pWchar+ _tcslen(pWchar)-1; TCHAR pChar; while(pWchar<pEndStr) { pChar = *pWchar; *pWchar = *pEndStr; *pEndStr = pChar; pWchar++; pEndStr--; } return TRUE; } #ifdef UNICODE #define StringRevers StringReversW #else #define StringRevers StringReversA #endif int _tmain() { TCHAR pStr[]=TEXT("哈哈,这个东西好,ok?"); StringRevers_(pStr); //StringRevers(pStr); printf("%d",sizeof(TEXT("哈哈,这个东西好,ok?"))); MessageBox(NULL,pStr,NULL,MB_OK); return 0; }

此程序便支持ANSI/UNICODE,并且输出无异常。 可以将StringRevers_(pStr);屏蔽,将 //StringRevers(pStr);打开,并在ANSI/UNICODE下编译看效果。 另外,输出到控制台的结果,也说明了使用的字长不一样。。。

关于用到的两个转换函数,可以查MSDN。

总结完毕。。。打完收工。!!!!

转载于:https://www.cnblogs.com/qilinzi/archive/2010/06/24/1940490.html

你可能感兴趣的文章
protobuf 安装与卸载
查看>>
jQuery基础——事件
查看>>
Java对象和引用
查看>>
ensp 启动路由器 43 错误解决方法
查看>>
Tail-chaining(末尾连锁)中断说明
查看>>
ASP.NET 推荐书籍
查看>>
mysql安装
查看>>
20172319 《程序设计与数据结构》 第二周学习总结
查看>>
02-Python基础之列表
查看>>
08-Python基础之迭代器与生成器
查看>>
POJ P3254 Corn fields 【状压dp】
查看>>
BZOJ3542 DZY Loves March 【map + 线段树】
查看>>
.net学习之集合、foreach原理、Hashtable、Path类、File类、Directory类、文件流FileStream类、压缩流GZipStream、拷贝大文件、序列化和反序列化...
查看>>
ViewPager的使用方法和实现过程
查看>>
Android编程之仿微信显示更多文字的View
查看>>
[置顶] ios 网页中图片点击放大效果demo
查看>>
[置顶] 某大型银行深化系统技术方案之二十:代码结构
查看>>
数据库中文mybatis连接mysql数据库插入中文乱码
查看>>
滚动停止jquery 文本上下无缝滚动,鼠标放上去就停止
查看>>
动画停止animate动画效果(泪奔的小孩)stop和delay的用法
查看>>