8.3 C++11对Unicode的支持

一、C++11对Unicode的支持

在C++98中,引入wchar_t对Unicode支持,但是后来由于不同平台下wchar_t的宽度并不相同(8,16,32位),导致可移植性受到影响。因此从C++11开始引入了char16_t、char32_t以及原有的char,分别存储utf16,utf32和utf8编码的数据。

此外还定义了字符串常量的前缀:

  • u8表示以utf8编码
  • u表示utf16编码
  • U表示utf32编码

以上三种,再加上wchar_t格式的L以及不带前缀的字符串,C++11则包含了5种字符串常量的前缀。

通常情况下,对于连续的字符串常量,C++会要求编译器将其连起来,比如"a" "b"和"ab"没有区别。

此外,对于多个连续声明的字符串常量,只要有一个有前缀,则编译器会将这些连续的字符串常量都以此前缀处理。(实际上vs2017并不允许)

此外,C++11还支持"\u十六进制码位"表示unicode字符。

std::string  str = "\u4F60\u597d";	//中文字符:你好

而想要正确显示一个字符(不乱码),要求输入编码格式、文件存储编码格式,编译时选择的编码格式、以及输出显示编码格式四者一致才能正确,否则都会出现乱码的现象。

二、对于Unicode库的支持

1.单码位转换

        size_t mbrtoc16(char16_t * pc16, const char * s, size_t n, mbstate_t * ps);
        size_t c16rtomb(char * s, char16_t c16, mbstate _t * ps);
        size_t mbrtoc32(char32_t * pc32, const char * s, size_t n, mbstate_t * ps);
        size_t c32rtomb(char * s, char32_t c32, mbstate_t * ps);

mb表示multiple bytes,这四个函数都表示单码位的转换。

#include <climits>
#include <clocale>
#include <cuchar>
#include <iomanip>
#include <iostream>
#include <string>

int main()
{
	std::setlocale(LC_ALL, "en_US.utf8");
	std::u16string strv = u"zß水🍌"; // or z\u00df\u6c34\U0001F34C
	std::cout << "Processing " << strv.size() << " UTF-16 code units: [ ";
	for (char16_t c : strv)
		std::cout << std::showbase << std::hex << static_cast<int>(c) << ' ';
	std::cout << "]\n";

	std::mbstate_t state{};
	char out[MB_LEN_MAX]{};
	for (char16_t c : strv)
	{
		std::size_t rc = std::c16rtomb(out, c, &state);
		std::cout << static_cast<int>(c) << " converted to [ ";
		if (rc != (std::size_t) - 1)
			for (unsigned char c8 : std::string{ out, rc })
				std::cout << +c8 << ' ';
		std::cout << "]\n";
	}
}
#include <clocale>
#include <cstring>
#include <cuchar>
#include <cwchar>
#include <iomanip>
#include <iostream>

int main()
{
	std::setlocale(LC_ALL, "en_US.utf8");

	std::string str = "z\u00df\u6c34\U0001F34C"; // or u8"zß水🍌"

	std::cout << "Processing " << str.size() << " bytes: [ " << std::showbase;
	for (unsigned char c : str)
		std::cout << std::hex << +c << ' ';
	std::cout << "]\n";

	std::mbstate_t state{}; // zero-initialized to initial state
	char16_t c16;
	const char *ptr = &str[0], *end = &str[0] + str.size();

	while (std::size_t rc = std::mbrtoc16(&c16, ptr, end - ptr + 1, &state))
	{
		std::cout << "Next UTF-16 char: " << std::hex
			<< static_cast<int>(c16) << " obtained from ";
		if (rc == (std::size_t) - 3)
			std::cout << "earlier surrogate pair\n";
		else if (rc == (std::size_t) - 2)
			break;
		else if (rc == (std::size_t) - 1)
			break;
		else
		{
			std::cout << std::dec << rc << " bytes [ ";
			for (std::size_t n = 0; n < rc; ++n)
				std::cout << std::hex << +static_cast<unsigned char>(ptr[n]) << ' ';
			std::cout << "]\n";
			ptr += rc;
		}
	}
}

2.多码位转换

        std::codecvt<char, char, std::mbstate_t>          // 完成多字节与char之间的转换
        std::codecvt<char16_t, char, std::mbstate_t>      // 完成UTF-16与UTF-8间的转换
        std::codecvt<char32_t, char, std::mbstate_t>      // 完成UTF-32与UTF-8间的转换
        std::codecvt<wchar_t, char, std::mbstate_t>       // 完成多字节与wchar_t之间的转换

以及派生codecvt_utf8、codecvt_utf16、codecvt_utf8_utf16等可以用于字符串转换的模板类。这些模板类配合C++11定义的wstring_convert模板,可以进行一些不同字符串的转换。

三、原生字符串字面量支持

C++11开始支持原生字符串字面量,语法是R"(string)".

#include <iostream>

int main()
{
	std::cout << "12345\t\n890" << std::endl;
	std::cout << R"(12345\t\n890)" << std::endl;
}

输出:

12345
890
12345\t\n890

而原生字符串字面值也可以添加前缀u,u8,U等表示字符编码内容:

	std::cout << uR"(12345\t\n890)" << std::endl;
	std::cout << UR"(12345\t\n890)" << std::endl;
	std::cout << u8R"(12345\t\n890)" << std::endl;

输出:

006DEBE4
006DEB3C
12345\t\n890

相关推荐

  1. 8.3 C++11Unicode支持

    2023-12-07 19:56:03       37 阅读
  2. 使用流读取UNICODE-16字符串

    2023-12-07 19:56:03       42 阅读
  3. 不明确unicode字符

    2023-12-07 19:56:03       6 阅读

最近更新

  1. TCP协议是安全的吗?

    2023-12-07 19:56:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2023-12-07 19:56:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2023-12-07 19:56:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2023-12-07 19:56:03       20 阅读

热门阅读

  1. 牛客剑指offer刷题其他算法篇

    2023-12-07 19:56:03       29 阅读
  2. 前后端交互—数据库与身份认证

    2023-12-07 19:56:03       29 阅读
  3. 《算法通关村——滑动窗口高频问题》

    2023-12-07 19:56:03       44 阅读
  4. vue实现父子传参

    2023-12-07 19:56:03       40 阅读
  5. 【Android】Retrofit创建实例源理

    2023-12-07 19:56:03       28 阅读
  6. 26.Oracle11g的数据装载

    2023-12-07 19:56:03       44 阅读
  7. Node.js 的 os 模块介绍

    2023-12-07 19:56:03       35 阅读
  8. Django回顾5

    2023-12-07 19:56:03       29 阅读