字符串编码

字符编码基础ASCII

ASCII 是一种 7 位编码,用 0 到 127 之间的数值来代表最常用的字符

1.ANSI编码

字符定义:

对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表一个字符(ASCII编码),而这之外的字符通常是使用0x80~0xFF范围内的两个字节来表示一个字符。比如汉字找那个的'汉'在简体中文中使用[0xBA, 0xBA]这两个字节存储。

编码标准

为了使计算机支持多种语言,不同的国家和地区制定了不同的标准,由此产生了 GB2312, Big5, JIS 等各自的编码标准。这些使用 2 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文系统下,ANSI 编码代表 GB2312 编码,繁体中文使用Big5,在日文操作系统下,ANSI 编码代表 JIS 编码。同时字节表示 ASCII 字符而用双字节表示 GB2312 中的字符;由于 GB2312 中本身也含有 ASCII 中包含的字符,在使用中逐渐就形成了“半角”和“全角”的区别。

中文操作系统中的‘汉’

char

ANSI(GBK)

UTF-8

Unicode(0x6C49)

BABA

0xE6B189

优点

内存占用小

缺点

1.需要完整遍历整个字符串才能确定每个字符的位置

2.查找性能差,同时无法国际化使用,主流的代替方式是UTF-8

3.Unicode某些特殊值无法表示??,打开某些特殊字符文件夹失败,如包含表情的文件夹,甚至有可能用户名带emoji符号。

示例

 

string test_name = "汉😀汉";

string test_name1 = "\u6C49\U0001F600\u6C49";

string test_name2 = "汉😂汉";

2.UNICODE 编码

字符定义:

Unicode 在今天已经大大超出了最初的目标。到 Unicode 12.1 为止,Unicode 已经包含了 137,994 个字符,囊括所有主要语言(使用中的和已经不再使用的),并包含了表情符号、数学符号等各种特殊字符。Unicode 的编码点是从 0x0 到 0x10FFFF,一共 1,114,112 个位置。一般用“U+”后面跟 16 进制的数值来表示一个 Unicode 字符,如 U+0020 表示空格,U+6C49 表示“汉”,U+1F600 表示“😀”,等等(不足四位的一般写四位)。

不同标准的Unicode

UTF-32 :

32 比特,是编码点的直接映射。

UTF-16 :

对于从 U+0000 到 U+FFFF 的字符,使用 16 比特的直接映射;对于大于 U+FFFF 的字符,使用 32 比特的特殊映射关系——在 Unicode 的 16 比特编码点中 0xD800–0xDFFF 是一段空隙,使得这种变长编码成为可能。在一个 UTF-16 的序列中,如果看到内容是 0xD800–0xDBFF,那这就是 32 比特编码的前 16 比特;如果看到内容是 0xDC00–0xDFFF,那这是 32 比特编码的后 16 比特;如果内容在 0xD800–0xDFFF 之外,那就是一个 16 比特的映射。

 

wstring test_name = L"\u6C49\U0001F600\u6C49";

wstring test_name1 = L"汉😀汉";

UTF-8 :

1 到 4 字节的变长编码。在一个合法的 UTF-8 的序列中,如果看到一个字节的最高位是 0,那就是一个单字节的 Unicode 字符;如果一个字节的最高两比特是 10,那这是一个 Unicode 字符在编码后的后续字节;否则,这就是一个 Unicode 字符在编码后的首字节,且最高位开始连续 1 的个数表示了这个字符按 UTF-8 的方式编码有几个字节。

Unicode编码

UTF-8编码(二进制)

U+0000 – U+007F

0xxxxxxx

U+0080 – U+07FF

110xxxxx 10xxxxxx

U+0800 – U+FFFF

1110xxxx 10xxxxxx 10xxxxxx

U+10000 – U+10FFFF

11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

 

char u8str[] = u8"汉😀汉";

平台兼容性

Windows

Windows 由于历史原因和保留向后兼容性的需要,一直用 char 表示传统编码(如,英文 Windows 上是 Windows-1252,简体中文 Windows 上是 GBK),用 wchar_t 表示 UTF-16。由于传统编码一次只有一种、且需要重启才能生效,要得到好的多语言支持,在和操作系统交互时必须使用 UTF-16。

由于窄字符在大部分 Windows 系统上只支持传统编码,要打开一个当前编码不支持的文件名称,就必须使用宽字符的文件名。微软的 fstream 系列类及其 open 成员函数都支持 const wchar_t* 类型的文件名,这是 C++ 标准里所没有的。

Linux和Mac OS

现代 Unix 系统,包括 Linux 和 Mac OS 在内,已经全面转向了 UTF-8。这样的系统中一般直接使用 char[] 和 string 来代表 UTF-8 字符串,包括输入、输出和文件名

3.编码转换

支持 Unicode 及其转换的 API。

Windows API

ansi string to wstring

UTF-8 string to wstring

wstring to ansi stirng

wstring to uft-8stirng


std::wstring trans(const std::string& sInput, int type) {

if (sInput.empty())

{

return L"";

}

int length = ::MultiByteToWideChar(type, 0, sInput.c_str(), -1, 0, 0);

wchar_t* result = new wchar_t[length + 1];

::memset(result, 0, (length + 1) * 2);

::MultiByteToWideChar(type, 0, sInput.c_str(), -1, result, length);

std::wstring strResult = result;

delete[] result;

result = nullptr;

return strResult;

}

// 当type为CP_ACP时,UNICODE转化为GBK;当type为CP_UTF8时,UNICODE转化为UTF8

std::string trans(const std::wstring& wsInput, int type) {

if (wsInput.empty())

{

return "";

}

int length = ::WideCharToMultiByte(type, 0, wsInput.c_str(), -1, 0, 0, 0, 0);

char* result = new char[length + 1];

::memset(result, 0, length + 1);

::WideCharToMultiByte(type, 0, wsInput.c_str(), -1, result, length, 0, 0);

std::string strResult = result;

delete[] result;

result = nullptr;

return strResult;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值