C ++ Solaris特殊字符的大写转换不起作用

时间:2014-12-26 07:24:38

标签: c++ utf-8 solaris uppercase

我使用以下代码进行大写转换。 我的软件中的字符串是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。

2 个答案:

答案 0 :(得分:0)

以下代码在我尝试过的除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 ++语言环境支持不完整/已损坏。

答案 1 :(得分:0)

谢谢你的帮助。

我使用以下代码解决了我的问题。标准C ++ facet在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

谢谢, 萨米特