C ++ 11 में यूनिकोड कितनी अच्छी तरह से समर्थित है?


183

मैंने पढ़ा है और सुना है कि C ++ 11 यूनिकोड का समर्थन करता है। उस पर कुछ सवाल:

  • C ++ मानक पुस्तकालय यूनिकोड का कितना अच्छा समर्थन करता है?
  • क्या std::stringयह क्या करना चाहिए?
  • मैं इसे कैसे इस्तेमाल करूं?
  • संभावित समस्याएं कहां हैं?

19
"क्या std :: string वह करता है जो उसे करना चाहिए?" आपको क्या लगता है कि इसे क्या करना चाहिए?
आर। मार्टिनो फर्नांडिस

2
मैं अपनी utf8 जरूरतों के लिए utfcpp.sourceforge.net का उपयोग करता हूं। इसकी एक साधारण हेडर फ़ाइल जो यूनिकोड स्ट्रिंग्स के लिए पुनरावृत्तियाँ प्रदान करती है।
fscan

2
std :: string को बाइट्स को स्टोर करना चाहिए, अर्थात UTF-8 एन्कोडिंग का कोड यूनिट अनुक्रम। हां, यह शुरुआत से ही ऐसा करता है। utf8everywhere.org
पावेल

3
यूनिकोड समर्थन के साथ सबसे बड़ी संभावित समस्याएं यूनिकोड के भीतर हैं और सूचना प्रौद्योगिकी में इसका उपयोग है। यूनिकोड इसके लिए उपयुक्त नहीं है (और डिज़ाइन नहीं किया गया है)। यूनिकोड को हर संभव ग्लिफ़ को पुन: उत्पन्न करने के लिए डिज़ाइन किया गया है जो किसी व्यक्ति द्वारा कहीं पर लिखा गया है, किसी समय में हर संभव और पांडित्य की बारीकियों के साथ संभव है, जिसमें 3 या 4 अलग-अलग अर्थ हैं और एक ही ग्लिफ़ की रचना के 3 या 4 अलग-अलग तरीके हैं। यह रोजमर्रा की भाषा के लिए उपयोग किए जाने के लिए उपयोगी होने के लिए नहीं है, और यह लागू होने या आसानी से या स्पष्ट रूप से संसाधित होने के लिए नहीं है।
डेमन

11
हाँ इसे रोजमर्रा की भाषा के लिए इस्तेमाल किया जा रहा है। कम से कम मेरा। और तुम्हारा भी शायद। यह सिर्फ यह बताता है कि सामान्य तरीके से मानव पाठ को संसाधित करना एक बहुत मुश्किल काम है। यह स्पष्ट रूप से परिभाषित करने के लिए भी संभव नहीं है कि एक चरित्र क्या है। सामान्य ग्लिफ़ प्रजनन भी वास्तव में यूनिकोड चार्टर का हिस्सा नहीं है।
बजे जीन-डेनिस मुइज

जवाबों:


267

C ++ मानक पुस्तकालय यूनिकोड का कितना अच्छा समर्थन करता है?

बहुत।

पुस्तकालय सुविधाओं के माध्यम से एक त्वरित स्कैन जो यूनिकोड समर्थन प्रदान कर सकता है, मुझे यह सूची प्रदान करता है:

  • स्ट्रींग लाइब्रेरी
  • स्थानीयकरण पुस्तकालय
  • इनपुट / आउटपुट लाइब्रेरी
  • नियमित अभिव्यक्ति पुस्तकालय

मुझे लगता है कि सभी पहले एक भयानक समर्थन प्रदान करते हैं। मैं आपके अन्य प्रश्नों के माध्यम से त्वरित चक्कर लगाने के बाद इसे और अधिक विस्तार से प्राप्त करूंगा।

क्या std::stringयह क्या करना चाहिए?

हाँ। C ++ मानक के अनुसार, यह वही है जो std::stringउसके भाई-बहनों को करना चाहिए:

वर्ग टेम्पलेट basic_stringउन वस्तुओं का वर्णन करता है जो किसी अनुक्रम को स्टोर कर सकते हैं जिसमें स्थिति शून्य के अनुक्रम के पहले तत्व के साथ मनमाने ढंग से चार-समान वस्तुओं की एक अलग संख्या शामिल है।

खैर, std::stringक्या यह ठीक है। क्या यह कोई यूनिकोड-विशिष्ट कार्यक्षमता प्रदान करता है? नहीं।

इसे होना चाहिए? शायद ऩही। वस्तुओं के std::stringअनुक्रम के रूप में ठीक है char। यह उपयोगी है; केवल झुंझलाहट यह है कि यह पाठ का एक बहुत ही निम्न-स्तरीय दृश्य है और मानक C ++ एक उच्च-स्तरीय एक प्रदान नहीं करता है।

मैं इसे कैसे इस्तेमाल करूं?

charवस्तुओं के अनुक्रम के रूप में इसका उपयोग करें ; यह दिखावा कुछ और है जो दर्द में समाप्त होता है।

संभावित समस्याएं कहां हैं?

सभी जगह? चलो देखते हैं...

स्ट्रींग लाइब्रेरी

स्ट्रिंग्स लाइब्रेरी हमें प्रदान करती है basic_string, जो केवल इस बात का एक क्रम है कि मानक "चार्-लाइक ऑब्जेक्ट्स" को क्या कहते हैं। मैं उन्हें कोड इकाइयाँ कहता हूँ। यदि आप पाठ का उच्च-स्तरीय दृश्य चाहते हैं, तो यह वह नहीं है जो आप खोज रहे हैं। यह क्रमांकन / deserialization / भंडारण के लिए उपयुक्त पाठ का एक दृश्य है।

यह सी लाइब्रेरी से कुछ उपकरण भी प्रदान करता है जिनका उपयोग संकीर्ण दुनिया और यूनिकोड दुनिया के बीच की खाई को पाटने के लिए किया जा सकता है: c16rtomb/ mbrtoc16और c32rtomb/ mbrtoc32

स्थानीयकरण पुस्तकालय

स्थानीयकरण पुस्तकालय अभी भी मानता है कि उन "चार जैसी वस्तुओं" में से एक "चरित्र" के बराबर है। यह निश्चित रूप से मूर्खतापूर्ण है, और एएससीआईआई जैसे यूनिकोड के कुछ छोटे सबसेट से परे बहुत सारी चीजें ठीक से काम करना असंभव बनाता है।

उदाहरण के लिए, <locale>हेडर में मानक "सुविधा इंटरफेस" को क्या कहते हैं :

template <class charT> bool isspace (charT c, const locale& loc);
template <class charT> bool isprint (charT c, const locale& loc);
template <class charT> bool iscntrl (charT c, const locale& loc);
// ...
template <class charT> charT toupper(charT c, const locale& loc);
template <class charT> charT tolower(charT c, const locale& loc);
// ...

कैसे आप इन कार्यों के किसी भी ठीक से वर्गीकृत, कहते हैं, U + 1F34C ʙᴀɴᴀɴᴀ की उम्मीद करते हैं, के रूप में u8"🍌"या u8"\U0001F34C"? इसका कोई तरीका नहीं है कि यह कभी भी काम करेगा, क्योंकि ये फ़ंक्शन इनपुट के रूप में केवल एक कोड इकाई लेते हैं।

यह उपयुक्त लोकेल के साथ काम कर सकता है यदि आपने char32_tकेवल उपयोग किया है : U'\U0001F34C'UTF-32 में एक एकल कोड इकाई है।

हालाँकि, इसका मतलब यह है कि आप केवल सरल आवरण परिवर्तन प्राप्त कर सकते हैं toupperऔर tolower, उदाहरण के लिए, जो कुछ जर्मन स्थानों के लिए पर्याप्त नहीं हैं: "pp" अपरकेस से "SS" you लेकिन toupperकेवल एक वर्ण कोड इकाई वापस कर सकते हैं ।

अगला, wstring_convert/ wbuffer_convertऔर मानक कोड रूपांतरण पहलू।

wstring_convertकिसी दिए गए एन्कोडिंग में स्ट्रिंग्स को दूसरे दिए गए एन्कोडिंग में स्ट्रिंग्स के बीच बदलने के लिए उपयोग किया जाता है। इस परिवर्तन में दो स्ट्रिंग प्रकार शामिल हैं, जो मानक एक बाइट स्ट्रिंग और एक विस्तृत स्ट्रिंग कहते हैं। चूंकि ये शब्द वास्तव में भ्रामक हैं, इसलिए मैं † के बजाय क्रमशः "क्रमबद्ध" और "deserialized" का उपयोग करना पसंद करता हूं।

के बीच कनवर्ट करने के लिए एन्कोडिंग एक codecvt (एक कोड रूपांतरण पहलू) द्वारा तय कर रहे हैं एक टेम्पलेट प्रकार तर्क के रूप में पारित कर दिया wstring_convert

wbuffer_convertएक समान कार्य करता है लेकिन एक विस्तृत deserialized स्ट्रीम बफ़र के रूप में जो बाइट क्रमबद्ध स्ट्रीम बफ़र को लपेटता है । किसी भी I / O को अंतर्निहित बाइट क्रमबद्ध स्ट्रीम बफर के माध्यम से किया जाता है और कोडकवेट तर्क द्वारा दिए गए एन्कोडिंग से रूपांतरण के साथ। लेखन उस बफ़र में क्रमबद्ध करता है, और फिर उसमें से लिखता है, और पठन बफ़र में पढ़ता है और फिर इससे डिस्क्राइब होता है।

मानक इन सुविधाओं के साथ उपयोग के लिए कुछ codecvt वर्ग टेम्पलेट्स प्रदान करता है: codecvt_utf8, codecvt_utf16, codecvt_utf8_utf16, और कुछ codecvtविशेषज्ञताओं। साथ में ये मानक पहलू निम्नलिखित सभी रूपांतरण प्रदान करते हैं। (नोट: निम्नलिखित सूची में, बाईं ओर एन्कोडिंग हमेशा क्रमबद्ध स्ट्रिंग / स्ट्रीमब्यूफ़ है, और दाईं ओर एन्कोडिंग हमेशा डीज़रीलाइज़्ड स्ट्रिंग / स्ट्रीमब्यूफ़ है; मानक दोनों दिशाओं में रूपांतरण की अनुमति देता है)।

  • UTF-8 CS UCS-2 के साथ codecvt_utf8<char16_t>, और codecvt_utf8<wchar_t>कहाँ sizeof(wchar_t) == 2;
  • UTF-8 ↔ साथ UTF-32 codecvt_utf8<char32_t>, codecvt<char32_t, char, mbstate_t>, और codecvt_utf8<wchar_t>जहां sizeof(wchar_t) == 4;
  • यूटीएफ -16 CS यूसीएस -2 के साथ codecvt_utf16<char16_t>, और codecvt_utf16<wchar_t>कहां sizeof(wchar_t) == 2;
  • UTF-16 16 UTF-32 के साथ codecvt_utf16<char32_t>, और codecvt_utf16<wchar_t>कहाँ sizeof(wchar_t) == 4;
  • UTF-8 ↔ साथ UTF-16 codecvt_utf8_utf16<char16_t>, codecvt<char16_t, char, mbstate_t>, और codecvt_utf8_utf16<wchar_t>जहां sizeof(wchar_t) == 2;
  • साथ संकीर्ण with चौड़ा codecvt<wchar_t, char_t, mbstate_t>
  • के साथ नहीं codecvt<char, char, mbstate_t>

इनमें से कई उपयोगी हैं, लेकिन यहां बहुत अजीब चीजें हैं।

सबसे पहले - पवित्र उच्च सरोगेट! नामकरण योजना गड़बड़ है।

फिर, UCS-2 का बहुत समर्थन है। यूसीएस -2 यूनिकोड 1.0 से एक एन्कोडिंग है जो 1996 में छोड़ी गई थी क्योंकि यह केवल मूल बहुभाषी विमान का समर्थन करता है। समिति ने 20 साल पहले एक एन्कोडिंग पर ध्यान केंद्रित करना क्यों उचित समझा, मुझे नहीं पता irable। यह अधिक एन्कोडिंग के लिए समर्थन की तरह नहीं है खराब या कुछ भी है, लेकिन यूसीएस -2 यहां अक्सर दिखाता है।

मैं कहूंगा कि char16_tस्पष्ट रूप से UTF-16 कोड इकाइयों के भंडारण के लिए है। हालांकि, यह मानक का एक हिस्सा है जो अन्यथा सोचता है। codecvt_utf8<char16_t>UTF-16 से कोई लेना-देना नहीं है। उदाहरण के लिए, wstring_convert<codecvt_utf8<char16_t>>().to_bytes(u"\U0001F34C")ठीक संकलन करेगा, लेकिन बिना शर्त विफल हो जाएगा: इनपुट को यूसीएस -2 स्ट्रिंग के रूप में माना जाएगा u"\xD83C\xDF4C", जिसे यूटीएफ -8 में परिवर्तित नहीं किया जा सकता है, क्योंकि यूटीएफ -8 0xD800-0xFFFF में किसी भी मूल्य को एन्कोड नहीं कर सकता है।

अभी भी UCS-2 मोर्चे पर, इन पहलुओं के साथ UTF-16 स्ट्रिंग में UTF-16 बाइट स्ट्रीम से पढ़ने का कोई तरीका नहीं है। यदि आपके पास UTF-16 बाइट्स का एक अनुक्रम है, तो आप इसे स्ट्रिंग में स्ट्रिंग में शामिल नहीं कर सकते char16_t। यह आश्चर्य की बात है, क्योंकि यह कम या ज्यादा एक पहचान रूपांतरण है। हालांकि इससे भी ज्यादा आश्चर्य की बात यह है कि यह तथ्य है कि यूटीएस -16 स्ट्रीम से यूसीएस -2 स्ट्रिंग के साथ डिसरसाइज करने का समर्थन है codecvt_utf16<char16_t>, जो वास्तव में एक हानिकारक रूपांतरण है।

UTF-16-as-bytes समर्थन काफी अच्छा है, हालांकि: यह एक BOM से धीरज का पता लगाने, या कोड में स्पष्ट रूप से चयन करने का समर्थन करता है। यह BOM के साथ और उसके बिना भी उत्पादन का समर्थन करता है।

कुछ और दिलचस्प रूपांतरण संभावनाएं अनुपस्थित हैं। UTF-16 बाइट स्ट्रीम या स्ट्रिंग से एक UTF-8 स्ट्रिंग में deserialize करने का कोई तरीका नहीं है, क्योंकि UTF-8 को deserialized फॉर्म के रूप में कभी भी समर्थित नहीं किया गया है।

और यहाँ संकीर्ण / विस्तृत दुनिया UTF / UCS दुनिया से पूरी तरह से अलग है। पुरानी शैली की संकीर्ण / विस्तृत एन्कोडिंग और किसी भी यूनिकोड एन्कोडिंग के बीच कोई रूपांतरण नहीं हैं।

इनपुट / आउटपुट लाइब्रेरी

I / O लाइब्रेरी का उपयोग यूनिकोड एन्कोडिंग में पाठ को पढ़ने और लिखने के लिए किया जा सकता है wstring_convertऔर wbuffer_convertऊपर वर्णित सुविधाओं का उपयोग कर । मुझे नहीं लगता कि मानक पुस्तकालय के इस हिस्से द्वारा समर्थित होने की आवश्यकता है।

नियमित अभिव्यक्ति पुस्तकालय

मैंने पहले भी स्टैक ओवरफ्लो पर C ++ रीगेक्स और यूनिकोड के साथ समस्याओं पर विस्तार किया है । मैं यहां उन सभी बिंदुओं को नहीं दोहराऊंगा, लेकिन केवल यह बताता हूं कि C ++ रीजैक्स में स्तर 1 यूनिकोड समर्थन नहीं है, जो कि हर जगह UTF-32 का उपयोग किए बिना उन्हें उपयोग करने योग्य बनाने के लिए न्यूनतम न्यूनतम है।

बस?

हाँ बस यही। वह मौजूदा कार्यक्षमता है। यूनिकोड कार्यक्षमता बहुत है जो सामान्यीकरण या पाठ विभाजन एल्गोरिदम की तरह कहीं नहीं देखी जा सकती है।

U + 1F4A9 । क्या C ++ में कुछ बेहतर यूनिकोड समर्थन प्राप्त करने का कोई तरीका है?

सामान्य संदिग्धों: ICU और Boost.Locale


Ly एक बाइट स्ट्रिंग, अनिश्चित रूप से, बाइट्स की एक स्ट्रिंग है, अर्थात, charऑब्जेक्ट। हालांकि, एक विस्तृत स्ट्रिंग शाब्दिक के विपरीत , जो हमेशा wchar_tवस्तुओं का एक सरणी होता है, इस संदर्भ में एक "विस्तृत स्ट्रिंग" आवश्यक रूप से wchar_tवस्तुओं का एक स्ट्रिंग नहीं है । वास्तव में, मानक कभी भी स्पष्ट रूप से परिभाषित नहीं करता है कि "वाइड स्ट्रिंग" का क्या अर्थ है, इसलिए हमें उपयोग से अर्थ का अनुमान लगाने के लिए छोड़ दिया गया है। चूंकि मानक शब्दावली सुस्त और भ्रमित है, इसलिए मैं स्पष्टता के नाम पर अपने स्वयं के उपयोग करता हूं।

UTF-16 जैसी एन्कोडिंग को अनुक्रम के रूप में संग्रहीत किया जा सकता है char16_t, जिसमें तब कोई धीरज नहीं होता है; या उन्हें बाइट्स के अनुक्रम के रूप में संग्रहीत किया जा सकता है, जिसमें एंडियननेस होता है (बाइट्स की प्रत्येक लगातार जोड़ी char16_tएंडियननेस के आधार पर एक अलग मूल्य का प्रतिनिधित्व कर सकती है )। मानक इन दोनों रूपों का समर्थन करता है। char16_tकार्यक्रम में आंतरिक हेरफेर के लिए एक अनुक्रम अधिक उपयोगी है। बाइट्स का एक क्रम बाहरी दुनिया के साथ ऐसे तार का आदान-प्रदान करने का तरीका है। "बाइट" और "वाइड" के बजाय मैं जिन शब्दों का उपयोग करूँगा, वे इस प्रकार "क्रमबद्ध" और "डिसेरिएलाइज़्ड" हैं।

‡ यदि आप कहने वाले हैं "लेकिन विंडोज!" अपना 🐎🐎 पकड़ो । Windows 2000 से Windows के सभी संस्करण UTF-16 का उपयोग करते हैं।

☦ हां, मैं ग्रोस एस्ज़ेट (,) के बारे में जानता हूं , लेकिन भले ही आप रात भर में सभी जर्मन स्थानों को overnight अपरकेस में बदल दें, फिर भी बहुत सारे अन्य मामले हैं जहां यह विफल हो जाएगा। Uppercasing U + FB00 U sʟɪɢᴀᴛᴜʀᴇ ғғ ing की कोशिश करें। कोई ʟᴀᴛɪɴ ᴄᴀᴘɪᴛᴀʟ ʟɪɢᴀᴛᴜʀᴇ ғғ नहीं है; यह सिर्फ दो एफएस पर अपरकेस है। या U + 01F0 ʟᴀᴛɪɴ sᴍᴀʟʟ + 0 0 0; कोई पूर्वनिर्धारित पूंजी नहीं है; यह सिर्फ एक राजधानी जे और एक संयोजन कैरन के लिए अपरकेस है।


26
जितना अधिक मैं इसके बारे में पढ़ता हूं, उतना ही मुझे इस सब के बारे में एक बात नहीं समझने का एहसास होता है। मैंने इस सामान को कुछ महीने पहले पढ़ा था और अभी भी ऐसा महसूस कर रहा हूं कि मुझे पूरी बात फिर से पता चल रही है ... मेरे गरीब मस्तिष्क के लिए इसे सरल रखने के लिए कि अब थोड़ा दर्द होता है, utf8everywhere पर ये सभी सलाह अभी भी मान्य हैं, सही? अगर मैं "सिर्फ" चाहता हूं कि मेरे उपयोगकर्ता अपनी सिस्टम सेटिंग्स को खोलने और लिखने में सक्षम हों, तो मैं उनसे फाइल का नाम पूछ सकता हूं, इसे std में स्टोर कर सकता हूं: स्ट्रिंग और सब कुछ ठीक से काम करना चाहिए, यहां तक ​​कि विंडोज पर भी? यह पूछने के लिए खेद है कि (फिर से) ...
उफ्लेक्स

5
@ यूफ्लेक्स आप वास्तव में एसटीडी के साथ कर सकते हैं :: स्ट्रिंग को बाइनरी ब्लॉब के रूप में माना जाता है। एक उचित यूनिकोड कार्यान्वयन में न तो आंतरिक (क्योंकि यह कार्यान्वयन विवरण में गहरा छिपा हुआ है) और न ही बाहरी एन्कोडिंग मामले (अच्छी तरह से, आपको अभी भी एनकोडर / डिकोडर उपलब्ध होने की आवश्यकता है)।
कैट प्लस प्लस

3
@ यूलेक्स शायद। मुझे नहीं पता कि अगर आप सलाह को नहीं मानते हैं तो यह एक अच्छा विचार है।
आर। मार्टिनो फर्नांडिस

1
C ++ 2014/17 में यूनिकोड समर्थन का प्रस्ताव है। हालाँकि यह 1 है, शायद 4 साल दूर है और अब बहुत कम उपयोग हो रहा है। open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3572.html
graham.reeds

20
@ graham.reeds हाहा, धन्यवाद, लेकिन मुझे इस बारे में पता था। "आभार" खंड की जांच करें;)
आर। मार्टिनो फर्नांडिस

40

यूनिकोड मानक लाइब्रेरी ( समर्थित के किसी भी उचित अर्थ के लिए) द्वारा समर्थित नहीं है ।

std::stringइससे बेहतर नहीं है std::vector<char>: यह यूनिकोड (या किसी अन्य प्रतिनिधित्व / एन्कोडिंग) के लिए पूरी तरह से अनजान है और बस इसकी सामग्री को बाइट्स के बूँद के रूप में मानते हैं ।

आप केवल दुकान और कड़ी लगाकर जोड़ना करने के लिए की जरूरत है धब्बे , यह बहुत अच्छी तरह से काम करता है; लेकिन जैसे ही आप यूनिकोड कार्यक्षमता ( कोड अंक , अंगूर की संख्या आदि) की इच्छा करते हैं , आप भाग्य से बाहर हो जाते हैं।

इसके लिए मुझे पता है कि एकमात्र व्यापक पुस्तकालय आईसीयू है । C ++ इंटरफ़ेस को जावा एक से लिया गया था, हालांकि यह मुहावरेदार होने से बहुत दूर है।


2
Boost.Locale के बारे में कैसे ?
उफ़्लेक्स

11
@ यूफ्लेक्स: आपके द्वारा लिंक किए गए पृष्ठ से इस लक्ष्य को प्राप्त करने के लिए Boost.Locale ने यूनिकोड के लिए अत्याधुनिक यूनिकोड और स्थानीयकरण पुस्तकालय: ICU - International Components का उपयोग किया है।
मैथ्यू एम।

1
Boost.Locale अन्य गैर-ICU बैकएंड का समर्थन करता है, यहाँ देखें: boost.org/doc/libs/1_53_0/libs/locale/doc/html/…
Superfly जॉन

@SuperflyJon: सच है, लेकिन उसी पृष्ठ के अनुसार, गैर-आईसीयू बैकेंड के यूनिकोड का समर्थन "गंभीर रूप से सीमित" है।
मथिउ एम।

24

आप सुरक्षित रूप से एक में UTF-8 स्टोर कर सकते हैं std::string(या में एक char[]या char*, उस बात के लिए), तथ्य यह है कि एक यूनिकोड NUL (U + 0000) UTF-8 में एक अशक्त बाइट है की वजह से है और इस एकमात्र तरीका एक अशक्त है कि यूटीएफ -8 में बाइट हो सकती है। इसलिए, आपके UTF-8 स्ट्रिंग्स को C और C ++ स्ट्रिंग फ़ंक्शन के सभी के अनुसार ठीक से समाप्त किया जाएगा, और आप उन्हें C ++ iostreams (सहित std::coutऔर std::cerrजब तक आपका लोकल UTF-8 है) के साथ चारों ओर स्लिंग कर सकते हैं ।

आप std::stringUTF-8 के लिए क्या नहीं कर सकते हैं कोड बिंदुओं में लंबाई है। std::string::size()आपको बाइट्स में स्ट्रिंग की लंबाई बताएगा , जो केवल यूटीएफ -8 के एएससीआईआई सबसेट के भीतर कोड बिंदुओं की संख्या के बराबर है।

यदि आपको कोड पॉइंट स्तर पर UTF-8 स्ट्रिंग्स पर काम करने की आवश्यकता है (अर्थात सिर्फ स्टोर नहीं करें और उन्हें प्रिंट करें) या यदि आप UTF-16 के साथ काम कर रहे हैं, जिसमें कई आंतरिक नल बाइट्स होने की संभावना है, तो आपको गौर करने की आवश्यकता है विस्तृत चरित्र स्ट्रिंग प्रकार।


3
std::stringबस ठीक nulls के साथ iostreams में फेंका जा सकता है।
आर। मार्टिनो फर्नांडिस

3
यह पूरी तरह से इरादा है। यह बिल्कुल भी नहीं टूटता c_str()क्योंकि size()अभी भी काम करता है। केवल टूटे हुए एपीआई (यानी जो सी दुनिया के अधिकांश की तरह एम्बेडेड नल को संभाल नहीं सकते हैं) टूट जाते हैं।
आर। मार्टिनो फर्नांडिस

1
एंबेडेड नल टूट जाते हैं c_str()क्योंकि c_str()माना जाता है कि डेटा को एक शून्य-टर्म सी स्ट्रिंग के रूप में लौटाया जाता है --- जो कि असंभव है, इस तथ्य के कारण कि सी स्ट्रिंग में एम्बेडेड नल नहीं हो सकते हैं।
इक़ेलमैन

4
अब और नहीं। c_str()अब बस के रूप में एक ही लौटाता है data(), यानी यह सब। आकार लेने वाले API इसका उपभोग कर सकते हैं। एपीआई, जो नहीं कर सकते।
आर। मार्टिनो फर्नांडिस

6
मामूली अंतर से जो c_str()यह सुनिश्चित करता है कि परिणाम NUL char-like ऑब्जेक्ट के बाद है, और मुझे नहीं लगता data()है। नहींं, data()अब जैसा दिखता है वैसा ही है। (बेशक, यह एपीआई के लिए आवश्यक नहीं है जो एक टर्मिनेटर खोज से इसे संदर्भित करने के बजाय आकार का उपभोग करता है)
बेन Voigt

8

C ++ 11 में यूनिकोड के लिए कुछ नए शाब्दिक स्ट्रिंग प्रकार हैं

दुर्भाग्य से गैर-समान एन्कोडिंग (जैसे यूटीएफ -8) के लिए मानक पुस्तकालय में समर्थन अभी भी खराब है। उदाहरण के लिए UTF-8 स्ट्रिंग की लंबाई (कोड-पॉइंट में) प्राप्त करने का कोई अच्छा तरीका नहीं है।


तो क्या हमें अभी भी std का उपयोग करने की आवश्यकता है :: यदि हम गैर-लैटिन भाषाओं का समर्थन करना चाहते हैं, तो फ़ाइल नामों के लिए wstring? क्योंकि आमतौर पर नए स्ट्रिंग शाब्दिक यहां मदद नहीं करते हैं क्योंकि आमतौर पर स्ट्रिंग उपयोगकर्ता से आते हैं ...
Uflex

7
@ यूफ़्लेक्स समस्या के बिना UTF-8 स्ट्रिंग पकड़std::string सकता है, लेकिन उदाहरण के लिए विधि स्ट्रिंग में बाइट्स की संख्या लौटाती है और कोड-पॉइंट की संख्या नहीं। length
कुछ प्रोग्रामर ने

8
सच कहूं तो, एक स्ट्रिंग के कोड पॉइंट्स में लंबाई प्राप्त करने से कई उपयोग नहीं होते हैं। उदाहरण के लिए, बाइट्स में लंबाई का उपयोग सही ढंग से पूर्व-आवंटित बफ़र्स के लिए किया जा सकता है।
आर। मार्टिनो फर्नांडिस

2
UTF-8 स्ट्रिंग में कोड बिंदुओं की संख्या बहुत दिलचस्प संख्या नहीं है: कोई ñ'LATIN SMALL LETTER N WITH TILDE' (U + 00F1) (जो एक कोड बिंदु है) या 'LATIN SMALL LETTER N' (के रूप में लिख सकता है ) U + 006E) के बाद 'COMBINING TILDE' (U + 0303) जो दो कोड पॉइंट हैं।
मार्टिन बोनर

उन सभी टिप्पणियों के बारे में "आपको इसकी आवश्यकता नहीं है और आपको इसकी आवश्यकता नहीं है" जैसे "कोड संख्या की संख्या महत्वहीन" आदि मेरे लिए थोड़ी गड़बड़ लगती है। एक बार जब आप एक पार्सर लिखते हैं जो utf8 स्रोत कोड को सॉर्ट करने के लिए माना जाता है, तो यह पार्सर के विनिर्देश पर निर्भर करता है कि वह LATIN SMALL LETTER N' == मानता है या नहीं (U+006E) followed by 'COMBINING TILDE' (U+0303)
BitTickler

4

हालाँकि, एक बहुत ही उपयोगी पुस्तकालय है जिसे छोटे-utf8 कहा जाता है , जो मूल रूप से / के लिए एक ड्रॉप-इन प्रतिस्थापन है । इसका उद्देश्य अभी भी लापता utf8-string कंटेनर वर्ग के अंतराल को भरना है।std::stringstd::wstring

यह utf8 स्ट्रिंग्स के साथ 'निपटने' का सबसे आरामदायक तरीका हो सकता है (यानी, यूनिकोड के सामान्यीकरण और समान सामान के बिना)। आप आराम से कोडपॉइंट पर काम करते हैं , जबकि आपका स्ट्रिंग रन-लेंथ-इनकोडेड chars में एन्कोडेड रहता है ।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.