Win32学习笔记 第二章 Unicode

原创 2003年05月01日 11:29:00

Win32学习笔记

作者: 姜学哲(netsail0@163.net)

教材: Windows程序设计(第五版)北京大学出版社
 [美]Charles Petzold 著
 北京博彦科技发展有限公司 译  ¥:160
参考资料:
 Windows 应用程序设计原理_方法_技术(因为是PDF格式的EBOOK,作者等不详)
 新编Windows API 参考大全  电子工业出版社  ¥:98
 C++ Primer(第三版)中国电力出版社 Stanley B.Lippman & Josee Lajoie 著 潘爱民 张丽 译 ¥:128
 TURBO C实用大全 徐金梧 杨德斌 徐科 编 ¥:42

环境: windows2000 server + Internet Explorer 6.0 + DirectX7.0 + Visual C++ 6.0

图们江计算机程序编制小组(chulsoft.xiloo.com)版权所有,转载请说明出处
--------------------------------------------------------------------
【第二章 Unicode】

佛曰:众生皆平等。但是人却可以利用较高等的智慧站在了众多生物的至高点。吃早饭的时候我看着被做成菜的那条鱼,想到它也是生命。所以说到底,还是有些等级之分。学习WIN32过程中让我知道了Unicode的存在。Unicode最终会取代ASCII码成为标准。但是之前还有很长一段路要走。虽然Unicode的优势很明显,但是因为历史遗留问题,ASCII会存在很长一段时间。

学习C语言的时候您应该接触过ASCII码。学习本章的内容需要ASCII知识。

学习Unicode有必要了解字符集的历史。从最早的象形字开始,我们使用字符文字已经有近6000年了。19世纪的几个发明家发明了电报,当时在电报中使用的代码是Morse代码。字母表中的每个字符对应于一系列短和长的脉冲。

计算机是处理的数据其实是一系列1和0。每一段数字都代表一种字符。这就是ASCII码。7位数的ASCII码对于美国的字符集支持得很好。不幸的是地球上有一百多个国家和地区,2000多个民族。对于美国以外的用户来讲在计算机中显示自己国家的文字困难重重。

尤其是中国,日本,朝鲜更是如此。以中国为例,有数也数不清的汉字。办法总是有的。人们引入了"代码页"和"双字节字符集"的概念。这种编码方式非常庞大和复杂,不利于维护。这个时候Unicode应运而生了。

Unicode的解决方案非常简单。既然不能用7位或者8位数值表示,那么我们应该试一下更宽的值。例如16位,这样就允许表示65536个字符。Unicode和ASCII是兼容的。也就是说,前128个字符的数值是相同的。

Unicode的最大好处是只有一个字符集。当然Unicode也有缺点,Unicode占用的内存是ASCII码的两倍。而且人们还不太习惯Unicode。

对于程序员来讲,8位的ASCII码和16位的Unicode是我们必须面对的问题。为了解决宽字符(16位)问题,Windows在头文件中定义了"新"数据类型。

typedef unsigned short wchar_t;

可以看出wchar_t其实是16位的无符号短整型数。Windows用这种方法存贮16位字符。

wchar_t *p = L"Hello!";

在"Hello!"前有一个大写字母L(代表long)。这将告诉编译器该字符串按宽字符保存。即每个字符占用2个字符。存贮该字符串需要14个字节。字符串末尾还有一个/0也需要2个字节。

我们都知道如何获得字符串的长度。

int iLength;
char *pc = "Hello!";
iLength = strlen(pc);

函数strlen()返回字符串的长度,长度将不包括末尾的/0。变量iLength将等于6,也就是字符串中的字符数。

接下来我们试着用strlen()检查宽字符的字符串。

wchar_t *pw = L"Hello!";
iLength = strlen(pw);

strlen()的参数应该是char类型的指针,但是现在却接受了一个unsigned short类型的指针。编译后您会发现iLength等于1。

why?字符串"Hello!"中的6个字符宽字符代码如下:

0x0048 0x0065 0x006c 0x006c 0x006f 0x0021

Intel处理器在内存中将其存为:

48 00 65 00 6c 00 6c 00 6f 00 21 00

strlen()的工作过程是遇到0就结束。因为0表示一个字符串的结束。当读完"48"后strlen()遇到的是0,所以strlen()返回1。

由上例可以看出C语言的函数无法正确处理宽字符。在参数中有字符串的函数全部需要重写。strlen()的宽字符版本是wcslen(),并且在STRING.H中和WCHAR.H中均有声明.

现在我们知道,要得到宽字符串的长度,可以调用

iLength = wcslen(pw);

该函数返回将返回字符串中的字符数6。请记住,改成宽字节后字符串的字符长度不变,只是字节长度改变了。千万不要混淆。

因为Unicode占用两倍的存储空间,所以宽字节运行库中的函数比常规的函数大。所以最好是建立两个版本的程序,一个处理ASCII字符串,另一个处理Unicode字符串。但是这样以来又引来了另一个小问题。因为每一个实现特定功能的函数都有两个版本,所以名字不好记。不管是ASCII版本还是Unicode版本,都用相同的名字该多好啊?幸好这个问题已经得到了解决。

解决办法是使用Visual C++包含的TCHAR.H头文件。该头文件不是标准C的一部分。为了与标准C的头文件分别开来,该头文件内定义的每个函数和宏定义的前面都有一条下划线。


TCHAR.H为需要字符串的标准运行库函数提供了一系列的替代名称。有时这些名称被称为"通用"函数名,因为它们既可以指向函数的Unicode版本,也可以指向ASCII版本。
以_tcslen()为例如果定义了_UNICODE的标识符,并且程序中包含了TCHAR.H,那么_tcslen()就定义为wcslen():

#define _tcslen wcslen

如果没有定义_UNICODE,则_tcslen()被定义为strlen()。

#define _tcslen strlen

TCHAR.H还用一个新的数据类型TCHAR来解决两种字符数据类型的问题。如果定义了_UNICODE标识符,那么TCHAR就是wchar_t:

typedef wchar_t TCHAR;

否则TCHAR就是char:

typedef char TCHAR;

还记得第一章里出现过的TEXT()吗?那是为了兼容UNICODE字符集所做的改动。下面就来看看TEXT()在头文件中是怎么定义的。

#define __T(x)    L##x

后面的L##x您可能看不懂。很少有书提到它。但那确实是标准C预处理的一部分。这一对"##"称为粘贴号(token paste)。看来我们对标准C的了解还不够。是时候买本"The C Programming Language"了。它将字母L添加到宏参数上。

__T("Hello!") 等于 L##"Hello!" 等于 L"Hello!"。

此外还有两个宏与__T定义相同:

#define _T(x) __T(x)
#define _TEXT(x) __T(x)

WINNT.H头文件中还定义了一个宏,该宏也跟__T一样,将L添加到字符串前。

#ifdef UNICODE
#define __TEXT(quote) L##quote
#else
#define __TEXT(quote) quote
#endif

#define TEXT(quote) __TEXT(quote)

在本书中使用的就是TEXT(quote)。现在您知道了为什么会把字符串用TEXT()括起来了吧。what?还不明白?您可以先恶补标准C,然后再多读几遍。再不会那就是天份问题了。不过,连像我这样的村民都能看懂,您没理由不会啊!

◎第三十四页

scrnsize是可以检测出您当前显示器分辨率的东东,比如我的是1024*768

有关这个程序,运行一次就可以了,不要想看懂它,让他见鬼去吧。我们要看懂的是第三章的HelloWin。可能看完几遍后您对第二章还是不太懂,没关系,一回生,两回熟。再多看几遍就可以了。

周志华机器学习读书笔记第二章(一)

模型评估与选择 (1)错误率+精度=1,错误率是指分类错误的样本数占样本总数的比例。 (2)误差:学习器的实际预测输出与样本的真实输出之间的差异。 训练误差:学习器在训练集上的误差。 泛化误差...
  • u013261340
  • u013261340
  • 2017年10月08日 14:53
  • 135

『机器学习——周志华』学习笔记——第二章:模型评估与选择

一、经验误差与过拟合 1、错误率:分类错误的样本数占样本总数的比例 2、精度 = 1 - 错误率 3、实际预测输出与样本的真实输出之间的差异被称为“误差”(error);在训练集上的误差被称为“训练误...
  • Sbtgmz
  • Sbtgmz
  • 2016年05月25日 23:31
  • 1355

win32的ANSI、UNICODE、UTF8互转

#include "stdafx.h" #include "KKLogObject.h" #include KKLogObject::KKLogObject() { } KKLogObjec...
  • zmy12007
  • zmy12007
  • 2015年10月21日 02:08
  • 992

周志华机器学习第二章读书笔记(二)

(1)ROC(Receiver Operating Characteristic)受试者工作特征 根据学习器的预测结果对样例进行排序,按此顺序逐个把样本作为正例进行预测,每次计算出两个重要量的值,得到...
  • u013261340
  • u013261340
  • 2017年10月13日 13:29
  • 66

VC编译选项里面如何增加 win32 unicode release项

为vc工程添加Unicode   Debug和Unicode   Release 通过使用unicode编译,软件可以适应多种情况,如何在自己的工程中添加这两种编译方式呢?下面是一个简单的步骤 ...
  • yyxaf
  • yyxaf
  • 2012年03月04日 15:10
  • 1991

C++primer第五版第二章学习笔记

基本内置类型:算数类型、空类型 算数类型:整型、浮点型 short、int、long、long long的区别:存放数据时所占用的内存大小不一样,sizeof(short) signed和un...
  • sunhero2010
  • sunhero2010
  • 2015年11月03日 20:18
  • 361

《机器学习》 -- 周志华 (第二章学习笔记)

模型评估与选择经验误差与过拟合误差 一般的把机器学习器在训练集上的误差成为训练误差或者经验误差 在新样本上的误差称为泛化误差 过拟合已经把训练样本自身的一些特点当做了所有潜在样本都会具有的一般性质,这...
  • Cristal_yin
  • Cristal_yin
  • 2017年07月08日 13:12
  • 365

深度学习第二章-线性代数笔记

本章主要介绍与深度学习相关的线性代数知识。2.1 标量、向量、矩阵和张量 标量 (scalar) 、向量 (vector)、矩阵 (matrix) 张量 (tensor) :一般地,一个数组中的元素分...
  • Eclipsesy
  • Eclipsesy
  • 2017年07月26日 11:00
  • 709

win32 UNICODE 支持

#include #ifdef _UNICODE#define tstring std::wstring#define __T(quote) L##quote#else#define tstring ...
  • muzizongheng
  • muzizongheng
  • 2013年07月10日 15:41
  • 587

《快学Scala》第二章习题解答

RT。 package com.scalalearn.scala.main /** * 快学scala 02习题 */ object LearnScala02 { //1.如果一个数字为...
  • rongyongfeikai2
  • rongyongfeikai2
  • 2016年05月14日 14:58
  • 1098
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Win32学习笔记 第二章 Unicode
举报原因:
原因补充:

(最多只允许输入30个字)