tl; डॉ
ICU लाइब्रेरी का उपयोग करें । यदि आप ऐसा नहीं करते हैं, तो आपका रूपांतरण रूटीन उन मामलों पर चुपचाप टूट जाएगा, जिनके बारे में आप शायद जानते भी नहीं हैं।
क्या है: सबसे पहले आप एक सवाल का जवाब देने के लिए है एन्कोडिंग अपने की std::string
? क्या यह ISO-8859-1 है? या शायद ISO-8859-8? या विंडोज कोडपेज 1252? क्या जो भी आप ऊपरी-से-निचले हिस्से में बदलने के लिए उपयोग कर रहे हैं, वह जानते हैं? (या यह पात्रों के लिए बुरी तरह से विफल रहता है 0x7f
?)
यदि आप std::string
कंटेनर के रूप में UTF-8 (8-बिट एन्कोडिंग के बीच एकमात्र समझदार विकल्प) का उपयोग कर रहे हैं, तो आप पहले से ही अपने आप को विश्वास में धोखा दे रहे हैं कि आप अभी भी चीजों के नियंत्रण में हैं, क्योंकि आप एक कंटेनर में मल्टीबायट सीक्वेंस स्टोर कर रहे हैं यह मल्टीबाइट अवधारणा के बारे में पता नहीं है। यहां तक कि कुछ के रूप में सरल .substr()
एक टिक टाइमबॉम्ब है। (क्योंकि मल्टीबाइट अनुक्रम को विभाजित करने से अमान्य (उप-) स्ट्रिंग हो जाएगा।)
और जैसे ही आप किसी तरह की कोशिश करते हैं std::toupper( 'ß' )
, किसी भी एन्कोडिंग में, आप गहरी मुसीबत में हैं। (क्योंकि मानक पुस्तकालय के साथ यह "सही" करना संभव नहीं है, जो केवल एक परिणाम चरित्र प्रदान कर सकता है , "SS"
यहां आवश्यक नहीं है।) [1] एक और उदाहरण होगा std::tolower( 'I' )
, जिसमें स्थानीय आधार पर अलग-अलग परिणाम प्राप्त होने चाहिए । जर्मनी में, 'i'
सही होगा; तुर्की में, 'ı'
(LATIN SMALL LETTER DOTLESS I) अपेक्षित परिणाम है (जो, फिर से, UTF-8 एन्कोडिंग में एक से अधिक बाइट है)। फिर भी एक और उदाहरण ग्रीक सिग्मा , अपरकेस '∑'
, लोअरकेस 'σ'
... एक शब्द के अंत को छोड़कर, जहां यह है 'ς'
।
इसलिए, कोई भी केस रूपांतरण जो एक समय में एक चरित्र पर काम करता है, या इससे भी बदतर, एक बार में एक बाइट , डिजाइन द्वारा टूट जाता है।
फिर यह बिंदु है कि मानक पुस्तकालय, जो यह करने में सक्षम है, उसके आधार पर यह पता लगाया जाता है कि आपके सॉफ्टवेयर पर चलने वाली मशीन पर कौन से स्थान समर्थित हैं ... और यदि यह नहीं है तो आप क्या करते हैं?
तो क्या आप कर रहे हैं वास्तव में की तलाश में एक स्ट्रिंग वर्ग है कि सभी इस के साथ सही ढंग से निपटने में सक्षम है, और वह यह है कि नहीं के किसी भी std::basic_string<>
संस्करण ।
(सी ++ 11 ध्यान दें: std::u16string
और std::u32string
कर रहे हैं बेहतर ।, लेकिन अभी भी सही नहीं सी ++ 20 लाया std::u8string
है, लेकिन इन सब करते एन्कोडिंग निर्दिष्ट है कई अन्य मामलों में वे अभी भी यूनिकोड यांत्रिकी से अनभिज्ञ रहते हैं, सामान्य, मिलान की तरह, ..। ।)
जबकि बूस्ट अच्छा लग रहा है , एपीआई बुद्धिमान, बूस्ट.लोकेल मूल रूप से आईसीयू के आसपास एक आवरण है । अगर बूस्ट को ICU सपोर्ट के साथ संकलित किया जाता है ... यदि यह नहीं है, तो Boost.Locale मानक लाइब्रेरी के लिए संकलित लोकेल सपोर्ट तक सीमित है।
और मेरा विश्वास करो, आईसीयू के साथ संकलन करने के लिए बूस्ट प्राप्त करना कभी-कभी एक वास्तविक दर्द हो सकता है। (विंडोज के लिए कोई पूर्व-संकलित बायनेरिज़ नहीं हैं, इसलिए आपको उन्हें अपने आवेदन के साथ एक साथ आपूर्ति करना होगा, और इससे कीड़े की एक पूरी नई परत खुलती है ...)
इसलिए व्यक्तिगत रूप से मैं घोड़े के मुंह से सीधे यूनिकोड समर्थन प्राप्त करने और सीधे आईसीयू पुस्तकालय का उपयोग करने की सलाह दूंगा :
#include <unicode/unistr.h>
#include <unicode/ustream.h>
#include <unicode/locid.h>
#include <iostream>
int main()
{
/* "Odysseus" */
char const * someString = u8"ΟΔΥΣΣΕΥΣ";
icu::UnicodeString someUString( someString, "UTF-8" );
// Setting the locale explicitly here for completeness.
// Usually you would use the user-specified system locale,
// which *does* make a difference (see ı vs. i above).
std::cout << someUString.toLower( "el_GR" ) << "\n";
std::cout << someUString.toUpper( "el_GR" ) << "\n";
return 0;
}
संकलन (इस उदाहरण में G ++ के साथ):
g++ -Wall example.cpp -licuuc -licuio
यह देता है:
ὀδυσσεύς
ध्यान दें कि शब्द के मध्य में that <-> Σ रूपांतरण, और शब्द के अंत में Σ <-> Σ रूपांतरण। कोई भी <algorithm>
समाधान आपको दे सकता है।
[१] २०१, में, जर्मन ऑर्थोग्राफी के लिए परिषद ने फैसला किया कि "+" U + 1E9E लेटिन कैपिटल लेटर शाफ़्ट एस को आधिकारिक रूप से इस्तेमाल किया जा सकता है, पासपोर्ट में अस्पष्ट "बचने" के लिए पारंपरिक "एसएस" रूपांतरण के बगल में एक विकल्प के रूप में (जहां नाम पूंजीकृत हैं) )। मेरा सुंदर उदाहरण, समिति के निर्णय से अप्रचलित ...