【问题标题】:C++ Solaris Uppercase conversion for special characters does not work特殊字符的 C++ Solaris 大写转换不起作用
【发布时间】:2015-02-23 14:07:36
【问题描述】:

我正在使用以下代码进行大写转换。 我软件中的字符串是 UTF8 编码的。以下代码在 Windows、AIX 和 Linux(均为 64 位)上运行良好,但在 Solaris 上无法运行(SunOS 5.10 Generic_147440-01 sun4u sparc SUNW,SPARC-Enterprise)。

在 Solaris 上,诸如“ä”之类的特殊字符不会被转换为等效的大写字母。但是,诸如“a”、“b”等 ASCII 字符正在正确转换为大写。

void String::MakeUpperUTF8()
{
    WCHAR *pwstr =  GetUnicode(); // Decode UTF8 encoded string to wide char string using iconv

     if (!pwstr)
    {
        return; // return if decode fails.
    }

    std::locale::global(std::locale("")); 
    const std::ctype<WCHAR>& f = std::use_facet< std::ctype<WCHAR> >(std::locale()); // using std //ctype facet and std locale convert string to uppercase   

    f.toupper(pwstr, pwstr + wcslen(pwstr)); 
    char *strPos = SetUnicode( pwstr, -1); // encode string back to UTF8

}

你能帮帮我吗?我想知道为什么这段代码在 Solaris 上不起作用。

【问题讨论】:

  • 您的默认语言环境是什么?
  • 你能举例说明你得到的结果吗?例如,如果您输入“ä”(c3 a4),您得到的是哪个字符(和值)而不是“Ä”(c3 84)?
  • 我的默认语言环境是 en_US.UTF-8。以下是 solaris 上 locale 命令的输出: LANG=en_US.UTF-8 LC_CTYPE="en_US.UTF-8" LC_NUMERIC="en_US.UTF-8" LC_TIME="en_US.UTF-8" LC_COLLATE="en_US. UTF-8" LC_MONETARY="en_US.UTF-8" LC_MESSAGES="en_US.UTF-8" LC_ALL=en_US.UTF-8
  • 字符“ä”未转换为任何字符。它保持不变。 '001Öäabc' 是我的输入字符串。该字符串被转换为“001ÖäABC”。大写转换时忽略特殊字符。
  • 可能您在 Solaris 上的语言环境已损坏。 This works on Linux 并且应该几乎可以在任何地方工作。它可以在你的机器上运行吗?

标签: c++ utf-8 solaris uppercase


【解决方案1】:

感谢大家的帮助。

我使用以下代码解决了我的问题。标准 C++ 方面在 Solaris 上不起作用。因此我使用了 towupper() Solaris API。

#if defined (SUN) || (__sun)
        for (long i=0; i < nWLength; ++i)
        {
            pwstr[i] = towupper(pwstr[i]);
        }
    #else
        const std::ctype<WCHAR>& f = std::use_facet< std::ctype<WCHAR> >(std::locale()); // using std ctype facet and std locale convert string to uppercase   
        f.toupper(pwstr, pwstr + nWLength); 
    #endif

谢谢, 苏米特

【讨论】:

    【解决方案2】:

    除了C 之外,我尝试过的任何语言环境都失败了以下代码:

    #include <locale>
    int main() {
        std::locale::global( std::locale("") );
        return 0;
    }
    

    内置(-std=c++0x好像没有效果,也试过-ansi结果一样):

    g++ -ggdb -Wall -std=c++0x solaris_locale.cc
    g++ -ggdb -Wall solaris_locale.cc
    

    失败:

    $ locale
    LANG=en_US.UTF-8
    LC_CTYPE="en_US.UTF-8"
    LC_NUMERIC="en_US.UTF-8"
    LC_TIME="en_US.UTF-8"
    LC_COLLATE="en_US.UTF-8"
    LC_MONETARY="en_US.UTF-8"
    LC_MESSAGES="en_US.UTF-8"
    LC_ALL=
    $ ./a.out 
    terminate called after throwing an instance of 'std::runtime_error'
      what():  locale::facet::_S_create_c_locale name not valid
    Abort (core dumped)
    

    作品:

    $ LANG=C ./a.out
    

    GDB 回溯给出:

    (gdb) bt
    #0  0xfe579265 in _lwp_kill () from /lib/libc.so.1
    #1  0xfe57218a in thr_kill () from /lib/libc.so.1
    #2  0xfe520fed in raise () from /lib/libc.so.1
    #3  0xfe4f875d in abort () from /lib/libc.so.1
    #4  0xfe7343d5 in __gnu_cxx::__verbose_terminate_handler ()
        at /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/libstdc++-v3/libsupc++/vterminate.cc:93
    #5  0xfe7313c5 in __cxxabiv1::__terminate (
        handler=0xfe734280 <__gnu_cxx::__verbose_terminate_handler()>)
        at /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/libstdc++-v3/libsupc++/eh_terminate.cc:39
    #6  0xfe731422 in std::terminate ()
        at /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/libstdc++-v3/libsupc++/eh_terminate.cc:49
    #7  0xfe731591 in __cxa_throw (obj=0x8061af0, tinfo=0xfe7652ec, 
        dest=0xfe725bb0 <~runtime_error>)
        at /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/libstdc++-v3/libsupc++/eh_throw.cc:83
    #8  0xfe71e927 in std::__throw_runtime_error (
        __s=0xfe735e18 "locale::facet::_S_create_c_locale name not valid")
        at /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/build/i86/i386-pc-solaris2.11/libstdc++-v3/include/bits/basic_string.h:233
    #9  0xfe72e790 in std::locale::facet::_S_create_c_locale (__cloc=@0xfeffec5c, 
        __s=0x8061254 "en_US.UTF-8") at c++locale.cc:66
    #10 0xfe735e18 in .LC11 () from /usr/lib/libstdc++.so.6
    #11 0x00000000 in ?? ()
    

    机器信息:

    $ uname -a
    SunOS os 5.11 11.1 i86pc i386 i86pc
    $ g++ -v
    Using built-in specs.
    COLLECT_GCC=g++
    COLLECT_LTO_WRAPPER=/usr/gcc/4.5/lib/gcc/i386-pc-solaris2.11/4.5.2/lto-wrapper
    Target: i386-pc-solaris2.11
    Configured with: /builds/hudson/workspace/nightly-update/build/i386/components/gcc45/gcc-4.5.2/configure CC=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/cc CXX=/ws/on11update-tools/SUNWspro/sunstudio12.1/bin/CC --prefix=/usr/gcc/4.5 --mandir=/usr/gcc/4.5/share/man --bindir=/usr/gcc/4.5/bin --libdir=/usr/gcc/4.5/lib --sbindir=/usr/gcc/4.5/sbin --infodir=/usr/gcc/4.5/share/info --libexecdir=/usr/gcc/4.5/lib --enable-languages=c,c++,fortran,objc --enable-shared --with-gmp-include=/usr/include/gmp --with-mpfr-include=/usr/include/mpfr --without-gnu-ld --with-ld=/usr/bin/ld --with-gnu-as --with-as=/usr/gnu/bin/as CFLAGS='-g -O2 '
    Thread model: posix
    gcc version 4.5.2 (GCC) 
    

    我会假设 Solaris C++ 语言环境支持不完整/损坏。

    【讨论】:

    • 我怀疑 glibc 语言环境!= 本地语言环境,而 libstdc++ 只能与 glibc 很好地配合。也许您可以尝试链接到 glibc 的相同测试,也可以使用 Sun 的本机编译器。
    • @n.m.我正在使用操作系统附带的g++ 版本,它是机器上唯一的C/C++ 编译器。我在 C 程序(不是 C++)中测试了setlocale(LC_ALL, "");,在同一台机器上使用gcc 构建,它似乎可以工作(至少mbstowcs() 可以与 UTF8 一起使用)。我认为从源代码安装 glibc 与这个问题无关。
    • 从源代码安装 glibc 会浪费时间,因为 glibc 不能在 Solaris 上构建/使用 - 它不支持 Solaris 系统调用,仅支持 Linux 系统调用。
    • @alanc 据我所知,有一个 OpenSoplaris 端口
    • @alanc 虽然我看到它已经有一段时间没有更新了,所以这可能不是一个好主意。
    猜你喜欢
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-01
    • 2011-09-26
    • 1970-01-01
    相关资源
    最近更新 更多