C ++ 11'de dize değişmezleri için Unicode kodlaması


85

İlgili bir soruyu takiben , C ++ 11'deki yeni karakter ve dize değişmez türleri hakkında soru sormak istiyorum. Görünüşe göre şimdi dört çeşit karakterimiz ve beş çeşit dizgi değişmezimiz var. Karakter türleri:

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

Ve dize değişmezleri:

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

Soru şudur: \x/ \u/ \Ukarakter başvuruları tüm dizgi türleriyle serbestçe birleştirilebilir mi? Tüm dizgi türleri sabit genişlikte mi, yani diziler tam olarak değişmez değerde göründüğü kadar çok öğe içeriyor mu, yoksa \x/ \u/ \Ubaşvuruları değişken sayıda bayta genişletiliyor mu? u""Ve u8""dizelerin kodlama semantiği var mı , örneğin diyebilirim char16_t x[] = u"\U0010FFFF"ve BMP olmayan kod noktası iki üniteli bir UTF16 dizisine kodlanır mı? Ve benzer şekilde için u8? (1) 'e yalnız vekiller yazabilir miyim \u? Son olarak, kodlama işlevlerinden herhangi biri farkında mı (yani, karakter farkındalar ve geçersiz bayt dizilerini saptayabilirler)?

Bu biraz açık uçlu bir soru, ancak yeni C ++ 11'in yeni UTF kodlama ve tür olanaklarının olabildiğince eksiksiz bir resmini elde etmek istiyorum.


4
GCC, u"\U0010FFFF"bir vekil çift olarak kodlar .
kennytm

Yanıtlar:


57

\ X / \ u / \ U karakter başvuruları tüm dize türleriyle serbestçe birleştirilebilir mi?

Hayır \xbir şey kullanılabilir, ancak \uve \Uancak özellikle UTF-kodlanmış dizeleri kullanılabilir. Bununla birlikte, herhangi bir UTF kodlu dizge için \uve \Uuygun gördüğünüz şekilde kullanılabilir.

Tüm dizge türleri sabit genişlikte mi, yani diziler tam olarak değişmez değerde göründüğü kadar çok öğe içeriyor mu, yoksa \ x / \ u / \ U başvuruları değişken sayıda bayta genişletiliyor mu?

Demek istediğin şekilde değil. \x, \uve \Udize kodlamasına göre dönüştürülür. Bu "kod birimlerinin" sayısı (Unicode terimleri kullanılarak. A char16_t, bir UTF-16 kod birimidir) değerlerinin sayısı, içeren dizinin kodlamasına bağlıdır. Hazır bilgi u8"\u1024", 2 chars artı boş sonlandırıcı içeren bir dize oluşturur . Değişmez değer u"\u1024", 1 char16_tartı boş sonlandırıcı içeren bir dize oluşturur .

Kullanılan kod birimlerinin sayısı Unicode kodlamasına bağlıdır.

U "" ve u8 "" dizgileri kodlama anlamlarına sahip mi, örneğin char16_t x [] = u "\ U0010FFFF" diyebilir miyim ve BMP olmayan kod noktası iki üniteli bir UTF16 dizisine kodlanır mı?

u""UTF-16 kodlu bir dize oluşturur. u8""UTF-8 kodlu bir dize oluşturur. Unicode spesifikasyonuna göre kodlanacaklar.

(1) 'de \ u ile yalnız vekiller yazabilir miyim?

Kesinlikle hayır. Spesifikasyon, UTF-16 vekil çiftlerinin (0xD800-0xDFFF) \uveya için kod noktaları olarak kullanılmasını açıkça yasaklar \U.

Son olarak, kodlama işlevlerinden herhangi biri farkında mıdır (yani, karakter farkındalar ve geçersiz bayt dizilerini algılayabilirler)?

Kesinlikle hayır. Peki, bunu yeniden ifade etmeme izin verin.

std::basic_stringUnicode kodlamalarıyla ilgilenmez. UTF kodlu dizeleri kesinlikle saklayabilirler . Ama sadece dizisi olarak bunlardan düşünebiliriz char, char16_tya char32_t; bunları belirli bir mekanizma ile kodlanmış bir Unicode kod noktası dizisi olarak düşünemezler. basic_string::length()kod noktalarının değil kod birimlerinin sayısını döndürür. Açıkçası, C standart kitaplık dizesi işlevleri tamamen yararsızdır

Bununla birlikte, bir Unicode dizgisinin "uzunluğunun" kod noktalarının sayısı anlamına gelmediğine dikkat edilmelidir. Bazı kod noktaları, önceki kod noktasıyla birleşen "karakterleri" (talihsiz bir ad) birleştiriyor. Böylece birden fazla kod noktası tek bir görsel karakterle eşleşebilir.

Iostreams aslında Unicode kodlu değerleri okuyabilir / yazabilir. Bunu yapmak için, kodlamayı belirtmek için bir yerel ayar kullanmanız ve onu çeşitli yerlere düzgün şekilde yerleştirmeniz gerekir. Bunu söylemek yapmaktan daha kolay ve size nasıl olduğunu gösterecek herhangi bir kodum yok.


7
@Philipp: Hayır, değiller. Unicode, bunları özellikle UTF-16 vekilleri için saklar. Ve belirtildiği gibi, C ++ 0x'in belirtimi, bu aralıkta bir kod noktası belirlemeye çalışırsanız derlemenin başarısız olacağını söylüyor.
Nicol Bolas

12
Bağlantınız onlar kanıtlıyor olan kod noktaları. Wikipedia'ya güvenmiyorsanız, Standardın 3. bölümündeki 9 ve 10 numaralı tanımları okuyun. Dize değişmezlerinde vekil kod noktaları, yine de kural 2.4 / 2 tarafından C ++ 0x'de yasaklanmıştır.
Philipp

1
Okuduktan sonra, Vekil kod noktalarının dize değişmezlerinde kabul edildiğini de onaylıyorum.
George Kourtis

C11 'de, \xörneğin U + 1F984 için, herhangi bir şeyle kullanılamaz ve, \ x önek ile çalışma olmayacak \uve \UClang içinde en az ASCII kontrol karakterleri ile kullanılamaz.
MarcusJ
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.