2016-12-12 17 views
6

wchar_t, char16_t veya char32_t değerini dar bir ostream ile beslerseniz, kod noktasının sayısal değerini yazdıracaktır.iostreams - "wchar_t" veya "charXX_t" değerini karakter olarak yazdırma

baskılar x120120120. Bunun nedeni, basic_ostream'un charT ile belirli bir kombinasyonu için operator<< olmasıdır, ancak diğer karakter türleri için benzer operatörler olmadığından, sessizce int'a dönüştürülür ve bu şekilde yazdırılır. Benzer bir şekilde, sigara dar dize hazır (L"x", u"x", U"X") sessizce dize (wstring, u16string, u32string) da derlenmez nesneleri void* dönüştürülür ve işaretçi değeri olarak basılmış ve olmayan dar olacaktır.

Yani, soru: dar ostream üzerinde karakteri yerine kod noktasıyla sayısal değer olarak daha gibi bir wchar_t, char16_t veya char32_t değerini yazdırmak için en az korkunç yolu nedir? Bu kodlamada, kodlamanın kodlamada gösterilebilen tüm kod noktalarını doğru bir şekilde dönüştürmesi gerekir ve kod noktası gösterilemediğinde bir hata bildirmelidir. (Örneğin, u'…' verildi ve UTF-8 ostream, üç baytlık sekansı 0xE2 0x80 0xA6 akışına yazılmalıdır fakat u'â' verildi ve KOI8-R ostream, bir hata rapor edilmelidir.) Aynı şekilde

Bir dar dar alan üzerinde dar bir C-string veya string nesnesi nasıl basılır, çıktı kodlamasına dönüştürülebilir?

Bu, ISO C++ 11 içinde yapılamazsa, platforma özel yanıtlar alırım.

(this question esinlenerek.)

+2

, ya 1) geniş bir ostream kullanmak zorunda veya 2)) bir potansiyel kayıplı dönüşüm olan (kendini kodlayan dar geniş karakter verileri dönüştürmek. Bir ostream sizin için bu dönüşümü yapamaz. ['Std :: wstring_convert'] 'a bakın (http: //en.cppreference.com/w/cpp/locale/wstring_convert) veya [ICONV] (https://www.gnu.org/software/libiconv/) veya [ICU] gibi bir kütüphane kullanın (http: //site.icu-project. org /). –

cevap

2

sen belirtildiği gibi, dar bir ostream için herhangi operator<<(std::ostream&, const wchar_t) yoktur. Eğer sözdizimini kullanmak isterseniz, ostream'u wchar s ile nasıl yapacağınızı öğretin, böylece bu rutin ilk önce bir tamsayıya dönüştürme gerektiren bir daha iyi bir aşırı yük olarak seçilmelidir.

Maceracı hissediyorsanız:

namespace std { 
    ostream& operator<< (ostream& os, wchar_t wc) { 
    if(unsigned(wc) < 256) // or another upper bound 
     return os << (unsigned char)wc; 
    else 
     throw your_favourite_exception; // or handle the error in some other way 
    } 
} 

Aksi takdirde, şeffaf bir wchar_t kapsar ve özel bir friend operator<< sahip basit struct yapmak ve bunları çıktısını almadan bu şekilde geniş karakterleri dönüştürün.

Düzenleme: için yerel ayarı unutmayın

ostream& operator<< (ostream& os, wchar_t wc) { 
    std::mbstate_t state{}; 
    std::string mb(MB_CUR_MAX, '\0'); 
    size_t ret = std::wcrtomb(&mb[0], wc, &state); 
    if(ret == static_cast<std::size_t>(-1)) 
     deal_with_the_error(); 
    return os << mb; 
} 

: sen gibi <cwchar> gelen işlevlerini kullanabilirsiniz, ve yerel ayarlarından bir on-the-fly dönüşüm yapmak için sistem varsayılan: kısaca

std::locale::global(std::locale("")); 
std::cout << L'ŭ'; 
+0

Bu, değeri dar çıktı kodlamasına dönüştürmez. Bu zorunlu ve ayrıca nasıl yapıldığını bilmediğim bir parça. – zwol

+0

@zwol ASCII içinde olması ve başka türlü reddetmesi durumunda, geniş bir karakteri nasıl kabul edeceğinizden daha çok nasıl dönüştürmek istersiniz? Daha sonra, örneğin, vurguları veya bir şeyi kaldırarak belirli olmanız gerekir. –

+0

Örneğinizde, bunu geçen 'x' harfi (“L'x” için, diğer türler için de aynısını yapmanız gerekir) kullanır, bu yüzden peşinde olduğunuzu varsaydım. –

İlgili konular