现代 C++ 字符串编码

2021-03-25  本文已影响0人  Platanuses

本文更新至 C++20。

字符类型

以上类型名称都是关键字,而非另外某种类型的 typedef。

字符串类型

字符串字面量可使用以下前缀:

R"(a
b\n)"

"a\nb\\n"

头文件 <string>

字符串类型除了 std::basic_string<char> 的别名 std::string 之外,还有:

编码转换

头文件 <cwchar>

std::mbstate_t 类用于表示多字节编码的状态,如余留的不完整字节。

头文件 <locale>

std::use_facet 函数用于查询一个 std::locale 而获得其 std::locale::facet,如:

auto &cvt = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(std::locale("zh_CN.gb18030"));

std::codecvt_base::result 枚举用于表示编码转换的结果,其中:

std::codecvt 类用于字符编码之间的转换,继承于 std::codecvt_basestd::locale::facet。如 std::codecvt<char16_t, char8_t, std::mbstate_t> 用于在 utf-16 和 utf-8 之间转换。std::codecvt<char16_t, char8_t, std::mbstate_t>std::codecvt<char32_t, char8_t, std::mbstate_t>std::codecvt<wchar_t, char, std::mbstate_t> 有特化。其中:

std::codecvt_base::result std::codecvt<InternT, ExternT, StateT>::out(
    StateT& state,
    const InternT* from, const InternT* from_end, const InternT*& from_next,
    ExternT* to, ExternT* to_end, ExternT*& to_next
) const;

其中,[from, from_end) 的源字符串转换到 [to, to_end) 的目标字符串,from_nextto_next 指向转换结束后源和目标缓冲区中的下一字节。如果源字符串结束于不完整字节,或源与目标缓冲区长度不匹配,则转换终止于让源和目标缓冲区均不越界的最后一个源字符串的完整字节。如:

#include <cwchar>
#include <locale>

int main() {
    auto &cvt = std::use_facet<std::codecvt<char16_t, char8_t, std::mbstate_t>>(std::locale());
    std::mbstate_t mbs;

    const char8_t *si = u8"是我";
    const char8_t *sin;
    char16_t so[4];
    char16_t *son;

    auto ret = cvt.in(mbs, si, si + 4, sin, so, so + 2, son);
    // ret == std::codecvt_base::result::partial, sin - si == 3, son - so == 1
}
int std::codecvt<InternT, ExternT, StateT>::length(
    StateT& state,
    const ExternT* from, const ExternT* from_end,
    std::size_t max
) const;

返回 [from, from_end) 的字符串中 ExternT 类型的个数 n,使其等效于虚拟的 .in(state, from, from_end, from_next, to, to + max, to_next) 且有 from + n == from_next

上一篇下一篇

猜你喜欢

热点阅读