Unicode std::string 类替换

Posted

技术标签:

【中文标题】Unicode std::string 类替换【英文标题】:Unicode std::string class replacement 【发布时间】:2011-05-17 08:22:08 【问题描述】:

我正在寻找有关 unicode 感知 std::string 库替换的建议。我有一堆使用 std::string 的代码,它的迭代器等,现在想支持 unicode 字符串(首选免费或开源实现,正则表达式功能会很棒!)。

此时我不确定我是否需要完全重写,或者我是否可以放弃放入支持所有 std::string 接口的新字符串库。 unicode 世界似乎非常复杂,我只是想在我的应用程序中启用它,而不必学习它的每一个方面。

顺便说一句,当索引运算符必须传回对 1、2、3 或 4 结构的引用时,它在理论上可以更改为 1、2、3 或 4 字节结构。如果传递一个更大或更小的值,内部数据表示的来回移动是否发生在原地?

【问题讨论】:

总是有 std::wstring,它提供了一个由宽字符组成的字符串 - 但是这不能保证与 unicode 一起使用(大小取决于平台),但它可能会有所帮助。但这将是 std::string 的简单替代品,因为它被定义为:typedef std::basic_string<wchar> wstring @icabod 使用 std::wstring 本身并不能解决发帖者的问题,它仍然会给出不正确的结果,例如length()。事实上,如果所有数据都以 UTF8 格式存储,std::string 就足够了。另请参阅:***.com/questions/402283/stdwstring-vs-stdstring。 【参考方案1】:

如果你确定你的 std::string 包含什么,你不需要完全重写。例如,您可以假设(并确保转换输入)您的 std::string 包含 UTF8 编码的字符串(对于那些需要本地化的字符串)。不要忘记 std::string 只是原始数据的容器,它与编码无关(即使在 C++0x 中,这只是一种可能性,而不是必需的)。

然后当你将文本传递给其他需要不同编码的库时,你可以使用像 UTF8CPP 这样的库来转换为所需的编码(但大多数时候这些库会自己做)。

这样就很简单了。 UTF8 在您的代码中带有标准 std::string,可以将 unicode 字符串传递给其他所有内容(必要时进行转换)。

在 boost 社区邮件列表中对此进行了很多讨论。也许阅读它(如果你有足够的时间......)可以帮助你了解其他可能的解决方案。

【讨论】:

我发现这是一个很好的解决方案。但是请注意,Microsoft 编写的任何库都会假定基于 char 的字符串是“ANSI”编码而不是 UTF-8,因此您必须围绕这些函数编写包装器。 是的,您必须确保仅在需要时完成这些转换,而不是在其余代码中。【参考方案2】:

根据您的需要,使用 std::wstring 或更大更复杂(但事实上的标准)ICU:http://site.icu-project.org/

【讨论】:

【参考方案3】:

您需要什么 unicode 编码?如果 utf-8 没问题,你可以看看Glib::ustring

Glib::ustring 有很多相同的 接口为 std::string,但包含 Unicode 字符编码为 UTF-8。

【讨论】:

请注意,Glib::ustring (应该)非常不能容忍非法字符序列;此外,如果它们通过了,例如在构造函数中,Glib 将通过调用 std::string((char*) 0) 而不是抛出描述性异常来让事情崩溃。【参考方案4】:

要求“类似 std::string 的类型,但用于 Unicode”就像要求“类似无符号的类型,但用于素数”。 std::string 完全能够以多种编码存储 Unicode - 最常用的是 UTF-8。

您需要替换的是您的迭代器,而不是您的存储类型。迭代器应该迭代字符串的代码点而不是字节。也就是说,++i 应该前进一个代码点,*i 应该返回一个代码点(通过 uint32_t)而不是 char

【讨论】:

“能够以多种编码方式存储 Unicode” 不正确。它能够以 UTF-8 存储 Unicodeonly。如果你想计算 CESU-8(坏主意)和 UTF-7(古老,已弃用),也许计数会上升到 3。但它仍然不是“很多” @Mihai:也是 GB 18030 和修改后的 UTF-8。您可能会争辩说这些都不重要(尽管当您需要修改后的 UTF-8 时,您通常需要它)。我认为除了 UTF-16 和 UTF-32 之外没有任何编码真的很重要,所以根据您的统计,任何数据类型都没有“很多”编码可以支持。 std::string 也完全能够存储,例如编码为 8859-1 的 Unicode 子集。重点是“Unicode 支持”与“存储格式”不同,std::string 提供了一种非常有用的存储格式。【参考方案5】:

我已经编写了自己的C++ UTF-8 library,它是std::wstring/string 的直接替换。显示给用户的数据类型是char32_t,但在内部,宽字符都被打包成utf8 char's。

整个过程非常快,而且它的性能最好,在许多 ascii 代码点中只有很少的 unicode 代码点。从 std::string 已知的所有操作都可用于此类(子字符串 find 除外)并且在代码点索引上操作,与字节索引相反。

作为防御性编程的一个好处,0-255 的整个 ANSI 范围都可以在没有多字节的情况下使用:)

希望这会有所帮助!

【讨论】:

以上是关于Unicode std::string 类替换的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Unicode 集将 std::string 传递给 CreateDirectory

ustring - std::string/std::wstring 的就地替换?

用 std::vector<std::string> 替换命令行参数 int argc 和 char** argv

用空格替换 std::string 中的特定字符

在 std::string 上执行正则表达式搜索和替换

替换由谓词确定的std :: string中的字符的最stl-ish方法是啥?