2008-10-08 20 views
7

के लिए केस-असंवेदनशील यूटीएफ -8 स्ट्रिंग कॉलेशन मैं custom collation function in SQLite में इसका उपयोग करने के लिए केस-असंवेदनशील तरीके से सी ++ में यूटीएफ -8 स्ट्रिंग्स की तुलना और सॉर्ट करने की विधि ढूंढ रहा हूं।SQLite (सी/सी ++)

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

क्या मैं अब तक है:

  1. strcoll सी स्थानों के साथ और std::collate/std::collate_byname केस-संवेदी होते। (वहाँ इनमें से केस-संवेदी संस्करणों हैं?)
  2. मैं एक POSIX strcasecmp का उपयोग करने की कोशिश की है, लेकिन यह "POSIX"

    POSIX स्थान में, strcasecmp के अलावा अन्य स्थानों के लिए not defined हो रहा है() और strncasecmp() ऊपरी रूपांतरणों के ऊपरी भाग में, फिर एक बाइट तुलना करें। परिणाम अन्य लोकेशंस में निर्दिष्ट नहीं हैं।

    और, वास्तव में, strcasecmp का परिणाम glibc साथ लिनक्स पर स्थानों के बीच नहीं बदलता है।

    #include <clocale> 
    #include <cstdio> 
    #include <cassert> 
    #include <cstring> 
    
    const static char *s1 = "Äaa"; 
    const static char *s2 = "äaa"; 
    
    int main() { 
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); 
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); 
        assert(setlocale(LC_ALL, "en_AU.UTF-8")); 
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); 
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); 
        assert(setlocale(LC_ALL, "fi_FI.UTF-8")); 
        printf("strcasecmp('%s', '%s') == %d\n", s1, s2, strcasecmp(s1, s2)); 
        printf("strcoll('%s', '%s') == %d\n", s1, s2, strcoll(s1, s2)); 
    } 
    

    यह छपा है:

    strcasecmp('Äaa', 'äaa') == -32 
    strcoll('Äaa', 'äaa') == -32 
    strcasecmp('Äaa', 'äaa') == -32 
    strcoll('Äaa', 'äaa') == 7 
    strcasecmp('Äaa', 'äaa') == -32 
    strcoll('Äaa', 'äaa') == 7 
    

पुनश्च

और हाँ, मैं ICU के बारे में जानकारी है, लेकिन हम अपने enormous size की वजह से एम्बेडेड मंच पर उपयोग नहीं कर सकते ।

उत्तर

7

जो आप वास्तव में चाहते हैं वह तर्कसंगत रूप से असंभव है। स्ट्रिंग को सॉर्ट करने का कोई लोकेल-स्वतंत्र, केस-असंवेदनशील तरीका नहीं है। सरल काउंटर उदाहरण "i" <> "मैं" है? मूर्ख जवाब नहीं है, लेकिन तुर्की में ये तार असमान हैं। "i" "İ" (यू + 130 लैटिन कैपिटल I ऊपर डॉट के साथ)

यूटीएफ -8 स्ट्रिंग्स को अतिरिक्त जटिलता जोड़ती है। यदि आपके पास उपयुक्त लोकेल है, तो वे पूरी तरह से वैध बहु-बाइट चार * स्ट्रिंग्स हैं। लेकिन न तो सी और न ही सी ++ मानक ऐसे लोकेल को परिभाषित करता है; अपने विक्रेता से जांचें (बहुत सारे एम्बेडेड विक्रेताओं, क्षमा करें, यहां कोई जनरिपक्व उत्तर नहीं है)। इसलिए आपको एक लोकेल चुनना है जिसका बहु-बाइट एन्कोडिंग यूटीएफ -8 है, mbscmp फ़ंक्शन काम करने के लिए। यह निश्चित रूप से सॉर्ट ऑर्डर को प्रभावित करता है, जो लोकेल निर्भर है। और यदि आपके पास कोई लोकेल नहीं है जिसमें कॉन्स char * यूटीएफ -8 है, तो आप इस चाल का उपयोग नहीं कर सकते हैं। (जैसा कि मैं इसे समझता हूं, माइक्रोसॉफ्ट का सीआरटी इससे पीड़ित है। उनका बहु-बाइट कोड केवल 2 बाइट तक वर्णों को संभालता है; यूटीएफ -8 की जरूरत 3)

wchar_t मानक समाधान नहीं है। यह माना जाता है कि आपको बहु-बाइट एन्कोडिंग से निपटने की ज़रूरत नहीं है, लेकिन आपका संयोजन अभी भी लोकेल (एलसी_Cओएलएलएटी) पर निर्भर करेगा। हालांकि, wchar_t का उपयोग करने का मतलब है कि अब आप उन लोकेशंस का चयन करते हैं जो यूटीएफ -8 का उपयोग कॉन्स char * के लिए नहीं करते हैं।

ऐसा करने के साथ, आप मूल रूप से स्ट्रिंग्स को लोअरकेस में परिवर्तित करके और उनकी तुलना करके अपना ऑर्डरिंग लिख सकते हैं। यह सही नहीं है। क्या आप एल "ß" == एल "एसएस" की उम्मीद करते हैं? वे एक ही लंबाई भी नहीं हैं। फिर भी, एक जर्मन के लिए आपको उन्हें बराबर मानना ​​होगा। क्या आप इसके साथ रह सकते हैं?

+2

जर्मन "ß" चरित्र (और ऐसे सभी प्रचुर मात्रा में मामलों) के साथ आपके उदाहरण के बारे में: इन्हें "हल" किया जाना चाहिए या अन्यथा यूटीएफ -8 या नहीं, इससे पहले हजारों बार निपटाया जाना चाहिए। एमएस वर्ड में हमेशा "टॉगल केस" सुविधा होती है - यह उस चरित्र पर प्री-यूनिकोड संस्करणों में कैसे काम करता है? WordPerfect कैसे किया? मुझे ओपी के समान समस्या है, सिवाय इसके कि मैं डेल्फी में काम करता हूं। मैंने कई विंडोज़ स्क्लाइट-आधारित ऐप्स देखे हैं जो एक केस-असंवेदनशील चयन (और मुझे लगता है कि ऑर्डर करें), चाहे वे एक अंग्रेजी, जर्मन या (मेरे मामले में) पोलिश लोकेल में स्थापित हों। फ़ायरफ़ॉक्स आज़माएं :) वे ऐसा कैसे करते हैं? –

+0

आमतौर पर गलत :) पोलिश में आईआईआरसी कोई कठिन मामला नहीं है; पोलिश में उपयोग किए जाने वाले सभी गैर-ASCII वर्ण "ASCII वर्णों" पर आधारित होते हैं। – MSalters

+0

तुर्की I समस्या के अलावा, यूनिकोड केस फोल्डिंग एल्गोरिदम (http://www.unicode.org/reports/tr44/) उल्लेखनीय रूप से अच्छी तरह से काम करता है। – dalle

0

मुझे नहीं लगता कि एक मानक सी/सी ++ लाइब्रेरी फ़ंक्शन है जिसका आप उपयोग कर सकते हैं। आपको अपना खुद का रोल करना होगा या तीसरे पक्ष की लाइब्रेरी का उपयोग करना होगा। लोकेल-विशिष्ट संयोजन के लिए पूर्ण यूनिकोड विनिर्देश यहां पाया जा सकता है: http://www.unicode.org/reports/tr10/ (चेतावनी: यह लंबा दस्तावेज़ है)।

0

विंडोज़ पर आप ओएस फ़ंक्शन तुलनास्ट्रिंग डब्ल्यू पर वापस गिर सकते हैं और NORM_IGNORECASE ध्वज का उपयोग कर सकते हैं। आपको अपने यूटीएफ -8 तारों को पहले यूटीएफ -16 में परिवर्तित करना होगा। अन्यथा, आईबीएम के International Components for Unicode पर एक नज़र डालें।

0

मेरा मानना ​​है कि आपको अपना खुद का रोल करना होगा या किसी तृतीय पक्ष लाइब्रेरी का उपयोग करना होगा। मैं एक थर्ड पार्टी लाइब्रेरी की अनुशंसा करता हूं क्योंकि सच्चे अंतर्राष्ट्रीय समर्थन प्राप्त करने के लिए बहुत से नियम हैं जिनका पालन करने की आवश्यकता है - जो किसी के साथ विशेषज्ञ सौदा करने के लिए सबसे अच्छा है।

0

मेरे पास उदाहरण कोड के रूप में कोई निश्चित उत्तर नहीं है, लेकिन मुझे यह इंगित करना चाहिए कि एक यूटीएफ -8 बायस्ट्रीम में वास्तव में यूनिकोड वर्ण हैं और आपको सी/सी ++ रनटाइम लाइब्रेरी के wchar_t संस्करणों का उपयोग करना होगा।

आपको उन यूटीएफ -8 बाइट्स को पहले wchar_t तारों में परिवर्तित करना होगा, हालांकि। यह बहुत कठिन नहीं है, क्योंकि यूटीएफ -8 एन्कोडिंग मानक very well documented है। मुझे यह पता है, क्योंकि मैंने इसे किया है, लेकिन मैं आपके साथ उस कोड को साझा नहीं कर सकता।

0

आप इसे प्रयोग कर रहे हैं खोज करने के लिए और केवल आपके स्थान के लिए छँटाई, मेरा सुझाव है कॉल करने के लिए अपने कार्य एक सरल समारोह है कि चार लोगों को प्रति एक बाइट में दोनों मल्टी-बाइट तार कन्वर्ट की तरह एक तालिका का उपयोग कर की जगह:

A -> एक
A -> एक
A -> एक
ß -> एस एस
सी -> ग
और इतने

पर तब बस strcmp फोन और परिणाम।

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

  • कोई संबंधित समस्या नहीं^_^