正确使用 Unicode 和 MBCS 字符集

这篇具有很好参考价值的文章主要介绍了正确使用 Unicode 和 MBCS 字符集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

正确使用 Unicode 和 MBCS 字符集

在 Windows 下做开发,初学者经常面临字符集选择的问题。本文详细解释 MBCS 字符集和 Unicode 字符集的正确使用方法,以及为什么写程序要用 Unicode 字符集。同时对 UTF-8 做了简单介绍。

在程序中正确使用字符集

以 VC 为例,微软在 VC6.0 的时候,创建项目的默认字符集是 MBCS。从 VC2002(就是 VC7.0)开始,默认字符集就变为了 Unicode,直到今天。

为了减少字符编码造成的种种问题,请务必确保整个项目使用相同的字符集编码。比如,如果设置项目字符集为 Unicode,那么整个项目都要用 Unicode 方式处理字符串。具体方法:

1. 设置项目字符集

有两种方法设置项目字符集。

方法一,在项目属性中设置:

以 VC2010 Express 为例:在 Solution Explorer 右击项目 -> Properties,打开的属性窗口中,左侧选择 Configuration Properties / General 分类,右边将 Character Set 设置为 Use Unicode Character Set 即表示将项目设置为 Unicode 字符集,设置为 Use Multi-Byte Character Set 即表示将项目设置为 MBCS 字符集。

方法二,在代码中设置:

在代码的最顶部增加以下代码,表示程序使用 Unicode 字符集:

#define UNICODE
#define _UNICODE

在代码的最顶部增加以下代码,表示程序使用 MBCS 字符集:

#undef UNICODE
#undef _UNICODE

备注:_UNICODE 用于 C 运行库,UNICODE 用于 WINAPI。

2. 写程序时使用对应的字符集

对于 MBCS 字符集:char 定义字符(串),字符和字符串常量直接使用(例如:“Hello” 表示 MBCS 字符串),字符串函数可以使用 strlen、strcpy、strcmp 等。STL 可以使用 string。

对于 Unicode 字符集:wchar_t 定义字符(串),字符和字符串常量加 L 前缀(例如:L"hello" 表示 Unicode 字符串),字符串函数可以使用 wcslen、wcscpy、wcscmp 等。STL 可以使用 wstring。

如果需要同时适用 Unicode 和 MBCS 两种字符集编码:TCHAR 定义字符(串),字符和字符串常量加 _T("")(例如:_T("hello") 表示 Unicode/MBCS 自适应字符串),字符串函数可以使用 _tcslen_tcscpy_tcscmp 等。

具体每个字符串函数在不同字符集编码下的函数名,请参考微软的帮助文档。

通过示例展现 Unicode 比 MBCS 的优势

  • 实验环境 Windows 7 + VC2010 Express + EasyX_20220116。(在 Win10 下可以得到同样的结果)
  • 因为代码中涉及到英文中文韩文字符,需要将 .cpp 文件以 UTF-8 编码保存。方法:File -> Save xxx.cpp As…,在文件另存为对话框里,“保存”按钮右边有一个向下的箭头,点击后选择“Save with Encoding…”,同意覆盖原文件,然后 Encoding 选择 Unicode (UTF-8 with signature) - Codepage 65001,Line endings 不用调整,确定保存即可。

两个示例程序的具体设置与代码

第一个示例程序:

项目名称 TestUnicode
项目类型:Win32 Console Application
项目字符集:Unicode

#include <graphics.h>
#include <conio.h>

int main()
{
	wchar_t s[] = L"厉害了我的国";

	initgraph(640, 480);
	settextstyle(24, 0, L"微软雅黑");
	outtextxy(10, 30, s);
	_getch();
	closegraph();

	return 0;
}

第二个示例程序:

项目名称 TestMbcs
项目类型:Win32 Console Application
项目字符集:MBCS

#include <graphics.h>
#include <conio.h>

int main()
{
	char s[] = "厉害了我的国";

	initgraph(640, 480);
	settextstyle(24, 0, "微软雅黑");
	outtextxy(10, 30, s);
	_getch();
	closegraph();

	return 0;
}

原理解释

ASCII 码规定了每个字符一个字节,前 128 个属于常规 ASCII 码,后 128 个属于扩展 ASCII 码。常规 ASCII 码里面含有英文大小写字母、阿拉伯数字、常见标点符号等。扩展 ASCII 码里面是一些不常用的字符。

于是在过去,想要表示多语言的时候,就利用了扩展 ASCII 码不常用的特点,将两个连续的扩展 ASCII 码表示成其它语言。

例如中文的 GB2312 编码,将汉字分成 94 个区和 94 个位,区和位分别使用了扩展 ASCII 码的 161~254 这个范围。“中国”两字的区位码分别是 5448 2590,那么可以构造一个这样的程序(暂时忽略编译警告):

// 设置为 MBCS 字符集
#undef UNICODE
#undef _UNICODE

#include <graphics.h>
#include <conio.h>

int main()
{
	// “中”的区位码是 54 48,“国”的区位码是 25 90
	char s[] = {160 + 54, 160 + 48, 160 + 25, 160 + 90, 0};

	initgraph(640, 480);
	settextstyle(24, 0, "微软雅黑");
	outtextxy(10, 30, s);
	_getch();
	closegraph();

	return 0;
}

执行这个程序,可以成功的输出“中国”两个字。

这就是在 MBCS 字符集下中文的表示形式。

其他语言类似,比如韩文的 EUC-KR 编码(过去叫 KSC5601 编码),也用的两个扩展 ASCII 码,并且范围也是 0xA1-0xFE。台湾地区的 BIG5 编码也覆盖了这个范围。那么问题来了:两个扩展 ASCII 码,究竟表示中文、韩文还是繁体中文或者别的语言?

这取决于操作系统的系统区域(locale)设置,
当 locale 设置为简体中文,那么两个连续的扩展 ASCII 码就会根据 GB2312 编码解析;
当 locale 设置为韩文,那么两个连续的扩展 ASCII 码就会根据 EUC-KR 编码解析。

由此可知:

  1. 系统区域设置错误,MBCS 字符集的字符串就无法正确显示。
  2. MBCS 字符集无法实现多语言混合显示。

当编码与 locale 不匹配的时候,就会出现“乱码”。

Unicode 字符集整合了全世界所有语言的文字,任何语言的任何一个文字,在 Unicode 编码中都有唯一的值对应。因此不再需要设置“系统区域(locale)”,也就不会产生“乱码”了。

就像前面的实验看到的那样,采用 Unicode 字符集的程序,无论是同时显示多少种语言,无论在什么语言的操作系统上执行,都可以正常显示。

该文章会更新,欢迎大家批评指正。

推荐一个零声学院的C++服务器开发课程,个人觉得老师讲得不错,
分享给大家:Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容
点击立即学习:C/C++后台高级服务器课程文章来源地址https://www.toymoban.com/news/detail-727591.html

到了这里,关于正确使用 Unicode 和 MBCS 字符集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java基础——IO流之字符集

    (1)IO前置内容:字符集 1.字符集基础知识: 计算机底层不可以直接存储字符,只能存储二进制(0,1)。 二进制可以转换成十进制。 计算机底层可以表示十进制编号。计算机可给人类字符进行编号存储,这套编号规则就是字符集。 2.ASCII字符集:(1字节) ASCII(American S

    2023年04月17日
    浏览(44)
  • mysql 的增删改查以及模糊查询、字符集语句的使用

    net  start mysql81 mysql -uroot -p show databases; show databases like \\\'%schema\\\'; create databases mydb; create databases if not exists mydb; show warnings; drop database mydb; drop database if not exists mydb; select database(); use mydb(); select database(); select version(); select user(); create database mydb2 character gbk collate gbk_chinese_ci show d

    2024年02月10日
    浏览(38)
  • Jenkins上使用expect脚本实现发布物上传SVN遇到字符集问题

    编写一个expect脚本实现发布物上传到svn的功能比较简单,可能需要注意一点就是增加文件替换功能,其核心步骤有4步: 但关键问题在于,脚本在mac上调试的好好的,放到jenkins的shell中执行就卡住,百思不得其解。 最后偶然间发现,jenkins中调用expect脚本,控制台输出是这样的

    2024年02月10日
    浏览(35)
  • MySQL 字符集概念与原理及如何配置字符集 - 超详细图文详解

    目录 一、字符集概念 1、字符(Character) 2、字符编码 3、字符集(Character set) 二、字符集原理 1、ASCII字符集 2、GB2312 3、GBK 4、GB18030 5、BIG5 6、Unicode 编码 三、字符序 四、MySQL字符集 字符序 1、mysql 字符集 2、mysql 字符序 3、字符集与字符序的关系 五、MySQL 数据存储字符集

    2024年02月04日
    浏览(53)
  • 算法加密与解密、字符编码与字符集

    加密保证数据不会被窃取或者修改 哈希算法 压缩映射 :散列又称为哈希,是把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值。 哈希算法(Hash)又称摘要算法(Digest),哈希算法的目的就是为了验证原始数据是否被篡改。 主流的散列算法有MD5和

    2024年02月03日
    浏览(50)
  • 有限字符集的字符串压缩算法

    在开发中,经常有上报线上堆栈来分析处理线上问题的场景,所以,对堆栈的压缩和加密也是必不可少的。加密:可以使用AES对称加密算法,压缩:可以在上传时利用protobuf天生的压缩性对字符串进行压缩。 不过,出于对流量的节省和传输效率的提升,可以通过在堆栈上传前

    2024年02月11日
    浏览(62)
  • oracle 字符集

      NLS_NCHAR_CHARACTERSET  国家字符集 NLS_CHARACTERSET  字符集 -----字符集和国家字符集的区别 字符集用来存储CHAR,VARCHAR2,CLOB,LONG等类型数据。 国家字符集用以存储NCHAR,NVARCHAR2,NCLOB等类型数据。

    2024年01月24日
    浏览(43)
  • (三) MySQL字符集

    MySQL字符集包括 基字符集 (CHARACTER)与 校对规则 (COLLATION)这两个概念: latin1支持西欧字符、希腊字符等 gbk支持中文简体字符 big5支持中文繁体字符 utf8几乎支持世界所有国家的字符 utf8mb4是真正意义上的utf-8 查看当前数据库默认的字符集: SHOW VARIABLES like \\\'character%\\\'; MySQL在

    2024年01月24日
    浏览(58)
  • 字符集详解

    计算机底层不可以直接存储字符的。 计算机中底层只能存储二进制(0、1) 。 二进制是可以转换成十进制的。 结论:计算机底层可以表示成十进制编号。计算机可以给人类字符进行编号存储,这套编号规则就是字符集。 ASCII(American Standard Code for Information Interchange,美国信息交

    2024年02月07日
    浏览(41)
  • HTML 字符集

    HTML5 中的默认字符集为 UTF-8。 数字 ASCII ANSI 8859-1 UTF-8 描述 32 space 33 ! ! ! ! exclamation mark 34 \\\" \\\" \\\" \\\" quotation mark 35 # # # # number sign 36 $ $ $ $ dollar sign 37 % % % % percent sign 38 ampersand 39 \\\' \\\' \\\' \\\' apostrophe 40 ( ( ( ( left parenthesis 41 ) ) ) ) right parenthesis

    2023年04月25日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包