std :: wstring वीएस std :: स्ट्रिंग


740

मैं std::stringऔर के बीच के अंतर को समझने में सक्षम नहीं हूं std::wstring। मुझे पता wstringहै कि यूनिकोड के पात्रों जैसे विस्तृत चरित्रों का समर्थन करता है। मुझे निम्नलिखित प्रश्न मिले हैं:

  1. जब मैं का उपयोग करना चाहिए std::wstringसे अधिक std::string?
  2. std::stringपूरे ASCII वर्ण सेट को विशेष वर्णों सहित पकड़ सकते हैं?
  3. है std::wstringसभी लोकप्रिय सी ++ compilers द्वारा समर्थित?
  4. वास्तव में एक " व्यापक चरित्र " क्या है?

10
ASCII चरक सेट में बहुत सारे "विशेष" अक्षर नहीं हैं, सबसे अधिक विदेशी शायद `(बैकक्वाटर) है। std :: string सभी यूनिकोड वर्णों का लगभग 0.025% (आमतौर पर, 8 बिट चार) पकड़ सकती है
MSalters

3
विस्तृत वर्ण और किस प्रकार का उपयोग करना है, के बारे में अच्छी जानकारी यहाँ पाई जा सकती है: programmers.stackexchange.com/questions/102205/…
Yariv

14
खैर, और चूंकि हम 2012 में हैं, utf8everywhere.org लिखा गया था। यह C ++ / Windows के साथ अधिकारों और गलतियों के बारे में सभी सवालों के बहुत जवाब देता है।
पावेल रेड्ज़विलोव्स्की

42
@MSalters: std :: string सभी यूनिकोड वर्णों का 100% हिस्सा पकड़ सकती है, भले ही CHAR_BIT 8 हो। यह std के एन्कोडिंग पर निर्भर करता है :: string, जो कि सिस्टम लेवल पर UTF-8 हो सकता है (जैसे कि विंडोज़ को छोड़कर लगभग हर जगह) ) या आपके आवेदन के स्तर पर। मूल संकीर्ण एन्कोडिंग यूनिकोड का समर्थन नहीं करता है? कोई समस्या नहीं है, बस इसका उपयोग न करें, इसके बजाय UTF-8 का उपयोग करें।
याकॉव गल्का

8
इस विषय पर महान पढ़ना: utf8everywhere.org
टिमोथी शील्ड

जवाबों:


989

string? wstring?

std::stringएक है basic_stringएक पर टेम्प्लेट की गई charहै, और std::wstringएक पर wchar_t

char बनाम wchar_t

charमाना जाता है कि यह एक चरित्र है, आमतौर पर एक 8-बिट चरित्र है।
wchar_tएक विस्तृत चरित्र रखने वाला है, और फिर, चीजें मुश्किल हो जाती हैं:
लिनक्स पर, एक wchar_t4 बाइट्स है, जबकि विंडोज पर, यह 2 बाइट्स है।

फिर यूनिकोड के बारे में क्या ?

समस्या यह है कि न तो है charऔर न ही wchar_tसीधे यूनिकोड से जुड़ा हुआ है।

लिनक्स पर?

चलो एक लिनक्स ओएस लेते हैं: मेरा उबंटू सिस्टम पहले से ही यूनिकोड जागरूक है। जब मैं चार स्ट्रिंग के साथ काम करता हूं, तो यह मूल रूप से UTF-8 (यानी यूनिकोड स्ट्रिंग ऑफ चार्ज) में इनकोड होता है । निम्नलिखित कोड:

#include <cstring>
#include <iostream>

int main(int argc, char* argv[])
{
   const char text[] = "olé" ;


   std::cout << "sizeof(char)    : " << sizeof(char) << std::endl ;
   std::cout << "text            : " << text << std::endl ;
   std::cout << "sizeof(text)    : " << sizeof(text) << std::endl ;
   std::cout << "strlen(text)    : " << strlen(text) << std::endl ;

   std::cout << "text(ordinals)  :" ;

   for(size_t i = 0, iMax = strlen(text); i < iMax; ++i)
   {
      std::cout << " " << static_cast<unsigned int>(
                              static_cast<unsigned char>(text[i])
                          );
   }

   std::cout << std::endl << std::endl ;

   // - - - 

   const wchar_t wtext[] = L"olé" ;

   std::cout << "sizeof(wchar_t) : " << sizeof(wchar_t) << std::endl ;
   //std::cout << "wtext           : " << wtext << std::endl ; <- error
   std::cout << "wtext           : UNABLE TO CONVERT NATIVELY." << std::endl ;
   std::wcout << L"wtext           : " << wtext << std::endl;

   std::cout << "sizeof(wtext)   : " << sizeof(wtext) << std::endl ;
   std::cout << "wcslen(wtext)   : " << wcslen(wtext) << std::endl ;

   std::cout << "wtext(ordinals) :" ;

   for(size_t i = 0, iMax = wcslen(wtext); i < iMax; ++i)
   {
      std::cout << " " << static_cast<unsigned int>(
                              static_cast<unsigned short>(wtext[i])
                              );
   }

   std::cout << std::endl << std::endl ;

   return 0;
}

निम्नलिखित पाठ का आउटपुट:

sizeof(char)    : 1
text            : olé
sizeof(text)    : 5
strlen(text)    : 4
text(ordinals)  : 111 108 195 169

sizeof(wchar_t) : 4
wtext           : UNABLE TO CONVERT NATIVELY.
wtext           : ol�
sizeof(wtext)   : 16
wcslen(wtext)   : 3
wtext(ordinals) : 111 108 233

आप देखेंगे कि "olé" पाठ charवास्तव में चार वर्णों द्वारा निर्मित है: 110, 108, 195 और 169 (अनुगामी शून्य की गिनती नहीं)। (मैं आपको wchar_tअभ्यास के रूप में कोड का अध्ययन करने दूंगा )

इसलिए, जब charलिनक्स पर काम करते हैं , तो आपको आमतौर पर यूनिकोड का उपयोग किए बिना इसे समाप्त करना चाहिए। और जैसा कि std::stringकाम करता है char, इसलिए std::stringपहले से ही यूनिकोड तैयार है।

ध्यान दें कि std::string, सी स्ट्रिंग एपीआई की तरह, "ओले" स्ट्रिंग पर विचार करने के लिए 4 वर्ण होंगे, तीन नहीं। इसलिए यूनिकोड वर्णों के साथ छंटनी / खेलने के दौरान आपको सतर्क रहना चाहिए क्योंकि UTF-8 में वर्णों का कुछ संयोजन निषिद्ध है।

विंडोज पर?

विंडोज पर, यह थोड़ा अलग है। Win32 को यूनिकोड के आगमन से पहले, पूरी दुनिया में उत्पादित charविभिन्न चार्जसेट / कोडपेग के साथ और बहुत से एप्लिकेशन को काम करना पड़ा ।

तो उनका समाधान एक दिलचस्प था: यदि कोई एप्लिकेशन काम करता है char, तो मशीन पर स्थानीय चारसेट / कोडपेज का उपयोग करके जीयूआई लेबल पर चार तार एन्कोडेड / प्रिंट / दिखाए जाते हैं। उदाहरण के लिए, फ्रांसीसी-स्थानीय विंडोज में "olé" "olé" होगा, लेकिन यदि आप Windows-1251 का उपयोग करते हैं तो एक सिरिलिक-स्थानीयकृत विंडोज ("ol" ) पर कुछ अलग होगा । इस प्रकार, "ऐतिहासिक एप्लिकेशन" आमतौर पर अभी भी उसी पुराने तरीके से काम करेंगे।

यूनिकोड आधारित अनुप्रयोगों के लिए, विंडोज उपयोग करता है wchar_t, जो 2-बाइट्स चौड़ा है, और UTF-16 में एन्कोडेड है , जो कि यूनिकोड 2-बाइट्स वर्णों पर एन्कोडेड है (या बहुत कम से कम, ज्यादातर संगत यूसीएस -2, जो लगभग है एक ही बात IIRC)।

का उपयोग कर आवेदन charकहा जाता है "multibyte" (क्योंकि प्रत्येक ग्लिफ़ एक या अधिक से बना है char, रों) का उपयोग करते समय अनुप्रयोगों wchar_tकहा जाता है "widechar" (क्योंकि प्रत्येक ग्लिफ़ एक या दो से बना है wchar_t। देखें MultiByteToWideChar और WideCharToMultiByte अधिक जानकारी के लिए Win32 रूपांतरण एपीआई।

इस प्रकार, यदि आप विंडोज पर काम करते हैं, तो आप बुरी तरह से उपयोग करना चाहते हैं wchar_t(जब तक कि आप किसी फ्रेमवर्क का उपयोग नहीं करते हैं, जैसे जीटीके + या क्यूटी ...)। तथ्य यह है कि पर्दे के पीछे, विंडोज wchar_tस्ट्रिंग्स के साथ काम करता है , इसलिए यहां तक ​​कि ऐतिहासिक अनुप्रयोगों charमें wchar_tएपीआई SetWindowText()( जैसे Win32 GUI पर लेबल सेट करने के लिए निम्न स्तर एपीआई फ़ंक्शन) का उपयोग करते समय उनके तार परिवर्तित हो जाएंगे ।

मेमोरी के मुद्दे?

UTF-32 प्रति वर्ण 4 बाइट्स है, इसलिए जोड़ने के लिए बहुत कुछ नहीं है, यदि केवल एक UTF-8 पाठ और UTF-16 पाठ हमेशा एक UTF-32 पाठ की तुलना में कम या समान मात्रा का उपयोग करेंगे (और आमतौर पर कम )।

यदि कोई स्मृति समस्या है, तो आपको अधिकांश पश्चिमी भाषाओं की तुलना में जानना चाहिए, UTF-8 पाठ उसी UTF-16 की तुलना में कम मेमोरी का उपयोग करेगा।

फिर भी, अन्य भाषाओं (चीनी, जापानी, आदि) के लिए, उपयोग की जाने वाली मेमोरी या तो यूटीएफ -16 की तुलना में यूटीएफ -8 के लिए या तो समान होगी, या थोड़ी बड़ी होगी।

सभी में, UTF-16 ज्यादातर वर्णों के अनुसार 2 और कभी-कभी 4 बाइट्स का उपयोग करेगा (जब तक कि आप किसी प्रकार की गूढ़ भाषा ग्लिफ़्स (क्लिंगन? एलविश?) के साथ काम नहीं कर रहे हों, जबकि UTF-8 1 से 4 बाइट्स तक खर्च करेगा।

अधिक जानकारी के लिए http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16 देखें ।

निष्कर्ष

  1. जब मुझे std :: wstring over std :: string का उपयोग करना चाहिए?

    लिनक्स पर? लगभग नहीं (§)।
    विंडोज पर? ज्यादातर हमेशा (§)।
    क्रॉस-प्लेटफ़ॉर्म कोड पर? आपके टूलकिट पर निर्भर करता है ...

    (Unless): जब तक आप टूलकिट / फ्रेमवर्क का उपयोग नहीं करते हैं अन्यथा नहीं

  2. std::stringविशेष वर्णों सहित सभी ASCII वर्ण सेट कर सकते हैं?

    सूचना: A std::string'बाइनरी' बफर रखने के लिए उपयुक्त है, जहाँ std::wstringयह नहीं है!

    लिनक्स पर? हाँ।
    विंडोज पर? Windows उपयोगकर्ता के वर्तमान स्थान के लिए केवल विशेष वर्ण उपलब्ध हैं।

    संपादित करें (से एक टिप्पणी के बाद जोहान गेरेल ):
    एक std::stringसब संभाल करने के लिए पर्याप्त हो जाएगा charआधारित तार (प्रत्येक char0 से 255 के लिए एक नंबर की जा रही है)। परंतु:

    1. ASCII को 0 से 127 में जाना है। उच्चतर charASCII नहीं हैं।
    2. एक char0 से 127 तक सही ढंग से आयोजित किया जाएगा
    3. एक char128 से 255 अपने एन्कोडिंग (यूनिकोड, गैर यूनिकोड, आदि) के आधार पर एक सार्थकता होगा, लेकिन यह के रूप में वे UTF-8 में इनकोड जब तक सभी यूनिकोड ग्लिफ़ धारण करने के लिए सक्षम हो जाएगा।
  3. है std::wstringलगभग सभी लोकप्रिय सी ++ compilers द्वारा समर्थित?

    ज्यादातर, जीसीसी आधारित संकलक के अपवाद के साथ जो विंडोज पर पोर्ट किए जाते हैं।
    यह मेरे g ++ 4.3.2 (लिनक्स के तहत) पर काम करता है, और मैंने विजुअल C ++ 6 के बाद से Win32 पर यूनिकोड एपीआई का उपयोग किया।

  4. वास्तव में एक विस्तृत चरित्र क्या है?

    C / C ++ पर, यह एक चरित्र प्रकार लिखा गया है, wchar_tजो सरल charचरित्र प्रकार से बड़ा है । इसका उपयोग उन वर्णों के अंदर करने के लिए किया जाता है जिनके सूचकांक (जैसे यूनिकोड ग्लिफ़) 255 (या 127, निर्भर ...) से बड़े होते हैं।


4
@gnud: शायद wchar_t को यूटीएफ -16 के आगमन से पहले सभी UCS-2 चार्ट्स (अधिकांश UTF-16 वर्ण) को संभालने के लिए पर्याप्त होना चाहिए था ... या शायद Microsoft के पास POSIX की तुलना में अन्य प्राथमिकताएं थीं, जैसे कि यूनिकोड को एक्सेस देना। Win32 पर चार के कोडेड उपयोग को संशोधित किए बिना।
पियरसबल

4
@ सोरिन सर्बनेया: यूटीएफ -8 1-6 बाइट ले सकता है, लेकिन जाहिर तौर पर मानक इसे 1-4 तक सीमित करता है। अधिक जानकारी के लिए en.wikipedia.org/wiki/UTF8#Description देखें ।
पियरसबल

8
हालांकि यह उदाहरण लिनक्स पर अलग-अलग परिणाम देता है और विंडोज सी ++ प्रोग्राम में कार्यान्वयन-डी behavior एनएड व्यवहार होता है जैसे कि olèयूटीएफ -8 के रूप में एन्कोड किया गया है या नहीं। इसके अलावा अधिक, कारण आप नहीं कर सकते हैं मूल रूप से स्ट्रीम wchar_t *करने के लिए std::coutहै, क्योंकि प्रकार एक बीमार का गठन कार्यक्रम में जिसके परिणामस्वरूप असंगत हैं और यह एनकोडिंग के उपयोग के साथ कोई संबंध नहीं है। यह इंगित करने के लायक है कि आप मंच के बजाय अपनी खुद की एन्कोडिंग प्राथमिकता का उपयोग करते हैं std::stringया std::wstringनिर्भर करते हैं, खासकर यदि आप चाहते हैं कि आपका कोड पोर्टेबल हो।
जॉन लेडिग्रेन

14
विंडोज वास्तव में यूटीएफ -16 का उपयोग करता है और काफी समय से है, विंडोज के पुराने संस्करणों ने यूसीएस -2 का उपयोग किया था लेकिन यह अब ऐसा नहीं है। मेरा एकमात्र मुद्दा यहां निष्कर्ष है जिसे std::wstringविंडोज पर उपयोग किया जाना चाहिए क्योंकि यह यूनिकोड विंडोज एपीआई के लिए बेहतर फिट है जो मुझे लगता है कि यह निराशाजनक है। यदि आपकी एकमात्र चिंता यूनिकोड विंडोज एपीआई में कॉल कर रही है और तार नहीं पिघल रहे हैं तो निश्चित है लेकिन मैं इसे सामान्य मामले के रूप में नहीं खरीदता हूं।
बजे जॉन लेडिग्रेन

15
@ जॉन लीडग्रेन:: If your only concern was calling into the Unicode Windows API and not marshalling strings then sureफिर, हम सहमत हैं। मैं C ++ में कोडिंग कर रहा हूं, जावास्क्रिप्ट नहीं। अनुपयोगी मार्शलिंग या किसी अन्य संभावित रूप से रनिंग के समय महंगा प्रसंस्करण से बचना जब यह संकलन के समय किया जा सकता है, उस भाषा के केंद्र में है। WinAPI के खिलाफ कोडिंग और उपयोग std::stringकरना केवल एक अनधिकृत रूप से बर्बाद हो रहे रनटाइम संसाधन है। आप इसे कमतर पाते हैं, और यह ठीक है, क्योंकि यह आपका दृष्टिकोण है। मेरा खुद का कहना है कि मैं विंडोज पर केवल निराशावाद के साथ कोड नहीं लिखूंगा क्योंकि यह लिनक्स की तरफ से बेहतर दिखता है।
पियरसेबल

71

मैं std::wstringविंडोज या कहीं और से बचने की सलाह देता हूं , सिवाय इसके जब इंटरफेस की आवश्यकता होती है, या कहीं भी विंडोज एपीआई कॉल और संबंधित चीनी के रूप में संबंधित एन्कोडिंग रूपांतरण।

मेरा विचार http://utf8everywhere.org पर संक्षेप में प्रस्तुत किया गया है , जिसमें मैं एक सह-लेखक हूं।

जब तक आपका एप्लिकेशन API- कॉल-केंद्रित नहीं है, उदाहरण के लिए मुख्य रूप से UI एप्लिकेशन, सुझाव यूनिकोड स्ट्रिंग्स को std :: string में स्टोर करना और UTF-8 में एन्कोडेड करना है, जो API कॉल के पास रूपांतरण कर रहा है। विशेष रूप से जटिल अनुप्रयोगों में रूपांतरण के स्पष्ट झुंझलाहट को रेखांकित करते हुए लेख में दिए गए लाभ। यह बहु-मंच और पुस्तकालय विकास के लिए दोगुना है।

और अब, आपके प्रश्नों का उत्तर दे रहा है:

  1. कुछ कमजोर कारण। यह ऐतिहासिक कारणों से मौजूद है, जहाँ विधवाओं को यूनिकोड का समर्थन करने का उचित तरीका माना जाता था। अब इसका उपयोग API को इंटरफ़ेस करने के लिए किया जाता है जो UTF-16 स्ट्रिंग्स को पसंद करते हैं। मैं उन्हें केवल ऐसे एपीआई कॉल के सीधे आसपास के क्षेत्र में उपयोग करता हूं।
  2. इसका std :: string से कोई लेना देना नहीं है। इसमें आप जो भी एन्कोडिंग डाल सकते हैं, उसे होल्ड कर सकते हैं। एकमात्र सवाल यह है कि आप इसकी सामग्री का इलाज कैसे करते हैं। मेरी सिफारिश UTF-8 है, इसलिए यह सभी यूनिकोड वर्णों को सही ढंग से रखने में सक्षम होगा। यह लिनक्स पर एक आम बात है, लेकिन मुझे लगता है कि विंडोज कार्यक्रमों को भी करना चाहिए।
  3. नहीं।
  4. वाइड कैरेक्टर एक भ्रामक नाम है। यूनिकोड के शुरुआती दिनों में, एक धारणा थी कि एक चरित्र को दो बाइट्स में एन्कोड किया जा सकता है, इसलिए नाम। आज, यह "चरित्र का कोई भी भाग जो दो बाइट्स लंबा है" के लिए खड़ा है। UTF-16 को ऐसे बाइट जोड़े (उर्फ वाइड अक्षरों) के अनुक्रम के रूप में देखा जाता है। UTF-16 में एक चरित्र को एक या दो जोड़े लगते हैं।

37

इसलिए, अब प्रत्येक पाठक को तथ्यों, स्थिति के बारे में स्पष्ट समझ होनी चाहिए। यदि नहीं, तो आपको पियर्सबल के लगभग व्यापक उत्तर [btw: धन्यवाद!] को अवश्य पढ़ना चाहिए

मेरा व्यावहारिक निष्कर्ष चौंकाने वाला सरल है: वह सब सी ++ (और एसटीएल) "चरित्र एन्कोडिंग" सामान काफी टूट गया है और बेकार है। इसे Microsoft पर दोष दें या नहीं, लेकिन इससे कोई मदद नहीं मिलेगी।

मेरा समाधान, गहन जांच के बाद, बहुत निराशा और परिणामी अनुभव निम्नलिखित हैं:

  1. स्वीकार करें, कि आपको एन्कोडिंग और रूपांतरण सामग्री के लिए स्वयं ही जिम्मेदार होना होगा (और आप देखेंगे कि इसमें से बहुत कुछ तुच्छ है)

  2. किसी भी UTF-8 एन्कोडेड स्ट्रिंग्स के लिए std :: string का उपयोग करें (सिर्फ a typedef std::string UTF8String)

  3. स्वीकार करें कि इस तरह के UTF8String ऑब्जेक्ट सिर्फ एक गूंगा है, लेकिन सस्ते कंटेनर है। कभी भी इसमें सीधे और / या अक्षरों में हेरफेर न करें (कोई खोज, प्रतिस्थापित, और इतने पर नहीं)। आप कर सकते हैं, लेकिन आप वास्तव में सिर्फ वास्तव में, वास्तव में मल्टी-बाइट स्ट्रिंग्स के लिए पाठ हेरफेर एल्गोरिदम लिखने में अपना समय बर्बाद नहीं करना चाहते हैं! यहां तक ​​कि अगर अन्य लोग पहले से ही ऐसी मूर्खतापूर्ण चीजें करते हैं, तो ऐसा मत करो! होने दो! (खैर, ऐसे परिदृश्य हैं जहां यह समझ में आता है ... बस उन लोगों के लिए आईसीयू पुस्तकालय का उपयोग करें)।

  4. उपयोग std :: UCS-2 एन्कोडेड स्ट्रिंग्स के लिए wstring ( typedef std::wstring UCS2String) - यह एक समझौता है, और उस गड़बड़ी के लिए एक रियायत जो WIN32 एपीआई पेश की गई है)। UCS-2 हममें से अधिकांश के लिए पर्याप्त है (उस पर बाद में ...)।

  5. UCS2String उदाहरणों का उपयोग करें जब भी चरित्र-दर-वर्ण पहुंच आवश्यक हो (पढ़ें, हेरफेर, और इसी तरह)। किसी भी चरित्र-आधारित प्रसंस्करण को गैर-बहु-प्रतिनिधित्व-प्रतिनिधित्व में किया जाना चाहिए। यह सरल, तेज, आसान है।

  6. UTF-8 और UCS-2 के बीच आगे और पीछे बदलने के लिए दो उपयोगिता कार्य जोड़ें:

    UCS2String ConvertToUCS2( const UTF8String &str );
    UTF8String ConvertToUTF8( const UCS2String &str );

रूपांतरण सीधे हैं, Google को यहां मदद करनी चाहिए ...

बस। जहाँ भी मेमोरी कीमती हो और सभी UTF-8 I / O के लिए UTF8String का उपयोग करें। UCS2String का उपयोग करें जहाँ भी स्ट्रिंग को पार्स और / या हेरफेर किया जाना चाहिए। आप किसी भी समय उन दो अभ्यावेदन के बीच परिवर्तित कर सकते हैं।

विकल्प और सुधार

  • & से एकल-बाइट चरित्र एन्कोडिंग (जैसे ISO-8859-1) const wchar_t tt_iso88951[256] = {0,1,2,...};के रूपांतरण को सादे अनुवाद तालिकाओं की मदद से महसूस किया जा सकता है, उदाहरण के लिए और UCS2 से रूपांतरण के लिए उपयुक्त कोड।

  • यदि UCS-2 पर्याप्त नहीं है, तो UCS-4 पर स्विच करने से ( typedef std::basic_string<uint32_t> UCS2String)

आईसीयू या अन्य यूनिकोड लाइब्रेरी?

उन्नत सामान के लिए।


डांग, यह जानना अच्छा नहीं है कि देशी यूनिकोड समर्थन नहीं है।
मिहाई दानिला

@Frunsi, मुझे यह जानने की उत्सुकता है कि क्या आपने Glib :: ustring की कोशिश की है और यदि ऐसा है, तो आपके विचार क्या हैं?
कैरोलीन बेल्टट्रान

@CarolineBeltran: मैं ग्लिब को जानता हूं, लेकिन मैंने इसका इस्तेमाल कभी नहीं किया, और मैं शायद कभी भी इसका इस्तेमाल नहीं करूंगा, क्योंकि यह बल्कि एक अनिर्दिष्ट लक्ष्य मंच (यूनिक्स सिस्टम ...) तक सीमित है। इसका विंडोज़ पोर्ट बाहरी win2unix- लेयर पर आधारित है, और इसमें IMHO OSX-संगतता-लेयर नहीं है। यह सब सामान एक गलत दिशा में स्पष्ट रूप से निर्देशित कर रहा है, कम से कम मेरे कोड के लिए (इस आर्च स्तर पर ...) ;-) तो, Glib एक विकल्प नहीं है
Frunsi

9
UTF-8 स्ट्रिंग्स पर खोज, बदलें, और इसी तरह से ठीक काम करता है (एक चरित्र का प्रतिनिधित्व करने वाले बाइट अनुक्रम का एक हिस्सा कभी भी दूसरे चरित्र के रूप में गलत नहीं समझा जा सकता है)। वास्तव में, UTF-16 और UTF-32 इसे बिल्कुल भी आसान नहीं बनाते हैं: तीनों एनकोडिंग व्यवहार में मल्टीबाइट एन्कोडिंग हैं, क्योंकि एक उपयोगकर्ता-कथित चरित्र (ग्रैफेम क्लस्टर) किसी भी संख्या में यूनिक कोड कोड हो सकता है! व्यावहारिक समाधान सब कुछ के लिए UTF-8 का उपयोग करना है, और केवल Windows API के साथ काम करते समय UTF-16 में कनवर्ट करना है।
डैनियल

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

25
  1. जब आप अपने स्ट्रिंग में विस्तृत वर्ण संग्रहीत करना चाहते हैं। wideकार्यान्वयन पर निर्भर करता है। यदि मैं सही तरीके से याद करूं तो दृश्य C ++ डिफॉल्ट 16 बिट तक जाता है, जबकि जीसीसी लक्ष्य के आधार पर डिफॉल्ट करता है। यहां 32 बिट लंबा है। कृपया ध्यान दें कि wchar_t (विस्तृत वर्ण प्रकार) का यूनिकोड से कोई लेना-देना नहीं है। यह केवल गारंटी है कि यह सबसे बड़े चरित्र सेट के सभी सदस्यों को संग्रहीत कर सकता है जो कार्यान्वयन अपने स्थानों से समर्थन करता है, और कम से कम जब तक चार। आप एन्कोडिंग का उपयोग करके भी यूनिकोड स्ट्रिंग्स को ठीक से स्टोर कर सकते हैं। लेकिन यह यूनिकोड कोड बिंदुओं के अर्थ को नहीं समझेगा। इसलिएstd::stringutf-8str.size()आपको अपने स्ट्रिंग में तार्किक वर्णों की मात्रा नहीं देगा, लेकिन केवल उस स्ट्रिंग / wstring में संग्रहीत चार या wchar_t तत्वों की मात्रा। इस कारण से, gtk / glib C ++ रैपर लोगों ने एक Glib::ustringवर्ग विकसित किया है जो utf-8 को संभाल सकता है।

    यदि आपका wchar_t 32 बिट लंबा है, तो आप utf-32यूनिकोड एन्कोडिंग के रूप में उपयोग कर सकते हैं , और आप फिक्स्ड (utf-32 निश्चित लंबाई) एन्कोडिंग का उपयोग करके यूनिकोड स्ट्रिंग्स को स्टोर और संभाल सकते हैं । इसका अर्थ है कि आपके wstring का s.size()फ़ंक्शन तब सही मात्रा में wchar_t तत्वों और तार्किक वर्णों को लौटाएगा ।

  2. हां, चर हमेशा कम से कम 8 बिट लंबा होता है, जिसका अर्थ है कि यह सभी ASCII मूल्यों को संग्रहीत कर सकता है।
  3. हां, सभी प्रमुख कंपाइलर इसका समर्थन करते हैं।

मैं # 2 को लेकर उत्सुक हूं। मैंने सोचा कि 7 बिट तकनीकी रूप से भी मान्य होंगे? या क्या यह कुछ 7-बिट ASCII वर्णों को संग्रहित करने में सक्षम होना चाहिए?
jalf

1
हाँ, जलफ़। c89 अपनी सीमाओं के प्रलेखन में बुनियादी प्रकारों के लिए न्यूनतम रेंज निर्दिष्ट करता है। (अहस्ताक्षरित चार के लिए, यह 0..255 मिनट है), और पूर्णांक प्रकारों के लिए एक शुद्ध बाइनरी सिस्टम है। यह चार का अनुसरण करता है, अहस्ताक्षरित चार और हस्ताक्षरित चार की न्यूनतम बिट लंबाई होती है 8. सी ++ उन नियमों को विरासत में मिला है।
जोहान्स शाउब - १२

15
"इसका मतलब है कि आपके wstring का s.size () फ़ंक्शन तब wchar_t तत्वों और तार्किक वर्णों की सही मात्रा वापस करेगा।" यह पूरी तरह से सटीक नहीं है, यहां तक ​​कि यूनिकोड के लिए भी। "तार्किक चरित्र" की तुलना में कोडपॉइंट को कहना अधिक सटीक होगा, यहां तक ​​कि UTF-32 में एक दिया गया चरित्र कई कोडपॉइंट से बना हो सकता है।
लोगान कैपल्डो

क्या आप लोग सार में कह रहे हैं कि C ++ में यूनिकोड वर्ण सेट के लिए मूल समर्थन नहीं है?
मिहाई दानिला

1
"लेकिन यह यूनिकोड कोड बिंदुओं के अर्थ को नहीं समझेगा।" खिड़कियों पर, न तो करता है std::wstring
डेडुप्लिकेटर

5

मैं अक्सर किसी भी समस्या के बिना utf-8 वर्ण रखने के लिए अक्सर std :: string का उपयोग करता हूं। मैं दिल से ऐसा करने की सलाह देता हूं जब एपीआई के साथ इंटरफेस होता है जो यूटीएफ -8 का उपयोग देशी स्ट्रिंग प्रकार के रूप में भी करता है।

उदाहरण के लिए, मैं अपने कोड को Tcl दुभाषिया के साथ इंटरफेस करते समय utf-8 का उपयोग करता हूं।

प्रमुख चेतावनी std :: string की लंबाई है, अब string में वर्णों की संख्या नहीं है।


1
जुआन: क्या आपका मतलब है कि std :: string सभी यूनिकोड वर्णों को पकड़ सकती है, लेकिन लंबाई गलत रिपोर्ट करेगी? क्या कोई कारण है कि यह गलत लंबाई की रिपोर्ट कर रहा है?

3
यूटीएफ -8 एन्कोडिंग का उपयोग करते समय, एक एकल यूनिकोड चरित्र कई बाइट्स से बना हो सकता है। यही कारण है कि मानक ascii सेट से ज्यादातर वर्णों का उपयोग करते समय utf-8 एन्कोडिंग छोटा होता है। यूनिकोड वर्णों की संख्या को मापने के लिए आपको विशेष कार्यों (या अपना स्वयं का रोल) का उपयोग करने की आवश्यकता है।

2
(Windows विशिष्ट) अधिकांश फ़ंक्शन अपेक्षा करेंगे कि बाइट्स का उपयोग करने वाला एक स्ट्रिंग ASCII है और 2 बाइट्स यूनिकोड है, पुराने संस्करण MBCS। जिसका मतलब है कि अगर आप 8 बिट यूनिकोड का भंडारण कर रहे हैं, तो आपको मानक विंडो फ़ंक्शन को कॉल करने के लिए 16 बिट यूनिकोड में बदलना होगा (जब तक कि आप केवल एएससीआईआई भाग का उपयोग नहीं कर रहे हैं)।
ग्रेग डोमजान

2
न केवल एक std :: string गलत तरीके से लंबाई की रिपोर्ट करेगा, बल्कि यह गलत स्ट्रिंग को आउटपुट भी करेगा। यदि कुछ यूनिकोड वर्ण को कई बाइट्स के रूप में UTF-8 में दर्शाया गया है, जो std :: string अपने स्वयं के वर्णों के रूप में सोचता है, तो आपका आमतौर पर std :: string हेरफेर रूट शायद कई अजीब वर्णों का उत्पादन करेगा जो किसी की गलत व्याख्या से उत्पन्न होते हैं। सही चरित्र।
मिहाई दानिला

2
मैं यह संकेत देने के लिए उत्तर बदलने का सुझाव देता हूं कि स्ट्रिंग्स को केवल बाइट्स के कंटेनरों के रूप में सोचा जाना चाहिए, और, यदि बाइट्स कुछ यूनिकोड एन्कोडिंग (UTF-8, UTF-16, ...) हैं, तो आपको विशिष्ट पुस्तकालयों का उपयोग करना चाहिए जो समझते हैं उस। मानक स्ट्रिंग-आधारित एपीआई (लंबाई, पदार्थ आदि) सभी मल्टीबीट वर्णों के साथ बुरी तरह विफल हो जाएंगे। यदि यह अद्यतन किया जाता है, तो मैं अपने डाउनवोट को हटा दूंगा।
मिहाई दानिला

4
  1. जब आप 'वाइड' (यूनिकोड) वर्णों को संग्रहीत करना चाहते हैं।
  2. हां: उनमें से 255 (0 को छोड़कर)।
  3. हाँ।
  4. यहाँ एक परिचयात्मक लेख है: http://www.joelonsoftware.com/articles/Unicode.html

11
std :: string 0 को ठीक प्रकार से पकड़ सकती है (यदि आप
c_str

3
और कड़ाई से बोल, एक बिट 8 बिट्स होने की गारंटी नहीं है। :) # 4 में आपका लिंक एक पढ़ा जाना चाहिए, लेकिन मुझे नहीं लगता कि यह सवाल का जवाब देता है। एक विस्तृत चरित्र यूनिकोड के साथ कड़ाई से नहीं है। यह बस एक व्यापक चरित्र है। (ओएस पर कितना व्यापक निर्भर करता है, लेकिन आम तौर पर 16 या 32 बिट)
जल्फ 12

2
  1. जब आप यूनिकोड स्ट्रिंग्स का उपयोग करना चाहते हैं और न ही सिर्फ एस्की, अंतर्राष्ट्रीयकरण के लिए मददगार
  2. हाँ, लेकिन यह 0 से अच्छा नहीं खेलता है
  3. नहीं है कि किसी के बारे में पता नहीं है
  4. विस्तृत चरित्र एक यूनिकोड चरित्र की निश्चित लंबाई प्रतिनिधित्व को संभालने का संकलक विशिष्ट तरीका है, MSVC के लिए यह एक 2 बाइट चरित्र है, जीसीसी के लिए मैं समझता हूं कि यह 4 बाइट्स है। और http://www.joelonsoftware.com/articles/Unicode.html के लिए एक +1

1
2. एक std :: string एक NULL वर्ण को ठीक प्रकार से पकड़ सकती है। यह utf-8 और विस्तृत वर्ण भी धारण कर सकता है।

@ जुआन: कि मुझे फिर से भ्रम में डाल दिया। यदि std :: string यूनिकोड वर्ण रख सकती है, तो std :: wstring के साथ क्या विशेष है?

1
@Appu: std :: string UTF-8 यूनिकोड वर्णों को पकड़ सकती है। विभिन्न चरित्र चौड़ाई पर लक्षित कई यूनिकोड मानक हैं। UTf8 8 बिट्स चौड़ा है। UTF-16 और UTF-32 क्रमशः 16 और 32 बिट्स चौड़े हैं
ग्रेग डी

एक std के साथ :: wstring। प्रत्येक यूनिकोड वर्ण निश्चित लंबाई एन्कोडिंग का उपयोग करते समय एक wchar_t हो सकता है। उदाहरण के लिए, यदि आप ग्रेग लिंक के रूप में सॉफ्टवेयर दृष्टिकोण पर जॉयल का उपयोग करना चुनते हैं। तब वैस्ट्रिंग की लंबाई स्ट्रिंग में यूनिकोड वर्णों की संख्या है। लेकिन यह अधिक स्थान लेता है

मैंने यह नहीं कहा कि यह एक 0 '\ 0' को पकड़ नहीं सकता है, और मेरा मतलब है कि यह अच्छी तरह से नहीं खेलता है कि कुछ तरीके आपको एक अपेक्षित परिणाम नहीं दे सकते हैं जिसमें wstring के सभी डेटा शामिल हैं। तो नीचे वोटों पर कठोर।
ग्रेग डोमजान

2

केवल 256 विभिन्न वर्णों से संतुष्ट नहीं होने वाले अनुप्रयोगों में या तो विस्तृत वर्ण (8 बिट्स से अधिक) या चर-लंबाई एन्कोडिंग (C ++ शब्दावली में एक मल्टीबैट एन्कोडिंग) जैसे UTF-8 का उपयोग होता है। व्यापक वर्णों को आम तौर पर एक चर-लंबाई एन्कोडिंग की तुलना में अधिक स्थान की आवश्यकता होती है, लेकिन प्रक्रिया के लिए तेज़ होते हैं। बहु-भाषा अनुप्रयोग जो बड़ी मात्रा में पाठ की प्रक्रिया करते हैं, आमतौर पर पाठ को संसाधित करते समय व्यापक वर्णों का उपयोग करते हैं, लेकिन इसे डिस्क पर संग्रहीत करते समय इसे UTF-8 में बदल देते हैं।

A stringऔर a के बीच का अंतर केवल wstringउनके द्वारा संग्रहित वर्णों का डेटा प्रकार है। एक स्ट्रिंग स्टोर charजिसका आकार कम से कम 8 बिट्स की गारंटी है, इसलिए आप प्रसंस्करण के लिए तार का उपयोग कर सकते हैं जैसे ASCII, ISO-8859-15, या UTF-8 टेक्स्ट। मानक वर्ण सेट या एन्कोडिंग के बारे में कुछ नहीं कहता है।

व्यावहारिक रूप से हर कंपाइलर एक कैरेक्टर सेट का उपयोग करता है जिसका पहला 128 अक्षर ASCII के साथ मेल खाता है। यह संकलक के मामले में भी है जो UTF-8 एन्कोडिंग का उपयोग करते हैं। UTF-8 या कुछ अन्य चर-लंबाई एन्कोडिंग में स्ट्रिंग्स का उपयोग करते समय जागरूक होने वाली महत्वपूर्ण बात यह है कि सूचक और लंबाई बाइट्स में मापा जाता है, वर्ण नहीं।

एक wstring का डेटा प्रकार है wchar_t, जिसका आकार मानक में परिभाषित नहीं है, सिवाय इसके कि इसे कम से कम एक चार के रूप में बड़ा होना चाहिए, आमतौर पर 16 बिट्स या 32 बिट्स। wstring को विस्तृत-वर्ण एन्कोडिंग को परिभाषित कार्यान्वयन में पाठ को संसाधित करने के लिए उपयोग किया जा सकता है। क्योंकि एन्कोडिंग मानक में परिभाषित नहीं है, यह स्ट्रिंग्स और वस्ट्रिंग के बीच कनवर्ट करने के लिए सीधा नहीं है। एक निश्चित लंबाई एन्कोडिंग के लिए या तो wstrings मान नहीं सकते हैं।

यदि आपको बहु-भाषा समर्थन की आवश्यकता नहीं है, तो आप केवल नियमित स्ट्रिंग्स का उपयोग करके ठीक हो सकते हैं। दूसरी ओर, यदि आप एक चित्रमय अनुप्रयोग लिख रहे हैं, तो अक्सर ऐसा होता है कि एपीआई केवल विस्तृत वर्णों का समर्थन करता है। तब आप संभवतः टेक्स्ट को संसाधित करते समय उसी विस्तृत वर्ण का उपयोग करना चाहते हैं। ध्यान रखें कि UTF-16 एक चर-लंबाई एन्कोडिंग है, जिसका अर्थ है कि आप length()वर्णों की संख्या वापस करने के लिए ग्रहण नहीं कर सकते हैं । यदि API UCS-2 जैसी निश्चित लंबाई वाली एन्कोडिंग का उपयोग करता है, तो प्रसंस्करण आसान हो जाता है। विस्तृत वर्णों और UTF-8 के बीच एक पोर्टेबल तरीके से करना मुश्किल है, लेकिन फिर, आपका उपयोगकर्ता इंटरफ़ेस API शायद रूपांतरण का समर्थन करता है।


इसलिए, पहले पैराग्राफ को पैराफ्रास्टिंग करते हुए: 256 से अधिक अक्षरों की आवश्यकता वाले एप्लिकेशन को मल्टीबाइट-एन्कोडिंग या एक if_multibyte- एन्कोडिंग का उपयोग करने की आवश्यकता होती है।
Deduplicator

यूसीएस -2 और यूसीएस -4 जैसे आम तौर पर 16 और 32 बिट एनकोडिंग को हालांकि मल्टीबीट एनकोडिंग नहीं कहा जाता है। C ++ मानक मल्टीबाइट एन्कोडिंग और विस्तृत वर्णों के बीच भिन्न होता है। एक विस्तृत चरित्र प्रतिनिधित्व एक निश्चित संख्या (आमतौर पर 8 से अधिक) बिट्स प्रति चरित्र का उपयोग करता है। वे एनकोडिंग जो एक बाइट का उपयोग करके सबसे आम वर्णों को एनकोड करते हैं, और मल्टीपल बाइट्स को बाकी के कैरेक्टर सेट को एनकोड करने के लिए मल्टीबीट एनकोडिंग कहा जाता है।
सेप्पो एनरवी

क्षमा करें, मैला टिप्पणी। कहा जाना चाहिए चर-लंबाई एन्कोडिंग। UTF-16 एक चर-लंबाई-एन्कोडिंग है, जैसे UTF-8। यह सही नहीं है एक बुरा विचार है।
डिडुप्लिकेटर

ये एक अच्छा बिंदु है। ऐसा कोई कारण नहीं है कि यूटीएफ -16 (यूसीएस -2 के बजाय) को स्टोर करने के लिए वेस्ट्रिंग का उपयोग नहीं किया जा सकता है, लेकिन फिर एक निश्चित लंबाई के एन्कोडिंग की सुविधा खो जाती है।
सेप्पो एनारवी

2

एक अच्छा सवाल! मुझे लगता है कि डेटा एनकाउंटर (कभी-कभी एक चार्ट भी शामिल) एक फ़ाइल के लिए डेटा को बचाने या किसी नेटवर्क के माध्यम से डेटा ट्रांसफर करने के लिए एक मेमोरी जांच है , इसलिए मैं इस प्रश्न का उत्तर देता हूं:

1. मुझे std का उपयोग कब करना चाहिए: wdring over std :: string?

यदि प्रोग्रामिंग प्लेटफ़ॉर्म या एपीआई फ़ंक्शन एक सिंगल-बाइट है, और हम कुछ यूनिकोड डेटा को प्रोसेस या पार्स करना चाहते हैं, जैसे कि विंडोज'आरजी फ़ाइल या नेटवर्क 2-बाइट स्ट्रीम से पढ़ा जाता है, तो हमें आसानी से std :: wstable वैरिएबल घोषित करना चाहिए उन्हें प्रोसेस करें। उदाहरण: wstring ws = L "w" (6 ओकटेट मेमोरी: 0x4E2D 0x56FD 0x0061), हम वर्ण '中' प्राप्त करने के लिए ws [0] का उपयोग कर सकते हैं और ws [1] को चरित्र 'get' और ws [2] प्राप्त कर सकते हैं। चरित्र 'ए' प्राप्त करें, आदि।

2. std :: string पूरे ASCII कैरेक्टर सेट को पकड़ सकती है, जिसमें स्पेशल कैरेक्टर शामिल हैं?

हाँ। लेकिन ध्यान दें: अमेरिकी ASCII, का अर्थ है प्रत्येक 0x00 ~ 0xFF ऑक्टेट एक वर्ण के लिए है, जिसमें मुद्रण योग्य पाठ जैसे "123abc & * _ &" शामिल है और आपने विशेष रूप से कहा है, ज्यादातर इसे 'के रूप में प्रिंट करें।' भ्रामक संपादकों या टर्मिनलों से बचें। और कुछ अन्य देश अपने स्वयं के "ASCII" चारसेट का विस्तार करते हैं, जैसे चीनी, एक चरित्र के लिए खड़े होने के लिए 2 ओकटेट्स का उपयोग करते हैं।

3.Is std :: wstring सभी लोकप्रिय C ++ कंपाइलर द्वारा समर्थित है?

हो सकता है, या ज्यादातर। मैंने उपयोग किया है: VC ++ 6 और GCC 3.3, YES

4. वास्तव में एक "विस्तृत चरित्र" क्या है?

एक विस्तृत चरित्र ज्यादातर सभी देशों के पात्रों को धारण करने के लिए 2 ऑक्टेट या 4 ऑक्टेट का उपयोग करने का संकेत देता है। 2 ऑक्टेट UCS2 एक प्रतिनिधि नमूना है, और आगे अंग्रेजी 'ए', इसकी मेमोरी 0x0061 के 2 ऑक्टेट है (बनाम एएससीआईआई की मेमोरी में 1 ऑक्टेट 0x61 है)


0

यहाँ कुछ बहुत अच्छे जवाब हैं, लेकिन मुझे लगता है कि कुछ चीजें हैं जो मैं विंडोज / विज़ुअल स्टूडियो के बारे में जोड़ सकता हूं। Tis VS2015 के साथ मेरे अनुभव पर आधारित है। लिनक्स पर, मूल रूप से इसका उत्तर UTF-8 का उपयोग std::stringहर जगह एन्कोडेड है। विंडोज / वीएस पर यह अधिक जटिल हो जाता है। यहाँ क्यों है। विंडोज को उम्मीद है charकि लोकल कोडपेज का उपयोग करके इन स्ट्रिंग को संग्रहीत किया जा सकता है। यह लगभग हमेशा ASCII वर्ण सेट है जिसके बाद आपके स्थान के आधार पर 128 अन्य विशेष वर्ण होते हैं। मुझे केवल यह बताएं कि यह विंडोज एपीआई का उपयोग करते समय नहीं, तीन अन्य प्रमुख स्थान हैं जहां ये तार मानक सी ++ के साथ बातचीत करते हैं। ये स्ट्रिंग शाब्दिक हैं, एक फ़ाइलनाम std::coutका उपयोग <<और पारित करने के लिए आउटपुट std::fstream

मैं यहां सामने रहूंगा कि मैं एक प्रोग्रामर हूं, भाषा विशेषज्ञ नहीं। मैं सराहना करता हूं कि USC2 और UTF-16 समान नहीं हैं, लेकिन मेरे उद्देश्यों के लिए वे विनिमेय होने के काफी करीब हैं और मैं उनका उपयोग यहां करता हूं। मुझे वास्तव में यकीन नहीं है कि विंडोज कौन सा उपयोग करता है, लेकिन मुझे आमतौर पर या तो जानने की आवश्यकता नहीं है। मैंने इस उत्तर में यूसीएस 2 कहा है, इसलिए यदि मैं इस मामले में अपनी अज्ञानता से किसी को भी परेशान करता हूं, तो मुझे अग्रिम रूप से खेद है और अगर मेरे पास गलत चीजें हैं तो मैं इसे बदलकर खुश हूं।

स्ट्रिंग शाब्दिक

यदि आप ऐसे स्ट्रिंग शाब्दिक दर्ज करते हैं जिनमें केवल ऐसे वर्ण होते हैं जिन्हें आपके कोडपेज द्वारा दर्शाया जा सकता है, तो वीएस आपकी फ़ाइल में आपके कोडपेज के आधार पर 1 बाइट प्रति वर्ण एन्कोडिंग के साथ संग्रहीत करता है। ध्यान दें कि यदि आप अपना कोडपेज बदलते हैं या किसी भिन्न कोड पेज का उपयोग करके किसी अन्य डेवलपर को अपना स्रोत देते हैं तो मुझे लगता है कि (लेकिन परीक्षण नहीं किया गया है) कि चरित्र अलग हो जाएगा। यदि आप एक अलग कोड पेज का उपयोग करके कंप्यूटर पर अपना कोड चलाते हैं तो मुझे यकीन नहीं है कि चरित्र भी बदल जाएगा।

यदि आप किसी ऐसे स्ट्रिंग शाब्दिक को दर्ज करते हैं जिसे आपके कोडपेज द्वारा प्रस्तुत नहीं किया जा सकता है तो वीएस आपसे फाइल को यूनिकोड के रूप में सहेजने के लिए कहेगा। फ़ाइल को तब UTF-8 के रूप में एन्कोड किया जाएगा। इसका मतलब है कि सभी गैर ASCII वर्ण (जो आपके कोडपेज पर हैं) को 2 या अधिक बाइट्स द्वारा दर्शाया जाएगा। इसका मतलब है कि अगर आप अपने स्रोत को किसी और को देते हैं तो स्रोत समान दिखाई देगा। हालांकि, संकलक को स्रोत पास करने से पहले, वीएस यूटीएफ -8 एन्कोडेड टेक्स्ट को कोड पेज एन्कोडेड टेक्स्ट में कनवर्ट करता है और कोड पेज से गायब किसी भी अक्षर को बदल दिया जाता है ?

वीएस में एक यूनिकोड स्ट्रिंग शाब्दिक का सही ढंग से प्रतिनिधित्व करने की गारंटी देने का एकमात्र तरीका Lयह है कि यह एक स्ट्रिंग स्ट्रिंग शाब्दिक बनाने के साथ स्ट्रिंग शाब्दिक से पहले है । इस मामले में VS फाइल में से UTF-8 एनकोडेड टेक्स्ट को UCS2 में बदल देगा। फिर आपको इस स्ट्रिंग शाब्दिक को एक std::wstringकंस्ट्रक्टर में पारित करने की आवश्यकता है या आपको इसे utf-8 में बदलने और इसे एक में डालने की आवश्यकता है std::string। या यदि आप चाहते हैं कि आप Windows API फ़ंक्शन का उपयोग करके इसे डालने के लिए अपने कोड पृष्ठ का उपयोग कर इसे एन्कोड कर सकते हैं std::string, लेकिन तब आपने व्यापक स्ट्रिंग शाब्दिक का उपयोग नहीं किया होगा।

std :: अदालत

जब <<आप उपयोग करते हुए कंसोल पर आउटपुट केवल उपयोग कर सकते हैं std::string, तो नहीं std::wstringऔर पाठ को आपके स्थानीय कोडपेज का उपयोग करके एन्कोड किया जाना चाहिए। यदि आपके पास एक है std::wstringतो आपको इसे विंडोज एपीआई कार्यों में से एक का उपयोग करके परिवर्तित करना होगा और आपके कोडपेज पर मौजूद किसी भी वर्ण को प्रतिस्थापित नहीं किया जाएगा ?(हो सकता है कि आप चरित्र को बदल सकें, मुझे याद नहीं है)।

एसटीडी :: फिलास्टल फाइलनाम

Windows OS अपने फ़ाइल नाम के लिए UCS2 / UTF-16 का उपयोग करता है ताकि आपका कोडपेज जो भी हो, आप किसी भी यूनिकोड वर्ण के साथ फाइल कर सकते हैं। लेकिन इसका मतलब यह है कि आपके कोडपेज पर उन वर्णों के साथ फ़ाइलों को एक्सेस करने या बनाने के लिए जो आपके उपयोग नहीं किए जाने चाहिए std::wstring। और कोई रास्ता नहीं है। यह एक Microsoft विशिष्ट विस्तार है, std::fstreamइसलिए संभवतः अन्य प्रणालियों पर संकलित नहीं किया जाएगा। यदि आप std :: string का उपयोग करते हैं तो आप केवल उन फ़ाइलनामों का उपयोग कर सकते हैं जिनमें केवल आपके कोडपेज पर वर्ण शामिल हैं।

आपके विकल्प

यदि आप अभी लिनक्स पर काम कर रहे हैं, तो संभवतः आपको यह दूर नहीं मिला। बस std::stringहर जगह UTF-8 का उपयोग करें ।

यदि आप विंडोज पर काम कर रहे हैं तो बस std::wstringहर जगह UCS2 का उपयोग करें । कुछ शुद्धतावादी कह सकते हैं कि यूटीएफ 8 का इस्तेमाल तब करें, जब जरूरत हो, तब कन्वर्ट करें, लेकिन परेशानी से परेशान क्यों हों।

यदि आप क्रॉस प्लेटफॉर्म हैं तो यह फ्रैंक होने की गड़बड़ है। यदि आप विंडोज़ पर हर जगह UTF-8 का उपयोग करने का प्रयास करते हैं तो आपको अपने स्ट्रिंग शाब्दिक और कंसोल के आउटपुट के साथ वास्तव में सावधान रहने की आवश्यकता है। आप वहां आसानी से अपने तार भ्रष्ट कर सकते हैं। यदि आप std::wstringलिनक्स पर हर जगह उपयोग करते हैं std::fstream, तो आपके पास व्यापक संस्करण तक पहुंच नहीं हो सकती है , इसलिए आपको रूपांतरण करना होगा, लेकिन भ्रष्टाचार का कोई जोखिम नहीं है। इसलिए व्यक्तिगत रूप से मुझे लगता है कि यह एक बेहतर विकल्प है। कई असहमत होंगे, लेकिन मैं अकेला नहीं हूँ - यह उदाहरण के लिए wxWidgets द्वारा लिया गया रास्ता है।

एक अन्य विकल्प लिनक्स पर और विंडोज पर टाइप unicodestringकिया जा सकता है , और एक मैक्रो है जिसे UNI कहा जाता है () जो विंडोज पर एल उपसर्ग करता है और लिनक्स पर कुछ भी नहीं है, फिर कोडstd::stringstd::wstring

#include <fstream>
#include <string>
#include <iostream>
#include <Windows.h>

#ifdef _WIN32
typedef std::wstring unicodestring;
#define UNI(text) L ## text
std::string formatForConsole(const unicodestring &str)
{
    std::string result;
    //Call WideCharToMultiByte to do the conversion
    return result;
}
#else
typedef std::string unicodestring;
#define UNI(text) text
std::string formatForConsole(const unicodestring &str)
{
    return str;
}
#endif

int main()
{

    unicodestring fileName(UNI("fileName"));
    std::ofstream fout;
    fout.open(fileName);
    std::cout << formatForConsole(fileName) << std::endl;
    return 0;
}

मुझे लगता है कि किसी भी मंच पर ठीक होगा।

जवाब

तो आपके सवालों का जवाब देने के लिए

1) यदि आप विंडोज के लिए प्रोग्रामिंग कर रहे हैं, तो हर समय, यदि प्लेटफॉर्म पार करता है, तो शायद हर समय, जब तक कि आप विंडोज पर संभावित भ्रष्टाचार के मुद्दों से निपटना नहीं चाहते हैं या #ifdefsमतभेदों के चारों ओर काम करने के लिए प्लेटफॉर्म के साथ कुछ कोड लिख सकते हैं , यदि बस उपयोग कर रहे हैं लिनक्स तो कभी नहीं।

2) जी हां। लिनक्स पर इसके अलावा आप इसे सभी यूनिकोड के लिए भी उपयोग कर सकते हैं। विंडोज़ पर आप इसे केवल सभी यूनिकोड के लिए उपयोग कर सकते हैं यदि आप मैन्युअल रूप से यूटीएफ -8 का उपयोग कर चुनते हैं। लेकिन विंडोज एपीआई और मानक सी ++ कक्षाएं std::stringस्थानीय कोडपेज का उपयोग करके एन्कोडेड होने की उम्मीद करेंगी । इसमें सभी ASCII प्लस और अन्य 128 वर्ण शामिल हैं जो आपके कंप्यूटर के उपयोग के लिए सेटअप किए गए कोडपेज के आधार पर बदलते हैं।

3) मेरा ऐसा मानना ​​है, लेकिन यदि ऐसा नहीं है, तो इसके wchar_tबजाय 'std :: basic_string' का उपयोग करना केवल एक साधारण टाइपफ़ीड हैchar

4) एक विस्तृत चरित्र एक चरित्र प्रकार है जो 1 बाइट मानक charप्रकार से बड़ा है । विंडोज पर यह 2 बाइट्स है, लिनक्स पर यह 4 बाइट्स है।


1
"हालांकि, संकलक को स्रोत पारित करने से पहले, वीएस यूटीएफ -8 एनकोडेड टेक्स्ट को कोड पेज एन्कोडेड टेक्स्ट में कनवर्ट करता है और कोड पेज से गायब किसी भी वर्ण के साथ बदल दिया जाता है?" -> मुझे नहीं लगता कि यह सच है जब संकलक UTF-8 एन्कोडिंग (उपयोग /utf-8) का उपयोग करता है ।
रूई दंतों

मुझे इसके विकल्प के रूप में जानकारी नहीं थी। इस लिंक से docs.microsoft.com/en-us/cpp/build/reference/… ऐसा लगता है कि प्रोजेक्ट गुणों में चयन करने के लिए कोई टिक बॉक्स नहीं है, आपको इसे अतिरिक्त कमांड लाइन विकल्प के रूप में जोड़ना होगा। अच्छी जगह!
फिल रोसेनबर्ग

-2

1) जैसा कि ग्रेग द्वारा उल्लेख किया गया है, wstring अंतर्राष्ट्रीयकरण के लिए सहायक है, कि जब आप अंग्रेजी के अलावा अन्य भाषाओं में अपना उत्पाद जारी करेंगे

4) विस्तृत चरित्र http://en.wikipedia.org/wiki/Wide_character के लिए इसे देखें


-6

आपको विस्तृत वर्णों का उपयोग कब नहीं करना चाहिए?

जब आप वर्ष 1990 से पहले का कोड लिख रहे हों।

जाहिर है, मैं फ्लिप कर रहा हूं, लेकिन वास्तव में, यह अब 21 वीं सदी है। 127 वर्ण लंबे समय से पर्याप्त हैं। हां, आप यूटीएफ 8 का उपयोग कर सकते हैं, लेकिन सिरदर्द से परेशान क्यों हैं?


16
@ अवतल: मुझे नहीं पता कि UTF-8 सिरदर्द क्या बनाता है जो कि विडचर्स (UTF-16) से अधिक है। UTF-16 में, आपके पास मल्टी-कैरेक्टर कैरेक्टर भी हैं।
पावेल रेड्ज़विलोव्स्की 16

समस्या यह है कि यदि आप कहीं भी हैं, लेकिन अंग्रेजी बोलने वाला देश आप wchar_t का उपयोग करने के लिए OUGHT करते हैं। यह बताने के लिए नहीं कि कुछ वर्णमालाओं में एक बाइट में फिट होने की तुलना में अधिक वर्ण हैं। हम वहां थे, डॉस पर। कोडपेज सिज़ोफ्रेनिया, नो, थैंक्स, नो मोर ..
स्विफ्ट - फ्राइडे पाई

1
@ स्विफ्ट के साथ समस्या wchar_tयह है कि इसका आकार और अर्थ ओएस-विशिष्ट हैं। यह बस पुरानी समस्याओं को नए के साथ स्वैप करता है। जबकि ओएस (समान प्लेटफार्मों पर, कम से कम) की परवाह किए बिना एक charहै char। इसलिए हम केवल यूटीएफ -8 का उपयोग कर सकते हैं, सब कुछ charएस के दृश्यों में पैक कर सकते हैं , और विलाप कर सकते हैं कि ऐसे दृश्यों के भीतर मापने, अनुक्रमित करने, खोजने आदि के लिए सी ++ हमें बिना किसी मानक तरीकों के पूरी तरह से कैसे छोड़ देता है।
अंडरस्कोर_ड

1
@Swift आपको लगता है कि यह पूरी तरह से पीछे की ओर है। wchar_tएक निश्चित-चौड़ाई वाला डेटा प्रकार है, इसलिए 10 की एक सरणी wchar_tहमेशा sizeof(wchar_t) * 10प्लेटफ़ॉर्म बाइट्स पर कब्जा करेगी । और UTF-16 एक चर-चौड़ाई वाली एन्कोडिंग है जिसमें वर्ण 1 या 2 16-बिट कोडपॉइंट (और UTF-8 के लिए s / 16/8 / g) हो सकते हैं।
अंडरस्कोर_ड

1
@SteveHollasch wchar_t खिड़कियों पर स्ट्रिंग का प्रतिनिधित्व एफएफएफ से अधिक वर्णों को विशिष्ट सरोगेट जोड़ी के रूप में सांकेतिक शब्दों में बदलना होगा, अन्य केवल एक wchar_t तत्व ले जाएगा। ताकि प्रतिनिधित्व गन्न संकलक द्वारा बनाए गए प्रतिनिधित्व के साथ संगत नहीं होगा (जहां एफएफएफएफ से कम सभी वर्ण उनके सामने शून्य शब्द होंगे)। Wchar_t में संग्रहीत क्या प्रोग्रामर और कंपाइलर द्वारा निर्धारित किया जाता है, कुछ समझौते से नहीं
स्विफ्ट - शुक्रवार पाई
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.