การเข้ารหัส Unicode สำหรับตัวอักษรสตริงใน C ++ 11


85

จากคำถามที่เกี่ยวข้องฉันต้องการถามเกี่ยวกับอักขระใหม่และประเภทลิเทอรัลสตริงใน C ++ 11 ดูเหมือนว่าตอนนี้เรามีอักขระสี่ประเภทและตัวอักษรสตริงห้าประเภท ประเภทอักขระ:

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

และตัวอักษรสตริง:

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)

คำถามคือ: คือ\x/ \u/ \Uอ้างอิงตัวได้อย่างอิสระร่วมกับทุกประเภทสตริง? ประเภทสตริงทั้งหมดมีความกว้างคงที่หรือไม่กล่าวคืออาร์เรย์มีองค์ประกอบอย่างแม่นยำเท่าที่ปรากฏในลิเทอรัลหรือถึง\x/ \u/ \Uการอ้างอิงจะขยายเป็นจำนวนไบต์ตัวแปรหรือไม่ Do u""และu8""สตริงมีการเข้ารหัสความหมายเช่นฉันพูดได้char16_t x[] = u"\U0010FFFF"ไหมและจุดรหัสที่ไม่ใช่ BMP ได้รับการเข้ารหัสเป็นลำดับ UTF16 สองหน่วยหรือไม่ และในทำนองเดียวกันสำหรับu8? ใน (1) ฉันสามารถเขียนตัวแทนคนเดียวด้วยได้\uหรือไม่? สุดท้ายมีการเข้ารหัสฟังก์ชันสตริงใด ๆ ที่รับรู้ (กล่าวคือเป็นอักขระที่รับรู้และสามารถตรวจจับลำดับไบต์ที่ไม่ถูกต้องได้)

นี่เป็นคำถามปลายเปิดเล็กน้อย แต่ฉันต้องการให้ภาพที่สมบูรณ์ที่สุดเท่าที่จะเป็นไปได้ของการเข้ารหัส UTF ใหม่และสิ่งอำนวยความสะดวกประเภทของ C ++ 11 ใหม่


4
GCC เข้ารหัสu"\U0010FFFF"เป็นคู่ตัวแทน
kennytm

คำตอบ:


57

การอ้างอิงอักขระ \ x / \ u / \ U สามารถใช้ร่วมกับสตริงทุกประเภทได้อย่างอิสระหรือไม่

ฉบับที่\xสามารถใช้ในการอะไร แต่\uและ\Uสามารถนำมาใช้เฉพาะในสายที่มี UTF-เข้ารหัสเฉพาะ อย่างไรก็ตามสำหรับสตริงที่เข้ารหัส UTF \uและ\Uสามารถใช้ได้ตามที่เห็นสมควร

ประเภทสตริงทั้งหมดมีความกว้างคงที่หรือไม่กล่าวคืออาร์เรย์มีองค์ประกอบอย่างแม่นยำเท่าที่ปรากฏในลิเทอรัลหรือการอ้างอิงถึง \ x / \ u / \ U จะขยายเป็นตัวแปรจำนวนไบต์หรือไม่

ไม่ใช่ในแบบที่คุณหมายถึง \x, \uและ\Uจะถูกแปลงอยู่บนพื้นฐานของการเข้ารหัสสตริง จำนวน "หน่วยรหัส" เหล่านั้น (โดยใช้เงื่อนไข Unicode A char16_tคือหน่วยรหัส UTF-16) ขึ้นอยู่กับการเข้ารหัสของสตริงที่มี ลิเทอรัลu8"\u1024"จะสร้างสตริงที่มี 2 charวินาทีบวกเทอร์มิเนเตอร์ว่าง ลิเทอรัลu"\u1024"จะสร้างสตริงที่มี 1 char16_tบวกเทอร์มิเนเตอร์ว่าง

จำนวนหน่วยรหัสที่ใช้ขึ้นอยู่กับการเข้ารหัส Unicode

สตริง u "" และ u8 "" มีการเข้ารหัสความหมายหรือไม่เช่นฉันสามารถพูดได้ว่า char16_t x [] = u "\ U0010FFFF" และจุดรหัสที่ไม่ใช่ BMP ได้รับการเข้ารหัสเป็นลำดับ UTF16 สองหน่วยหรือไม่

u""สร้างสตริงเข้ารหัส UTF-16 u8""สร้างสตริงเข้ารหัส UTF-8 ซึ่งจะเข้ารหัสตามข้อกำหนดของ Unicode

ใน (1) ฉันสามารถเขียนตัวแทนคนเดียวกับ \ u ได้หรือไม่?

ไม่ได้อย่างแน่นอน. ข้อกำหนดห้ามชัดแจ้งโดยใช้ UTF-16 คู่ตัวแทน (0xD800-0xDFFF) เป็น codepoints สำหรับหรือ\u\U

สุดท้ายมีการเข้ารหัสฟังก์ชันสตริงใด ๆ ที่รับรู้ (กล่าวคือเป็นอักขระที่รับรู้และสามารถตรวจจับลำดับไบต์ที่ไม่ถูกต้องได้)

ไม่ได้อย่างแน่นอน. ให้ฉันเขียนข้อความนั้นใหม่

std::basic_stringไม่จัดการกับการเข้ารหัส Unicode พวกเขาสามารถจัดเก็บสตริงที่เข้ารหัส UTF ได้อย่างแน่นอน แต่พวกเขาเท่านั้นที่สามารถคิดว่าพวกเขาเป็นลำดับของchar, char16_tหรือchar32_t; พวกเขาไม่สามารถคิดว่ามันเป็นลำดับของจุดรหัส Unicode ที่เข้ารหัสด้วยกลไกเฉพาะ basic_string::length()จะส่งคืนจำนวนหน่วยรหัสไม่ใช่จุดรหัส และเห็นได้ชัดว่าฟังก์ชันสตริงไลบรารีมาตรฐาน C นั้นไร้ประโยชน์โดยสิ้นเชิง

อย่างไรก็ตามควรสังเกตว่า "ความยาว" สำหรับสตริง Unicode ไม่ได้หมายถึงจำนวนจุดรหัส จุดรหัสบางจุดกำลังรวม "อักขระ" (ชื่อที่ไม่ดี) ซึ่งรวมกับจุดรหัสก่อนหน้า จุดรหัสหลายจุดจึงสามารถแมปกับอักขระภาพเดียวได้

Iostreams สามารถอ่าน / เขียนค่าที่เข้ารหัส Unicode ได้ ในการทำเช่นนั้นคุณจะต้องใช้โลแคลเพื่อระบุการเข้ารหัสและติดตั้งลงในที่ต่างๆอย่างเหมาะสม พูดง่ายกว่าทำและฉันไม่มีรหัสที่จะแสดงให้คุณเห็น


7
@ ฟิลิปป์: ไม่พวกเขาไม่ใช่ Unicode สงวนไว้โดยเฉพาะสำหรับตัวแทน UTF-16 และตามที่ระบุไว้ข้อกำหนดของ C ++ 0x กล่าวว่าการคอมไพล์จะล้มเหลวหากคุณพยายามกำหนดจุดโค้ดในช่วงนั้น
Nicol Bolas

12
ลิงก์ของคุณพิสูจน์ได้ว่าเป็นจุดรหัส หากคุณไม่เชื่อถือ Wikipedia โปรดอ่านคำจำกัดความที่ 9 และ 10 ในบทที่ 3 ของ Standard จุดรหัสตัวแทนในตัวอักษรสตริงถูกห้ามใน C ++ 0x โดยกฎ§ 2.4 / 2 แม้ว่า
Philipp

1
หลังจากอ่านฉันยืนยันเช่นกันว่าจุดรหัสตัวแทนได้รับการยอมรับในตัวอักษรสตริง
George Kourtis

ใน C11, \xไม่สามารถใช้กับอะไรเช่น U + 1F984 จะไม่ทำงานกับ \ x คำนำหน้าและ\uและ\Uไม่สามารถใช้ร่วมกับตัวควบคุม ASCII, atleast ในเสียงดังกราว
MarcusJ
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.