使用C 17处理Unicode的有效,符合标准的机制是什么

What is the efficient, standards-compliant mechanism for processing Unicode using C++17?

本文关键字:标准 机制 是什么 有效 17处理 Unicode 使用      更新时间:2023-10-16

简短版本:
如果我想编写可以通过Unicode字符有效执行操作的程序,可以在UTF-8或UTF-16编码中输入和输出文件。C 的合适方法是什么?

长版:
C 早于Unicode,并且从那以后都显着发展。我需要知道如何编写符合标准的C 代码,该代码无泄漏。我需要一个清晰的答案:

  • 我应该选择哪个字符串容器?

    • 用UTF-8?
    • std::string
    • std::wstring(对此并不了解(
    • 用UTF-16的std::u16string
    • std::u32string with utf-32?
  • 我应该完全粘在上述容器之一上还是在需要时更改它们?

  • 当使用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::u16stringchar32_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 chars。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[]和非UTF char[]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转换(并同时与语言兼容?

这是一个非常广泛的话题,值得自己独立问题。