当前位置: 首页 > 知识库问答 >
问题:

使用C 17处理Unicode的高效、符合标准的机制是什么?

严正初
2023-03-14

简短版本:
如果我想编写可以有效地执行Unicode字符操作的程序,能够以UTF-8或UTF-16编码输入和输出文件。用C来做到这一点的适当方法是什么?

长版本:
C早于Unicode,从那以后两者都有了显着的发展。我需要知道如何编写符合标准的无泄漏C代码。我需要一个明确的答案:

>

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

    • 标准::字符串与 UTF-8?
    • 标准:::wstring(真的不太了解它)
    • 标准::u16 字符串与 UTF-16?
    • 标准::u32 字符串与 UTF-32?

    我应该完全坚持上述容器之一还是在需要时更换它们?

    当使用 UTF 字符串时,我是否可以在字符串文本中使用非英语字符,例如波兰语字符:ąćęłńśźż 等?

    当我们将UTF-8编码字符存储在std::string中时,会发生什么变化?它们是限于一个字节的ASCII字符还是可以是多字节的?
    当我执行以下操作时会发生什么?

     std::string s = u8"foo";
     s += 'x';
    

    wchar_t和其他多字节字符类型有什么区别?wchar_t字符或wchar_tstring文字是否能够存储UTF编码?

  • 共有1个答案

    洪育
    2023-03-14

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

    这真的取决于你自己根据自己的特殊需求来决定。您提出的任何选择都将起作用,并且它们都有自己的优点和缺点。通常,UTF-8 适合用于存储和通信目的,并且向后兼容 ASCII。而 UTF-16/32 在处理统一码数据时更易于使用。

    std::wstring(不太了解它)

    wchar_t的大小取决于编译器,甚至取决于平台。例如,在 Windows 上,wchar_t为 2 个字节,因此标准::wstring 可用于 UTF-16 编码的字符串。在其他平台上,wchar_t可能是 4 个字节,这使得 std::wstring 可用于 UTF-32 编码的字符串。这就是为什么wchar_t/std::wstring通常不在可移植代码中使用,以及为什么在C 11中引入了char16_t/std::u16字符串和char32_t/std::u32字符串。对于 UTF-8,即使 char 也可能存在可移植性问题,因为在编译器供应商的排序中,char 可以是有符号的,也可以是无符号的,这就是为什么在 C 20 中为 UTF-8 引入了 char8_t/std::u8string 的原因。

    我应该完全坚持上述容器之一还是在需要时更换它们?

    使用任何适合你需要的容器。

    通常,您应该在整个代码中使用一种字符串类型。仅在字符串数据进入/离开程序的边界处执行数据转换。例如,当读/写文件、网络通信、平台系统调用等时。

    如何在两者之间正确转换?

    有很多方法可以解决这个问题。

    C 11 及更高版本有标准::wstring_convert/标准::wbuffer_convert。但这些在C 17中被弃用了。

    有第三方Unicode转换库,如ICONV、ICU等。

    有C库函数,平台系统调用等。

    当使用 UTF 字符串时,我是否可以在字符串文本中使用非英语字符,例如波兰语字符:ąćęłńśźż 等?

    是的,如果您使用适当的字符串前缀:

    u8用于UTF-8。

    < code>L适用于UTF-16或UTF-32(取决于编译器/平台)。

    u16用于UTF-16。

    适用于UTF-32的< code>u32。

    另请注意,用于保存源文件的字符集可能会影响编译器解释字符串文本的方式。因此,请确保您选择用于保存文件的任何字符集(如 UTF-8),您都会告诉编译器该字符集是什么,否则您可能会在运行时得到错误的字符串值。

    当我们在标准::字符串中存储UTF-8编码字符时,会发生什么变化?它们是限制为单字节 ASCII 字符,还是可以是多字节字符?

    每个字符串字符可以是单字节,也可以是 Unicode 代码点的多字节表示形式的一部分。这取决于字符串的编码和要编码的字符。

    就像标准::wstring(当wchar_t为 2 个字节时)和 std::u16 字符串可以保存包含 Unicode BMP 外部补充字符的字符串一样,这需要 UTF-16 代理项进行编码。

    当字符串容器包含 UTF 编码字符串时,每个“字符”只是一个 UTF 编码的代码单元。UTF-8 将 Unicode 代码点编码为 1-4 个代码单元(标准::字符串中为 1-4 个字符)。UTF-16 将代码点编码为 1-2 个代码单元(在标准::wstring/std:u16 字符串中为 1-2 wchar_t s/char16_ts)。UTF-32 将代码点编码为 1 个代码单元(在 std::u32 字符串为 1 个char32_t)。

    当我执行以下操作时会发生什么?

    std::string s = u8"foo";
    s += 'x';
    

    正如你所料。< code>std::string包含< code>char元素。不管编码是什么,< code>operator =(char)都会在< code>std::string的末尾附加一个< code>char。

    如何区分UTF char[]和非UTF char[]或< code>std::string?

    您需要了解字符串的原始编码,或者对< code > char[]/< code > STD::string 数据进行自己的启发式分析,看看它是否符合UTF。

    wchar_t和其他多字节字符类型有什么区别?

    字节大小和 UTF 编码。

    char=ANSI/MBCS或UTF-8

    < code>wchar_t = DBCS、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转换)并同时兼容地区?

    这是一个非常广泛的议题,本身就值得单独提出这个问题。

     类似资料:
    • 我有一个巨大的csv文件作为原始数据源(14 gb)。我想创建一个场景,其中每个请求都包含来自csv的元素,解析为JSON对象并包装为JSON数组。 我现在尝试的是使用预处理我的csv文件,并将其转储到单列下的新csv文件中,如下所述:https://stackoverflow.com/a/65845365/2290763 然后我使用我的输出csv文件(50gb)作为Gatling进纸器,并将该单

    • 在您开始叫喊未定义的行为之前,N4659(C 17)中明确列出了这一点 然而在N3337(C 11) 什么改变了? 从[N4659 basic.exec]中收集到的信息 除非另有说明,否则对单个运算符的操作数和单个表达式的子表达式的求值是不排序的。[...] 运算符操作数的值计算在运算符结果的值计算之前排序。如果一个内存位置上的副作用相对于同一内存位置上的另一个副作用或使用同一内存位置中任何对象的

    • 问题内容: 我有一个非常大的XML文件,需要将其转换为另一个XML文件,并且我想使用XSLT做到这一点。我对内存优化而不是速度优化更感兴趣(尽管速度也不错!)。 您将推荐使用哪个基于Java的XSLT处理器? 您是否会推荐其他方法(非XSLT,非Java?),如果可以,为什么? 问题中的XML文件很大,但不是很深-有数百万行(元素),但只有大约3个级别。 问题答案: 目前,只有三个 已知的XSLT

    • 本文向大家介绍GO语言标准错误处理机制error用法实例,包括了GO语言标准错误处理机制error用法实例的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了GO语言标准错误处理机制error用法。分享给大家供大家参考。具体分析如下: 在 Golang 中,错误处理机制一般是函数返回时使用的,是对外的接口,而异常处理机制 panic-recover 一般用在函数内部。 error 类型介绍 e

    • 问题内容: 我正在编写一个Java程序,用于从POP3电子邮件中下载附件。最初,我通过获取MimePart的内容类型得到验证的输入流来执行此操作。然后,我可以简单地通过FileOutputStream将输入流写入本地文件。 但是,我遇到的一件事是,当我收到一封带有附件的电子邮件作为唯一内容并访问它之后,该邮件(消息类型)仅由一个部分组成,即文本/普通类型。其内容包括大量随机外观的字符。 通过互联网

    • 本文向大家介绍什么是iOS的目标-动作机制 ?相关面试题,主要包含被问及什么是iOS的目标-动作机制 ?时的应答技巧和注意事项,需要的朋友参考一下 目标是动作消息的接收者。一个控件,或者更为常见的是它的单元,以插座变量(参见"插座变量"部分) 的形式保有其动作消息的目标。 动作是控件发送给目标的消息,或者从目标的角度看,它是目标为了响应动作而实现的方法。 程序需要某些机制来进行事件和指令的翻译。这