半角字符向全角字符转换

来源:互联网 发布:centos6.5 yum源配置 编辑:程序博客网 时间:2024/06/10 09:19

      为了使软件的密码框支持文本拖放功能,贪图方便,直接使用了delphi的RichEdit控件,没想到,忘记关闭输入法了,导致用户输入密码时,有可能以全角字符输入,而解密时若输入半角字符,则报密码错误...虽然看似是一个简单的错误,但为寻找这一错误,还真花费了不少时间.

      无奈,既然犯了错误,那就必须全力承担.分析了下全角与半角的区别,下面是半角下全角转换的函数.

function FullCharacterString(HalfCharacter:AnsiString):AnsiString;
var
i:integer;
FullCh:AnsiString;
begin
for i:=1 to length(HalfCharacter) do
  FullCh:=FullCh+#163+chr(ord(HalfCharacter[i])+128);

  Result:=FullCh;
end;

 

代码很简单,只是为了说明下原理.

刚开始以为这种转换只对中国用户有效...我以为只有中文有全角半角的概念...其实不然...本地集字符里,概念都差不多. 只要是大于128的,就认为后面还跟着一个字符,再转换成对应的本地语言码就OK了.

 

当用户输入密码时,先尝试转换为全角字符,再拿去与密钥匹配,若符合就把输入的密码修改为全角字符. 至此,困扰已久的全角半角问题完美解决.

 

下面是在windows程序设计一书中找到的文章,

 

空方框表示该位置未定义字符。这与ANSI/ISO 8859-1的最终定义一致。ANSI/ISO 8859-1仅显示了图形字符,而没有控制字符,因此没有定义DEL。此外,代码0xA0定义为一个非断开的空格(这意味着在编排格式时,该字符不用于断开一行),代码0xAD是一个软连字符(表示除非在行尾断开单词时使用,否则不显示)。此外,ANSI/ISO 8859-1将代码0xD7定义为乘号(*),0xF7为除号(/)。Windows中的某些字体也定义了从0x80到0x9F的某些字符,但这些不是ANSI/ISO 8859-1标准的一部分。

MS-DOS 3.3(1987年4月发行)向IBM PC用户引进了代码页(code page)的概念,Windows也使用此概念。代码页定义了字符的映像代码。最初的IBM字符集被称作代码页437,或者「MS-DOS Latin US)。代码页850就是「MS-DOS Latin 1」,它用附加的带重音字母(但不是图2-2所示的Latin 1 ISO/ANSI标准)代替了一些线形字符。其它代码页被其它语言定义。最低的128个代码总是相同的;较高的128个代码取决于定义代码页的语言。

在MS-DOS中,如果用户为PC的键盘、显示卡和打印机指定了一个代码页,然后在PC上创建、编辑和打印文件,一切都很正常,每件事都会保持一致。然而,如果用户试图与使用不同代码页的用户交换文件,或者在机器上改变代码页,就会产生问题。字符码与错误的字符相关联。应用程序能够将代码页信息与文件一起保存来试图减少问题的产生,但该策略包括了某些在代码页间转换的工作。

虽然代码页最初仅提供了不包括带重音符号字母的附加拉丁字符集,但最终代码页的较高的128个字符还是包括了完整的非拉丁字母,例如希伯来语、希腊语和斯拉夫语。自然,如此多样会导致代码页变得混乱;如果少数带重音的字母未正确显示,那么整个文字便会混乱不堪而不可阅读。

代码页的扩展正是基于所有这些原因,但是还不够。斯拉夫语的MS-DOS代码页855与斯拉夫语的Windows代码页1251以及斯拉夫语的Macintosh代码页10007不同。每个环境下的代码页都是对该环境所作的标准字符集修正。IBM OS/2也支援多种EBCDIC代码页。

但等一下,你会发现事情变得更糟糕。

双字节字符集

迄今为止,我们已经看到了256个字符的字符集。但中国、日本和韩国的象形文字符号有大约21,000个。如何容纳这些语言而仍保持和ASCII的某种兼容性呢?

解决方案(如果这个说法正确的话)是双字节字符集(DBCS:double-byte character set)。DBCS从256代码开始,就像ASCII一样。与任何行为良好的代码页一样,最初的128个代码是ASCII。然而,较高的128个代码中的某些总是跟随着第二个字节。这两个字节一起(称作首字节和跟随字节)定义一个字符,通常是一个复杂的象形文字。

虽然中文、日文和韩文共享一些相同的象形文字,但显然这三种语言是不同的,而且经常是同一个象形文字在三种不同的语言中代表三件不同的事。Windows支持四个不同的双字节字符集:代码页932(日文)、936(简体中文)、949(韩语)和950(繁体汉字)。只有为这些国家(地区)生产的Windows版本才支持DBCS。

双字符集问题并不是说字符由两个字节代表。问题在于一些字符(特别是ASCII字符)由1个字节表示。这会引起附加的程序设计问题。例如,字符串中的字符数不能由字符串的字节数决定。必须剖析字符串来决定其长度,而且必须检查每个字节以确定它是否为双字节字符的首字节。如果有一个指向DBCS字符串中间的指针,那么该字符串前一个字符的地址是什么呢?惯用的解决方案是从开始的指针分析该字符串!

Unicode解决方案

我们面临的基本问题是世界上的书写语言不能简单地用256个8位代码表示。以前的解决方案包括代码页和DBCS已被证明是不能满足需要的,而且也是笨拙的。那什么才是真正的解决方案呢?

身为程序写作者,我们经历过这类问题。如果事情太多,用8位数值已经不能表示,那么我们就试更宽的值,例如16位值。而且这很有趣的,正是Unicode被制定的原因。与混乱的256个字符代码映像,以及含有一些1字节代码和一些2字节代码的双字节字符集不同,Unicode是统一的16位系统,这样就允许表示65,536个字符。这对表示所有字符及世界上使用象形文字的语言,包括一系列的数学、符号和货币单位符号的集合来说是充裕的。

明白Unicode和DBCS之间的区别很重要。Unicode使用(特别在C程序设计语言环境里)「宽字符集」。「Unicode中的每个字符都是16位宽而不是8位宽。」在Unicode中,没有单单使用8位数值的意义存在。相比之下,在双字节字符集中我们仍然处理8位数值。有些字节自身定义字符,而某些字节则显示需要和另一个字节共同定义一个字符。

处理DBCS字符串非常杂乱,但是处理Unicode文字则像处理有秩序的文字。您也许会高兴地知道前128个Unicode字符(16位代码从0x0000到0x007F)就是ASCII字符,而接下来的128个Unicode字符(代码从0x0080到0x00FF)是ISO 8859-1对ASCII的扩展。Unicode中不同部分的字符都同样基于现有的标准。这是为了便于转换。希腊字母表使用从0x0370到0x03FF的代码,斯拉夫语使用从0x0400到0x04FF的代码,美国使用从0x0530到0x058F的代码,希伯来语使用从0x0590到0x05FF的代码。中国、日本和韩国的象形文字(总称为CJK)占用了从0x3000到0x9FFF的代码。