使用带有UTF-8字符串的boost :: format%s说明符

时间:2011-05-09 19:27:37

标签: c++ utf-8 boost-format

我们正在为具有大量代码库的现有应用程序添加对UTF8的支持。此应用程序使用boost::format(),非ASCII字符的输出未正确对齐。具体来说,当使用%{width}.{length} s说明符时,boost::format()会计算字符数,而字符数不会与utf8字符串“做正确的事情”。我认为应该可以更改字符串长度代码(可能 string::size())以使用utf8len()或类似的东西,基于......某些东西?

在这种情况下,将现有代码库更改为使用UCS2(或UCS4或UTF-16等)是不切实际的,但如果需要,可以修改boost::format()。我希望其他人遇到这种需求,并指出我可能的解决方案。

注意:我在使用带有utf8的语言环境时发现了一些网页,但大多数网页似乎更适用于在流中转换为utf8和UCS4。

2 个答案:

答案 0 :(得分:0)

这对你来说可能为时已晚,但也许它会帮助别人。 Boost :: format接受std :: locale作为可选模板参数。 (见http://www.boost.org/doc/libs/1_55_0/libs/format/doc/format.html)。如果你传递一个unicod感知的语言环境,比如boost :: locale(" en_US.UTF-8"),你应该得到所需的行为。

您可以设置应用程序的默认语言环境,而不是每次都将语言环境传递给boost :: format构造函数,这可以帮助您避免其他问题。如果你选择这条路线,我会建议在std :: locale上使用boost :: locale,因为boost :: locale' s不会修改你的数字格式,除非你明确地要求它( docs here)。

通常,这是一种goto方法,可以使C ++中的应用程序与Unicode很好地协同工作。如果功能可以使用语言环境(std :: regex,std :: sort,boost :: format),给它一个unicode感知语言环境,你应该是安全的(如果你不是,请告诉我,我想要知道)。

如果您正在制作一个小型,轻量级的应用程序而只关心80%的情况,您可能不想为包含ICU(Unicode的国际组件)付出代价,这是默认引擎提升语言环境在提供unicde时所包含的支持。在这种情况下,使用您的操作系统或Posix unicode支持构建Boos,您的应用程序将保持小而轻,但您不会获得很多unicode支持,例如多个校对级别。

对于您所描述的问题,Posix支持可能已经足够了。

答案 1 :(得分:0)

即使使用基于UTF-8的语言环境,AFAIK Boost Format也会以代码为单位测量所有内容。

如果可以切换到另一个库,请考虑使用C ++ 20 std::format{fmt} formatting library,它们以显示宽度为单位计算宽度(类似于wcswidth),因此对齐正确。例如

fmt::print("┌{0:─^{2}}┐\n"
           "│{1: ^{2}}│\n"
           "└{0:─^{2}}┘\n", "", "Hello, world!", 20);

打印:

┌────────────────────┐
│   Hello, world!    │
└────────────────────┘

免责声明:我是{fmt}和C ++ 20 std :: format

的作者