2009-09-30 19 views
11

मुझे पता है कि वहाँ utf-8 के बारे में विभिन्न सवाल किया गया कर रहे हैं, मुख्य रूप से पुस्तकालयों वस्तुओं की तरह utf-8 'स्ट्रिंग' में हेरफेर करने के बारे में हूँ।UTF-8 C++: त्वरित और गंदा चाल

हालांकि, मैं एक 'अंतर्राष्ट्रीयकृत' परियोजना (एक वेबसाइट, जिसमें मैं एक सी ++ बैकएंड कोड करता हूं ... पूछता हूं) पर काम कर रहा हूं, यहां तक ​​कि अगर हम utf-8 से निपटते हैं तो हमें भी इस तरह की आवश्यकता नहीं है पुस्तकालयों। अधिकांश बार सादे std :: स्ट्रिंग विधियों या एसटीएल एल्गोरिदम हमारी आवश्यकताओं के लिए बहुत ही पर्याप्त हैं, और वास्तव में यह पहली जगह utf-8 का उपयोग करने का लक्ष्य है।

तो, क्या मैं यहाँ रहा हूँ "त्वरित & गंदा" चाल की एक पूंजीकरण कि आप utf-8 std :: स्ट्रिंग (कोई स्थिरांक चार * के रूप में जमा करने के लिए संबंधित के बारे में पता है, मुझे नहीं पता वास्तव में सी-स्टाइल कोड की परवाह है, मेरे बफर आकार के बारे में लगातार चिंता करने से मुझे बेहतर चीजें मिलती हैं)।

उदाहरण के लिए, यहाँ एक "त्वरित & गंदा" वर्णों की संख्या प्राप्त करने के लिए (जो उपयोगी है अगर यह अपने प्रदर्शन बॉक्स में फिट होगा पता करने के लिए) चाल है:

#include <string> 
#include <algorithm> 

// Let's remember than in utf-8 encoding, a character may be 
// 1 byte: '0.......' 
// 2 bytes: '110.....' '10......' 
// 3 bytes: '1110....' '10......' '10......' 
// 4 bytes: '11110...' '10......' '10......' '10......' 
// Therefore '10......' is not the beginning of a character ;) 

const unsigned char mask = 0xC0; 
const unsigned char notUtf8Begin = 0x80; 

struct Utf8Begin 
{ 
    bool operator(char c) const { return (c & mask) != notUtf8Begin; } 
}; 

// Let's count 
size_t countUtf8Characters(const std::string& s) 
{ 
    return std::count_if(s.begin(), s.end(), Utf8Begin()); 
} 

वास्तव में मैं

  • छँटाई काम करता है के रूप में उम्मीद
  • : जब मैं वर्णों की संख्या और उस std :: स्ट्रिंग या एसटीएल एल्गोरिथम की तुलना में कुछ और की जरूरत है मुफ्त के बाद से के लिए प्रस्ताव नहीं होगा एक USECASE सामना करने के लिए अभी तक
  • एक शब्द का कोई हिस्सा किसी शब्द या एक और शब्द के हिस्से के रूप में भ्रमित किया जा सकता है

मैं, पता करने के लिए यदि आप अन्य तुलनीय चाल है चाहते हैं दोनों की गिनती के लिए और अन्य साधारण कार्यों के लिए।
मैं फिर कहता हूँ, मैं के बारे में ICU और Utf8-CPP पता है, लेकिन मैं उन्हें में रुचि के बाद से मैं एक पूर्ण उपचार की जरूरत नहीं है नहीं कर रहा हूँ (और वास्तव में मैं पात्रों में से गिनती की तुलना में अधिक की जरूरत कभी नहीं किया है)।
मैं भी दोहराने है कि मैं के उपचार में कोई दिलचस्पी नहीं है चार * की, वे पुराने ढंग का है।

+9

तो diacritics संयोजन आपके लिए कोई फर्क नहीं पड़ता? यह दुख की बात है। वे आपकी गिनती के पात्र हो सकते हैं लेकिन वे अधिक जगह नहीं लेते हैं। वास्तव में कोई संयोजन चरित्र। या शून्य चौड़ाई रिक्त स्थान। और उम्मीद के अनुसार काम छंटनी? आप क्या उम्मीद करते हैं? जब आप जानबूझकर यूनिकोड (कुछ प्रकार के बाइट सरणी को छोड़कर) का उपयोग नहीं करेंगे तो किसी भी लोकेल-विशिष्ट प्रकार को संयोजन के बारे में पता होगा। – Joey

+0

मेरा संपादन देखें, मेरा आवेदन किसी वेबसाइट के लिए बैकएंड है, इसलिए लोकेल ब्राउज़र के हाथ में है। हमने अभी तक संयोजन पात्रों की समस्या का सामना नहीं किया है, मैंने उनके बारे में सुना है लेकिन उन्हें कभी नहीं देखा है, आप किस भाषा में उन्हें सामना करते हैं? –

+0

गैर-अंग्रेज़ी पाठ के लिए काम नहीं करने वाले उपयोग मामलों के युगल: सॉर्टिंग, केस फोल्डिंग, मिलान (उदाहरण के लिए जर्मन ß और एसएस)। –

उत्तर

5

खैर यह गंदा चाल काम नहीं करेगा। सबसे पहले, क्या इस के बाद मुखौटा का मान:

const unsigned char mask = 0x11000000; 
    const unsigned char notUtf8Begin = 0x10000000; 

द्विआधारी साथ शायद आप मिश्रण कर रहे हैं हेक्स प्रतिनिधित्व।

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

एक चक्र को लागू करना मुश्किल नहीं होगा जो गणना और आगे बढ़कर अग्रणी बाइट्स के लिए सरल मास्क तालिका का उपयोग कर कूदता है।

अंत में आप वर्णों की जाँच के लिए एक ही हे (एन) हो जाते हैं और यह हर UTF8 स्ट्रिंग के साथ काम करेंगे।

+0

हां, मेरे मास्क मिश्रित हो गए, क्षमा करें। हालांकि count_if संयोजन diacritics समस्या से अलग अभी भी सही है। –

+0

मैं एक utf8 स्ट्रिंग क्लास पर काम कर रहा था जहां ++ विस्तृत कोड बिंदुओं पर सही ढंग से चलेंगे और बाइट से बाइट तक कूदने के लिए ऑफ़सेट की सरणी पर छोड़ दिया जाएगा। यह आगे बढ़ने के लिए बहुत अच्छा काम करता है लेकिन इसके लिए - यह कोई लाभ नहीं देता है। पैडेंटिक कोड को बनाए रखना आसान है। – jmucchiello

1

बाइनरी के रूप में UTF_8 को सॉर्ट करना 'यूनिकोड' क्रम में क्रमबद्ध नहीं होगा। बीओसीयू -1 होगा। जैसा कि कहा गया था, आपकी "अपेक्षित" गैर-अंग्रेजी सामग्री के लिए एक बहुत कम बार है।

0

हम इसे OpenLieroX में भी संभालते हैं (जो कि मुझे लगता है कि वास्तव में एक गेम में ठीक है)।

हमारे पास ऐसे यूटीएफ -8 std :: तारों के लिए उपयोगी कार्यों/एल्गोरिदम का एक गुच्छा है। Unicode.h और Unicode.cpp देखें। उदाहरण के लिए, यूटीएफ 8 इटरेटर्स हैं, कुछ सरल हेरफेर ऑपरेटर (डालें या मिटाएं), ऊपरी/निचले केस रूपांतरण, केस स्वतंत्र खोज, आदि

लेकिन उन कार्यों को हमेशा सही होने की अपेक्षा न करें। उदाहरण के लिए, वे वास्तव में डायक्रिटिक्स या एक ही पाठ को एन्कोड करने के संभावित तरीकों के संयोजन के बारे में नहीं जानते हैं।

संबंधित मुद्दे