4

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

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

注意:我发现了一些关于将语言环境与 utf8 结合使用的网页,但其中大部分似乎更适用于在流中转换为 utf8 和 UCS4。

4

2 回答 2

1

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

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

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

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

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

于 2015-08-21T11:49:09.773 回答
0

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

如果您可以切换到另一个库,请考虑 C++20std::format{fmt} 格式化库,它以显示宽度单位计算宽度(类似于wcswidth),因此对齐是正确的。例如

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

印刷:

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

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

于 2020-06-24T22:46:33.527 回答