boost库的string_algo中的to_upper函数没有考虑到本地化。

3

我在string_algo包中的函数遇到了问题。

看一下这段代码:

#include <boost/algorithm/string.hpp>
int main() {
   try{
      string s = "meißen";
      locale l("de_DE.UTF-8");
      to_upper(s, l);
      cout << s << endl;
   catch(std::runtime_error& e){
      cerr << e.what() << endl;
   }

   try{
      string s = "composición";
      locale l("es_CO.UTF-8");
      to_upper(s, l);
      cout << s << endl;
   catch(std::runtime_error& e){
      cerr << e.what() << endl;
   }
}

这段代码的预期输出应该是:
MEISSEN
COMPOSICIÓN

然而,我得到的唯一的东西是:
MEIßEN
COMPOSICIóN

很明显地,区域设置没有被考虑进去。我甚至尝试设置全局区域设置也没有成功。我该怎么办?


UTF-8是一种很好的传输格式。但在内存中并不那么理想,因为每个代码点可以是1到4个字符。在内存中使用UCS-2更容易,因为它是固定大小的(注意,UTF-16由于代理对而再次变成可变大小)。 - Martin York
4个回答

3
除了Éric Malenfant的答案之外,std::locale facets只适用于单个字符。要获得更好的结果,您可以使用std::wstring,这样就可以转换更多的字符,但是仍然不完美(例如ß)。我建议尝试一下Boost.Locale(一个新的boost库,还没有被包含在boost中),它可以做到这一点。

http://cppcms.sourceforge.net/boost_locale/docs/,

特别是请参考http://cppcms.sourceforge.net/boost_locale/docs/index.html#conversions,该链接涉及到您所讨论的问题。

1

std::toupper假定1:1转换,因此ß到SS的情况无望,无论使用Boost.StringAlgo与否。

查看StringAlgo的代码,我们可以看到它确实使用了locale(似乎除了Borland)。因此,对于另一种情况,我很好奇:在您的平台上,toupper('ó',std::locale("es_CO.UTF-8"))的结果是什么?

写上面的内容让我想到了另一件事:您的源字符串的编码是什么?UTF8?在这种情况下,std::toupper将看到'ó'的两个代码单元,因此没有希望。Latin1?在这种情况下,使用名为".UTF-8"的locale是不一致的。


我的源代码使用UTF-8编码。当我尝试使用std::toupper('o', std::locale("es_CO.UTF-8"))时,会出现警告“多字符字符常量”,并且我不会得到任何答案,而是一个错误:terminate called after throwing an instance of 'std::bad_cast' what(): std::bad_cast。 - Sambatyon
1
正如我在答案中所写:toupper逐个字符处理字符串。UTF-8中的'ó'占用两个字节,因此没有希望toupper能够产生有意义的结果。您需要使用一种编码,使得您的字符可以用单个代码单元表示。在当前情况下,我看到两个选择:Latin1和char字符串,或者UTF-16(或32,取决于平台上sizeof(wchar_t)的大小)和wchar_t字符串。 - Éric Malenfant

0
在标准库中,有std::toupper(即boost::to_upper使用的函数),它一次处理一个字符。
这就解释了为什么ß不起作用。您没有说您使用哪个标准库和代码页,因此我不知道为什么ó不起作用。
如果您使用wstring会发生什么?

0
你可以使用 boost::locale。 这里 有一个例子。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接