【问题标题】:How to uppercase a u32string (char32_t) with a specific locale?如何将具有特定语言环境的 u32string (char32_t) 大写?
【发布时间】:2018-01-16 14:50:07
【问题描述】:

在装有 Visual Studio 2017 的 Windows 上,我可以使用以下代码将 u32string 大写(基于 char32_t):

#include <locale>
#include <iostream>
#include <string>

void toUpper(std::u32string& u32str, std::string localeStr)
{
    std::locale locale(localeStr);

    for (unsigned i = 0; i<u32str.size(); ++i)
        u32str[i] = std::toupper(u32str[i], locale);
}

同样的事情不适用于 macOS 和 XCode。 我收到这样的错误:

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/__locale:795:44: error: implicit instantiation of undefined template 'std::__1::ctype<char32_t>'
return use_facet<ctype<_CharT> >(__loc).toupper(__c);

有便携的方法吗?

【问题讨论】:

  • 感觉你错过了#include。没有minimal reproducible example,很难分辨。
  • 我不认为我错过了一个头文件。我已将包含添加到示例中。
  • 也许您的编译器的 RTL 根本没有实现 ctype&lt;char32_t&gt;?附带说明一下,这似乎是您应该使用 std::transform() 而不是手动循环的东西,例如:std::locale loc(localeStr); std::transform(u32str.begin(), u32str.end(), u32str.begin(), [&amp;loc](char32_t c) -&gt; char32_t { return std::toupper(c, loc); });
  • 我想是的。有没有更好的(便携式)方法?
  • 关于这个:stackoverflow.com/a/41316811/2007933 似乎不支持ctype&lt;char32_t&gt;

标签: c++ c++11 unicode uppercase ctype


【解决方案1】:

我找到了解决办法:

我现在使用 std::stringutf8 编码,而不是使用 std::u32string。 从std::u32stringstd::string (utf8) 的转换可以通过utf8-cpp 完成:http://utfcpp.sourceforge.net/

需要将utf8字符串转换为std::wstring(因为std::toupper并非在所有平台上都为std::u32string实现)。

void toUpper(std::string& str, std::string localeStr)
{
    //unicode to wide string converter
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;

    //convert to wstring (because std::toupper is not implemented on all platforms for u32string)
    std::wstring wide = converter.from_bytes(str);

    std::locale locale;

    try
    {
        locale = std::locale(localeStr);
    }
    catch(const std::exception&)
    {
        std::cerr << "locale not supported by system: " << localeStr << " (" << getLocaleByLanguage(localeStr) << ")" << std::endl;
    }

    auto& f = std::use_facet<std::ctype<wchar_t>>(locale);

    f.toupper(&wide[0], &wide[0] + wide.size());

    //convert back
    str = converter.to_bytes(wide);
}

注意:

  • 在 Windows 上 localeStr 必须是这样的:en, de, fr, ...
  • 在其他系统上:localeStr 必须是 de_DEfr_FRen_US、...

【讨论】:

    猜你喜欢
    • 2013-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 2019-02-27
    相关资源
    最近更新 更多