【问题标题】:(Encoded) String handling in C++ - questions / best practices?(编码)C++ 中的字符串处理 - 问题/最佳实践?
【发布时间】:2009-01-11 20:26:36
【问题描述】:

在 C++ 中处理字符串的最佳实践是什么?我特别想知道如何处理以下情况:

  • 文本和 XML 文件的文件输入/输出,可以用不同的编码编写。处理此问题的推荐方法是什么,以及如何检索这些值?我想,一个 XML 节点可能包含 UTF-16 文本,然后我必须以某种方式处理它。

  • 如何处理char* 字符串。毕竟,这可以是无符号的,我想知道我如何确定他们使用什么编码(ANSI?),以及如何转换为 UTF-8?是否有任何推荐阅读,其中记录了 C/C++ 关于字符串的基本保证?

  • UTF-8 等字符串的字符串算法——计算长度、解析等。如何做到最好?

  • 真正可移植的字符类型是什么?我了解到wchar_t 可以是 8-32 位宽,如果我想跨平台保持一致(特别是在不同平台之间移动数据时 - 这似乎是一个问题,如前所述例如EASTL, look at item #13)

目前,我在任何地方都在使用std::string,在调用 Unicode-API 时,我使用了一个小的帮助实用程序来转换为 UTF-16,但我很确定这并不是最好的方法。使用 Qt 的 QString 或 ICU String 类似乎是正确的,但我想知道是否有更轻量级的方法(即如果我的 char 字符串是 ANSI 编码的,并且使用的 ANSI 子集等于UFT-8,然后我可以轻松地将数据视为 UTF-8 并提供从/到 UTF-8 的转换器,我已经完成了,因为我可以将它存储在 std::string 中,除非这种方法存在问题)。

【问题讨论】:

    标签: c++ string unicode


    【解决方案1】:

    为了简单起见,我只建议使用 UTF-16;为了简单起见,Java/C#/Python 3.0 完全切换到该模型。 我一直期望 wchar_t 为 16 位或 32 位宽,许多平台都支持这一点;实际上,像 wcrtomb() 这样的 API 不允许实现支持 wchar_t* 的转换状态,但由于 UTF-8 不需要,因此可以使用它,而排除其他编码。

    然后,我回答关于 XML 的问题。

    文本和 XML 文件的文件输入/输出,可以用不同的编码编写。处理此问题的推荐方法是什么,以及如何检索这些值?我想,一个 XML 节点可能包含 UTF-16 文本,然后我必须以某种方式处理它。

    我不确定,但我不这么认为。 在同一个文件中混合两种编码会带来麻烦和数据损坏。 以 UTF-16 编码文件通常是一个糟糕的选择,因为大多数程序都依赖于在任何地方使用 ASCII。 问题是:XML 文件可能使用任何单一编码,甚至可能是 UTF-16,但初始编码声明也必须使用 UTF-16,甚至标签。我看到 UTF-16 的问题是:如何可靠地解析初始声明?答案在规范中:,第 4.3.3 节:

    在没有外部传输协议(例如 HTTP 或 MIME)提供的信息的情况下,包含编码声明的实体以声明中指定的编码以外的编码呈现给 XML 处理器,这是一个致命错误,或者对于既不以字节顺序标记也不以编码声明开头的实体使用 UTF-8 以外的编码。请注意,由于 ASCII 是 UTF-8 的子集,普通的 ASCII 实体并不严格需要编码声明。

    阅读时,请注意 XML 文件也是一个实体,称为文档实体;一般来说,实体是文档的存储单元。从整个规范来看,我会说每个实体只允许一个编码声明,并且在阅读它们时我会将所有实体转换为 UTF-16 以便于处理。

    网络摄影:

    【讨论】:

    • 在运行时将所有内容编码为 UTF-16 似乎有点浪费,不是吗?我假设我必须为每个字符串文字执行此操作,或者在它们前面都加上 L 以便默认情况下它们很宽(但 L 本身并不意味着它将是 UTF-16,所以我仍然可能需要转换)。有什么想法吗?
    • Java 使用 UCS-2 为简单起见。当时是固定宽度的编码。
    【解决方案2】:

    UTF-8 等字符串的字符串算法——计算长度、解析等。如何做到最好?

    mbrlen 为您提供 C 字符串的长度。我不认为 std::string 可以用于多字节字符串,您应该将 wstring 用于宽字符串。

    一般来说,您应该在程序中坚持使用 UTF-16,并且仅在 I/O 上使用 UTF-8(我不太了解其他选项,但它们肯定更复杂且容易出错)。

    如何处理 char* 字符串。毕竟,这可以是无符号的,我想知道我如何确定他们使用什么编码(ANSI?),以及如何转换为 UTF-8?是否有任何推荐阅读,其中记录了 C/C++ 关于字符串的基本保证?

    基本上,您可以使用任何编码,而且您会碰巧使用运行系统的本机编码,只要它是 8 位编码。 C 是为 ASCII 而生的,语言环境处理是事后才想到的。多年来,每个系统都主要理解一种本机编码,例如 ISO-8859-x,而来自另一种编码的文件甚至可能无法表示。

    因为对于 UTF-8 字符串,一个字节并不总是一个字符,我最安全的选择是对它们使用多字节字符串。我使用的 C 手册抽象地描述了多字节字符串,没有详细说明这些问题(特别是使用的编码)。对于 C,请参见 mbrlen 和 mbrtowc 等函数。在我的 Linux 系统上,注意到它们的行为取决于 LC_CTYPE,这可能意味着多字节字符串的本机类型。从文档中可以推断出他们的 API 也支持编码,您可以从一个字节转换为两个字节并返回。

    如何处理 char* 字符串。毕竟,这可以是未签名的,也可以是不签名的,

    如果您依赖 char 的签名,那么您做错了。仅当您将 char 用作数字类型时,字符的签名才重要,然后您应该始终使用无符号或有符号字符;实际上,您应该假设普通 char 既不是无符号也不是有符号的,并且像 a > 0 (如果 a 是 char)这样的表达式具有未定义的语义。但是它到底有什么用呢?

    【讨论】:

    • 嗯,这与我是否将 char 视为 unsigned 或 signed 无关,问题是,这会产生什么问题吗?从 EASTL 的资料中可以看出,他们显然对此有问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-18
    相关资源
    最近更新 更多