使用C 17处理Unicode的有效,符合标准的机制是什么
What is the efficient, standards-compliant mechanism for processing Unicode using C++17?
简短版本:
如果我想编写可以通过Unicode字符有效执行操作的程序,可以在UTF-8或UTF-16编码中输入和输出文件。C 的合适方法是什么?
长版:
C 早于Unicode,并且从那以后都显着发展。我需要知道如何编写符合标准的C 代码,该代码无泄漏。我需要一个清晰的答案:
-
我应该选择哪个字符串容器?
- 用UTF-8?
-
std::wstring
(对此并不了解( - 用UTF-16的
std::u16string
? -
std::u32string
with utf-32?
std::string
-
我应该完全粘在上述容器之一上还是在需要时更改它们?
-
当使用UTF字符串时,我可以在字符串文字中使用非英语字符,例如polish conture:
吗?ąćęłńśźż
etc? -
当我们将UTF-8编码字符存储在
std::string
中时,什么会发生什么变化?它们是否仅限于单字节ASCII字符,还是可以是多字节?
当我进行以下操作时会发生什么?std::string s = u8"foo"; s += 'x';
-
WCHAR_T和其他多字节字符类型之间有什么区别?
wchar_t
字符或wchar_t
字符串是否能够存储UTF编码?
我应该选择哪个字符串容器?
这确实取决于您根据自己的特定需求做出决定。您提出的任何选择都将起作用,它们每个都有自己的优势和缺点。通常,UTF-8非常适合用于存储和通信目的,并且与ASCII兼容。而在处理Unicode数据时,UTF-16/32更容易使用。
std::wstring
(对此并不了解太多(
wchar_t
的大小依赖编译器,甚至依赖于平台。例如,在Windows上,wchar_t
为2个字节,使std::wstring
可用于UTF-16编码字符串。在其他平台上,wchar_t
可能是4个字节,使std::wstring
可用于UTF-32编码字符串。这就是为什么wchar_t
/std::wstring
通常在Portable代码中不使用char16_t
/std::u16string
和char32_t
/std::u32string
的原因。即使是char
也可能存在UTF-8的可移植性问题,因为char
可以在编译器供应商的描述时签署或未签名,这就是为什么char8_t
/std::u8string
在C 20中引入了UTF-8。
我应该完全粘在上述容器之一上还是在需要时更改它们?
使用适合您需求的任何容器。
通常,您应该在整个代码中使用一种字符串类型。仅在字符串数据输入/离开程序的边界上执行数据转换。例如,读取/编写文件,网络通信,平台系统调用等时
如何在它们之间正确转换?
有很多方法可以处理。
C 11及以后具有std::wstring_convert
/std::wbuffer_convert
。但是这些在C 17中被弃用。
有第三方Unicode转换库,例如ICONV,ICU等
有C库功能,平台系统调用等。
当使用UTF字符串时,我可以在字符串文字中使用非英语字符,例如polish字符:
ąćęłńśźż
etc?
是,如果您使用适当的字符串字面前缀:
u8
for utf-8。
L
用于UTF-16或UTF-32(取决于编译器/平台(。
u16
for utf-16。
u32
用于UTF-32。
另外,请注意,您用来保存源文件的字符集可能会影响编译器解释字符串文字的方式。因此,请确保您选择将文件保存在诸如UTF-8中的任何字符集,都告诉编译器该charset是什么,否则您最终可能会在运行时遇到错误的字符串值。
当我们将UTF-8编码字符存储在
std::string
中时,什么会发生什么变化?它们是否仅限于单字节ASCII字符,还是可以是多字节?
每个字符串字符可以是单字节,也可能是Unicode CodePoint的多字节表示的一部分。它取决于字符串的编码,并且字符被编码。
就像 std::wstring
(当wchar_t
为2个字节时(和std::u16string
可以容纳包含UNICODE BMP之外的补充字符的字符串一样,它需要UTF-16代理才能编码。
字符串容器包含UTF编码的字符串时,每个字符''只是UTF编码的CodeUnit。UTF-8编码UNICODE CODEPOINT为1-4 CODENITS(std::string)
中的1-4 char
s。UTF-16中的CODEPOINT编码为1-2 codeunits(1-2 wchar_t
s/ char16_t
s in std::wstring
/ std::u16string
(。-32编码一个编码点为1 CodeUnit(std::u32string
中的1 char32_t
(。
当我执行以下操作时会发生什么?
std::string s = u8"foo"; s += 'x';
正是您期望的。std::string
容纳char
元素。无论编码如何,operator+=(char)
都会简单地将一个char
附加到std::string
的末尾。
如何区分UTF
char[]
和非UTFchar[]
或std::string
?
您需要在外面了解字符串的原始编码,或者对char[]
/std::string
数据执行自己的启发式分析,以查看它是否符合UTF。
WCHAR_T和其他多字节字符类型之间有什么区别?
字节大小和UTF编码。
char
= ANSI/MBC或UTF-8
wchar_t
= DBC,UTF-16或UTF-32,具体取决于编译器/平台
char8_t
= utf-8
char16_t
= utf-16
char32_t
= utf-32
WCHAR_T字符或WCHAR_T字符串文字能够存储UTF编码?
是的,UTF-16或UTF-32,具体取决于编译器/平台。在UTF-16的情况下,单个wchar_t
只能保留BMP中的代码点值。UTF-32中的单个wchar_t
可以保持任何编码点值。wchar_t
字符串可以编码任何编码中的所有编码点。
如何正确操纵UTF字符串(例如Toupper/Tolower转换(并同时与语言兼容?
这是一个非常广泛的话题,值得自己独立问题。
- 使用CMake检测支持的C++标准
- 如何理解C++标准N3337中的expr.const.cast子句8
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- 编译标准库类型
- 标准是否使用多余的大括号(例如 T{{{10}}})定义列表初始化?
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 铸造标准::有没有回到原来的类型
- 标准 N3337 5.2.10 第 7 条中的C++"类型"是什么意思?
- this_thread::sleep_for和计时时钟之间的关系是否由C++11标准指定
- 标准库类型的赋值运算符的引用限定符
- 标准是否严格定义了该程序应该如何编译?
- 如何从Windows应用程序输出到标准?
- 安全到标准:移动会员?
- 如何正确将字符串转换为标准::时间::system_clock::time_point?
- 这是否符合C++标准:双响双响,例如!!(-0.0).
- 标准::变体的赋值运算符
- 捕获标准输出以压缩并使用 CTRL-C 中断会给出损坏的 zip 文件
- 使用C 17处理Unicode的有效,符合标准的机制是什么
- 标准库是否有比较器反转机制
- 是否有标准的机制来检索C字符串的哈希值?