简介
如果你编写的程序是针对非英语国家的用户,如中国、日本、东欧和中东地区,那么你一定要熟悉 UNICODE 字符集。尤其是用 Visual C++/MFC 编写针对上述国家和地区的用户的程序时,如果你想让自己的应用程序得到更广泛的用户,那么必须考虑代码 UNICODE 的兼容性,也就是说它既在 ASCII 模式下运行 ,也能在UNICODE 模式下运行。本文将介绍 UNICODE 的一些基本编程知识,澄清很多人(包括我自己)在这个问题上存在的模糊认识。对于任何使用 Visual C++ 和/或 MFC
编程的人来说,这篇文章肯定值得一读。
UNICODE到底是什么?
UNICODE 是目前用来解决 ASCII 码 256 个字符限制问题的一种比较流行的解决方案。大家知道,ASCII 字符集只有256个字符,用 0-255 之间的数字来表示。包括大小写字母、数字以及少数特殊字符;如标点符号、货币符号等。对于大多数拉丁语言来说,这些字符已经够用。但是,许多亚洲和东方语言所用的字符远远不止256个字符。有些超过千个。人们为了突破 ASCII 码字符数的限制,试图用一种简单的方法来针对超过256个字符的语言编写计算机程序。于是 UNICODE 应运而生。UNICODE
通过用双字节来表示一个字符,从而在更大范围内将数字代码映射到多种语言的字符集。
Visual C++的解决方案
作为软件开发人员,如何熟练有效地使用 UNICODE 呢?如果你正在用 Visual C++ 编写程序,UNICODE 兼容性意味着你的程序是否具有国际化特征,也就是说你的应用程序是针对本地市场还是国际市场。一旦你作出了决定,那么就得在代码中实现具体细节。好在 Visual C++ 提供了很多内建功能来支持 UNICODE,在创建工程时就可以利用 Visual C++ 提供的这些功能。在产生应用程序框架代码之前,AppWizard 允许开发人员决定是否支持 UNICODE。Win32 SDK 包含有一些数据类型遵循
UNICODE 编码规则,MFC 以宏的形式提供了将一般文本转换成 UNICODE 数据类型的途径。开发人员只需要稍微改变一下编写代码的习惯便可以轻松编写支持 UNICODE 的应用。
字符串
C 程序员一般是用 char 关键字象下面这样来声明一个字符串数组:
char str[100];
象下面这样声明函数原形:
void strcpy( char *out, char *in );
为了将上面的声明改成支持双字节的 UNICODE 字符集,可以用下面的方法:
wchar_t str[100];
或者
void wcscpy( wchar_t *out, wchar_t *in );
此外,微软还提供一种通过预处理指令来实现 UNICODE。每当用 Visual C++ 创建新工程时,只要确定是否支持另外一种字符集,则 AppWizard 将会在头文件中插入预处理指令。这些指令告诉编译器程序想要支持何种字符集。这样在使用VC++提供的通用数据类型时,编译器将用相应的数据类型把通用数据类型替换成所需要支持的字符集。这样很容易将代码重新编译成支持其它字符集的程序。
为了在 Visual C++ 6.0 中激活 UNICODE 标准,可以这样做:打开工程文件后,从主菜单中选择“Project | Settings”打开工程设置对话框 => 然后选择“C/C++”标签 => 在“Preprocessor definitions”编辑框中添加 UNICODE 或者 _UNICODE 预处理宏指令。如图一所示:
图一 Project Settings 对话框
注意这里的 UNICODE 和 _UNICODE 有什么区别呢?前者没有下划线,专门用于 Windows 头文件;后者有一个前缀下划线,专门用于 C 运行时头文件。
在代码中,凡是用关键字 char 的地方都用 TCHAR 取代;凡是用 char * 的地方都用 LPTSTR 取代;凡是定义在双引号中的字符串常量(如"VCKBASE Online Journal")都用 TEXT 宏重写:
TEXT("VCKBASE Online Journal");
TEXT 宏的主要作用是当定义了 UNICODE/_UNICODE 预处理指令时,字符串被标志为双字节字符串,否则字符串被标示为 ANSI 字符串。TEXT 的定义如下:
TEXT(
LPTSTR string // ANSI 或者 Unicode 字符串
);
参数 string 为字符串指针,指向被解释的 Unicode 或者 ANSI 字符串
在文档中 微软提供了包括通用类型在内的几种数据类型都与 ASCII 和 UNICODE兼容。这一点可以参考微软在线文档有关“通用数据类型和数据类型”的章节。
例子代码下面通过一些简单的例子来进一步探讨 UNICODE 编程。
使用 ASCII 字符集的“Hello, World”:
修改上面的代码使之支持 UNICODE 字符集,串常量必须要改成对应的 UNICODE 字符。方法是对串常量使用TEXT 宏。这个宏将告诉预处理器检查使用什么样的字符标准:
当预处理器碰到通用数据类型,它便检查 AFXWIN.H 头文件的 _UNICODE 定义。然后根据 UNICODE 定义插入相应的的数据类型。
下面的这个例子使用 Win32 API 函数和通用数据类型设置 C 盘的卷标。
通过使用 TCHAR 数据类型,将这段代码最上面的字符数组声明为两个字节的字符。TEXT 宏再次被用于字符串常量:
Visual C++ 中的通用数据类型
Visual C++ 提供了几种 MFC 专用的数据类型用于创建具有国际化特性的应用程序。这些定义很通用,完全可以在 UNICODE、ASCII、DBCS (双字节字符集) 和 MBCS (多字节字符集)。由于篇幅所限,本文不打算涉及所有上面提到的这些字符集。有关它们的详细资料请参考相关资料。MFC 提供了一种透明的方式来实现这些字符集。通用数据类型的映射到哪个字符集以及映射方式是根据工程的设置决定的,默认值为 ASCII 模式,其它几个可选项是 MBCS、DBCS 或者 UNICODE。本文主要讨论
UNICODE,所以下表中只列出了 ASCII 与 UNICODE 字符之间的映射关系:
表一:
通用 MFC 数据类型
|
映射到 ASCII
|
映射到 UNICODE
|
注释
|
_TCHAR
|
char
|
wchar_t
|
_TCHAR 是一个映射宏,当定义 UNICODE 时,该数据类型映射到 wchar_t,如果没有定义 UNICODE,那么它映射到 char。 |
_T 或 _TEXT
|
char 常量字符串
|
wchar_t 常量字符串
|
功能与宏相同,在 ASCII 模式下,它们被忽略,也就是说被预处理器删除掉,但是如果定义了UNICODE, 则它们会将常量字符串转换成等价的 UNICODE 。 |
LPTSTR
|
char*, LPSTR(Win32)
|
wchar_t*
|
可移植的32位字符串指针。它将字符类型映射到工程设置的类型。 |
LPCTSTR
|
const char*, LPCSTR(Win32)
|
const wchar_t*
|
可移植的32位常量字符串指针。它将字符类型常量映射到工程设置的类型。 |
使用表一中列出的通用数据类型,开发人员可以保证所创建的工程始终是针对一种字符集,这些通用数据类型就相当于占位符,在编译时被特定的字节所替代,使得应用程序在 ASCII 和 UNICODE 模式下都能运行。但是,有一点要特别注意,那就是上述的通用数据类型为微软专有,与 ANSI 标准并不兼容。有关微软提供的这些通用数据类型详细描述请参考 MSDN 库文档。
有关技术注释
为了成功编译支持 UNICODE 的 MFC 程序,必须使用 MFC 的 UNICODE 版本库。该库在定制安装Visual C++ 时是个可选安装项。
有一点很重要:那就是不使用 UNICODE 标准在外观上并不影响程序的执行。也就是说,上面提到过的代码不管设没设置 _UNICODE 生成选项,最终都能生成正常运行的程序。当开发人员使用多个版本的Win32 API函数时才会出现问题。
在使用多个版本的 Win32 API函数(任何有字符或字符串作为参数的 Win32 API函数)时,编译器根据是否设置 _UNICODE 指令来决定调用正确的函数。如果没有定义_UNICODE,那么编译器将默认调用 ASCII 版本函数。
结束语
综上所述可以看到,编译 UNICODE 版本的程序并不难。只是在编写代码时记住函数调用上些微的变化。微软为此提供的扩展是开发人员能够以透明的方式选择所用的字符集,为应用软件的国际化打开了方便之门。
Jeffrey Richter 在他的《Windows 核心编程》(机械工业出版社-王建华、张焕生、侯丽坤等译)一书中专门用一章讨论了 UNICODE。翻译得也不错。有兴趣的朋友不妨找来看看。
分享到:
相关推荐
win32编程入门程序 包括:自定义消息 定时器 使用资源(图标,光标,菜单,对话框) 键盘消息响应 后备缓冲区 说明:需自建工作空间,并在建好之后在属性->配置属性->常规->项目默认值->字符集 选择"使用Unicode...
第2部分则提供了各种高级主题来展示可以使用Python做些什么,包括正则表达式、网络编程、网络客户端编程、多线程编程、图形用户界面编程、 Web编程、数据库编程、扩展Python 和一些其他材料。 本书适合Python初学...
第2章 快速入门 2.1 程序输出,print语句及“Hello World!” 2.2 程序输入和raw_input()内建函数 2.3 注释 2.4 操作符 2.5 变量和赋值 2.6 数字 2.7 字符串 2.8 列表...
包含几个关于socket传输的说明介绍文档,里面有代码 class Server { ... string msg = Encoding.Unicode.GetString(buffer, 0, bytesRead); Console.WriteLine("Received: {0}", msg); // 按Q退出 } }
感觉编程语言Feel是一种专注于效率的开源编程语言。 它可以帮助您轻松构建跨平台软件。 通过精心设计的语法规则...入门快速预览Main := () { Print("Hello, world!") Greetings := Make_greetings("Fall in love with
写的时我发现,易语言根本不支持Unicode编程.也不也没有word类型真的搞不懂,这能叫中文编程 算了,不吐槽了.易语言还是很不错的中文编程,我想是开发工具对中国人来说简单入门简单 这个编辑框功能比较简单 可输入 可...
北京动力节点-Java编程零基础教程-053-Java基本语法-Unicode码.avi 北京动力节点-Java编程零基础教程-054-Java基本语法-UTF-8.avi 北京动力节点-Java编程零基础教程-055-Java基本语法-UTF-8的编码格式.avi 北京...
第2章 快速入门 2.1 程序输出,print语句及“hello world!” 2.2 程序输入和raw_input()内建函数 2.3 注释 2.4 操作符 2.5 变量和赋值 2.6 数字 2.7 字符串 2.8 列表...
在逐渐掌握Qt 4的过程中,我们萌发了编写一本关于Qt 4的书来帮助初学者入门的想法。最终,在电子工业出版社博文视点资讯有限公司的大力支持下,我们的想法终于得以付诸实施。 \关于Qt \Qt是挪威的Trolltech公司的...
第2章 快速入门 2.1 程序输出,print语句及“hello world!” 2.2 程序输入和raw_input()内建函数 2.3 注释 2.4 操作符 2.5 变量和赋值 2.6 数字 2.7 字符串 2.8 列表...
第1章 Windows应用程序开发入门 1 1.1 第一个实例程序 1 1.1.1 start.exe 1 1.1.2 Windows API 2 1.1.3 程序入口函数 2 1.1.4 start.c代码分析 2 1.2 编译代码 3 1.2.1 安装Visual Studio 3 1.2.2 ...
第1章 Windows应用程序开发入门 1 1.1 第一个实例程序 1 1.1.1 start.exe 1 1.1.2 Windows API 2 1.1.3 程序入口函数 2 1.1.4 start.c代码分析 2 1.2 编译代码 3 1.2.1 安装Visual Studio 3 1.2.2 ...
第2章 快速入门 2.1 程序输出,1print语句及“HellocWorld!” 2.2 程序输入和raw_input()内建函数 2.3 注释 2.4 操作符 2.5 变量和赋值 2.6 数字 2.7 字符串 2.8 列表...
在逐渐掌握Qt 4的过程中,我们萌发了编写一本关于Qt 4的书来帮助初学者入门的想法。最终,在电子工业出版社博文视点资讯有限公司的大力支持下,我们的想法终于得以付诸实施。 \关于Qt \Qt是挪威的Trolltech公司的...
写的时我发现,易语言根本不支持Unicode编程.也不也没有word类型真的搞不懂,这能叫中文编程 算了,不吐槽了.易语言还是很不错的中文编程,我想是开发工具对中国人来说简单入门简单 这个编辑框功能比较简单 可输入 可...
目录 历史 前言 I. C语言入门 1. 程序的基本概念 1. 程序和编程语言 2. 自然语言和形式语言 ...3. 在Linux C编程中使用Unicode和UTF-8 B. GNU Free Documentation License Version 1.3, 3 November 2008 参考书目 索引
C 语言入门..........................................................5 第 1 章 程序的基本概念..........................................5 1.1. 程序和编程语言................................................