2012-02-26 8 views
5

Wchar_t ve char arasında, komut satırında kendisine iletilen bir dizi yerel konum kullanılarak dönüştürmeyi sınayan basit bir program var. Yerel adın ve dönüştürülmeyen dizenin yazdırılmasıyla başarısız olan dönüşümlerin bir listesini verir.xlocale kırık?

Ben clang ve libC++ kullanarak yapıyorum. Anladığım kadarıyla, libC++ adlı yerel destek, OS X üzerinde xlocale kitaplığı tarafından sağlanır.

Bazı beklenmedik hataların yanı sıra, dönüştürmenin başarısız olduğu bazı durumlarda da göremiyorum.

İşte program. İşte

#warning call this program like: "locale -a | ./a.out" or pass \ 
locale names valid for your platform, one per line via standard input 

#include <iostream> 
#include <codecvt> 
#include <locale> 
#include <array> 

template <class Facet> 
class usable_facet : public Facet { 
public: 
    // FIXME: use inheriting constructors when available 
    // using Facet::Facet; 
    template <class ...Args> 
    usable_facet(Args&& ...args) : Facet(std::forward<Args>(args)...) {} 
    ~usable_facet() {} 
}; 

int main() { 
    std::array<std::wstring,11> args = {L"a",L"é",L"¤",L"€",L"Да",L"Ψ",L"א",L"আ",L"✈",L"가",L""}; 

    std::wstring_convert<usable_facet<std::codecvt_utf8<wchar_t>>> u8cvt; // wchar_t uses UCS-4/UTF-32 on this platform 

    int convert_failures = 0; 
    std::string line; 
    while(std::getline(std::cin,line)) { 
     if(line.empty()) 
      continue; 

     using codecvt = usable_facet<std::codecvt_byname<wchar_t,char,std::mbstate_t>>; 
     std::wstring_convert<codecvt> convert(new codecvt(line)); 

     for(auto const &s : args) { 
      try { 
       convert.to_bytes(s); 
      } catch (std::range_error &e) { 
       convert_failures++; 
       std::cout << line << " : " << u8cvt.to_bytes(s) << '\n'; 
      } 
     } 
    } 

    std::cout << std::string(80,'=') << '\n'; 
    std::cout << convert_failures << " wstring_convert to_bytes failures.\n"; 
} 

İşte

en_US.ISO8859-15 : € 

Euro karakter ISO 8859-15 charset bulunabileceğini ve yok beklenmemektedir çıktı bir örnek doğru çıktı

en_US.ISO8859-1 : € 
en_US.US-ASCII : ✈ 

bazı örnekler Yani bu başarısız olmamalı.

İşte beklediğim ama

en_US.ISO8859-15 : ¤ 
en_US.US-ASCII : ¤ 

Bu ISO 8859-1 var ama kaldırılır ve ISO 8859-15 euro simgesini ile değiştirildi para birimi simgesi olduğunu almazlar çıktı örnekleridir. Bu dönüşüm başarılı olmamalı, ancak hiçbir hata bildirilmiyor. Bu durumu incelerken, her iki durumda da '¤', '¤' ISO 8859-1 gösterimi olan 0xA4'e dönüştürüldüğünü buluyorum.

Yalnızca libC++ aracılığıyla xlocale doğrudan kullanmıyorum. Mac OS X üzerinde xlocale sadece kötü yerel tanımları ile kırılmış mı? Düzeltmenin bir yolu var mı? Yoksa başka bir şeyin sonucunu gördüğüm konular mı?

cevap

3

Xlocale sistemiyle ilgili sorunlar gördüğünüzden şüpheleniyorum. Bir bug report en çok takdir edilecektir!

+2

tamamlandı. id 10935025 – bames53

+0

Hala 10.8'de kırılmış görünüyor :(Belki de xlocale verilerine ulaşmanın ve el ile düzeltme yapmanın bir yolu var mı? – bames53

+0

UTF-32'nin aslında OS X'deki tüm yereller tarafından wchar_t kodlaması olarak kullanılmadığı ortaya çıkıyor. Oldukça talihsiz olan, – bames53

-1

Neden wchar_t'nin UTF-32 olmasını beklediğinizi veya "OS X'in wchar_t'sinin UTF-32 olduğuna dair sözleşmesini" duyduğunuzu bilmiyorum. Bu kesinlikle yanlış. wchar_t sadece 16 bit genişliğindedir.

Wchar_t hakkında daha fazla bilgi için http://en.wikipedia.org/wiki/Wide_character adresine bakın.

+3

'wchar_t' OS X'de 32 bit genişliğinde ve en unix işletim sistemlerinde değil, 16. – bames53

+1

… Wikipedia'nın diğer platformlarda da 8 bit olabileceğini belirttiği bir gerçektir. +11, bunu çözmek için char16_t' ve char32_t' ekler, ancak bu ilgisizdir. – Potatoswatter