2015-09-07 2 views
7

जी ++ के साथ लिनक्स पर, यदि मैं एक utf8 वैश्विक लोकेल सेट करता हूं, तो wcin आंतरिक wchar_t एन्कोडिंग में यूटीएफ -8 को सही ढंग से ट्रांसकोड करता है।wcin.imbue और UTF-8

हालांकि, अगर मैं क्लासिक लोकेल का उपयोग करता हूं और एक यूटीएफ 8 लोकेल को wcin में लगाता हूं, तो ऐसा नहीं होता है। इनपुट या तो पूरी तरह से विफल रहता है, या प्रत्येक व्यक्तिगत बाइट स्वतंत्र रूप से wchar_t में परिवर्तित हो जाता है।

क्लैंग ++ और libC++ के साथ, न तो वैश्विक लोकेल सेट करना और न ही wcin कार्य में लोकेल को एम्बेड करना।

#include <iostream> 
#include <locale> 
#include <string> 

using namespace std; 

int main() { 
    if(true)   
     // this works with g++, but not with clang++/libc++ 
     locale::global(locale("C.UTF-8")); 
    else 
     // this doesn't work with either implementation 
     wcin.imbue(locale("C.UTF-8")); 
    wstring s; 
    wcin >> s; 
    cout << s.length() << " " << (s == L"áéú"); 
    return 0; 
} 

इनपुट स्ट्रीम में केवल ééú वर्ण हैं। (वे यूटीएफ -8 में हैं, कोई सिंगल-बाइट एन्कोडिंग नहीं)।

लाइव डेमो: onetwo (मैं ऑनलाइन कंपेलरों के साथ अन्य व्यवहार को पुन: पेश नहीं कर सकता)।

क्या यह मानक-अनुरूप है? क्या मुझे अकेले वैश्विक लोकेल छोड़ने और imbue का उपयोग करने में सक्षम नहीं होना चाहिए?

क्या वर्णित व्यवहारों में से किसी एक को कार्यान्वयन बग के रूप में वर्गीकृत किया जाना चाहिए?

+1

"clang ++" से आपका क्या मतलब है? संकलक अप्रासंगिक है क्योंकि यह पूरी तरह से मानक पुस्तकालय (सी और सी ++ भागों दोनों) और मशीन पर स्थापित लोकेल डेटा पर निर्भर करता है। क्या आपने libstdC++ और libC++ दोनों के साथ जांच की है, या दो compilers के साथ libstdC++ दो बार जांचें? –

+0

@ जोनाथन वाकई आप सही हैं, मुझे "libstdC++ और libC++" कहा जाना चाहिए था। मुझे लगता है कि मैंने clang ++ के साथ libC++ का उपयोग किया है, लेकिन मैं अभी इसे जांच नहीं सकता। जैसे ही मैं अपनी मशीन पर जाता हूं, डबल-चेक और अपडेट कर दूंगा। –

+0

ठीक है, तो मुझे आश्चर्य है कि समस्या 'wcin' की मौलिक सीमा है, जिसमें यूटीएफ -8 ऑक्टेट्स से' wchar_t' का रूपांतरण stdio परत द्वारा किया जाता है, जो वैश्विक लोकेल का उपयोग धारा के एक नहीं करता है। लेकिन यह libstdC++ (और शायद libC++ भी) में एक बग हो सकता है, मुझे यकीन नहीं है। मैं भी काम करने के लिए 'imbue' के उपयोग की उम्मीद करेंगे। –

उत्तर

2

सबसे पहले आपको wcout के साथ wcout का उपयोग करना चाहिए।

अब आप कि करने के लिए दो संभव समाधान है:

1) का उपयोग कर

ios_base::sync_with_stdio(false); 

ध्यान दें, कि यह पहला कॉल किया जाना चाहिए द्वारा iostream और cstdio धाराओं के तुल्यकालन को निष्क्रिय, अन्यथा व्यवहार पर निर्भर करता है कार्यान्वयन।

int main() { 

    ios_base::sync_with_stdio(false); 
    wcin.imbue(locale("C.UTF-8")); 

    wstring s; 
    wcin >> s; 
    wcout << s.length() << " " << (s == L"áéú"); 
    return 0; 
} 

2) दोनों स्थान और wcout लोकलाइज़ करें:

int main() { 

    std::setlocale(LC_ALL, "C.UTF-8"); 
    wcout.imbue(locale("C.UTF-8")); 

    wstring s; 
    wcin >> s; 
    wcout << s.length() << " " << (s == L"áéú"); 
    return 0; 
} 

उन दोनों परीक्षण ideone का उपयोग कर, ठीक काम करता है। मेरे पास मेरे साथ clang ++/libC++ नहीं है, इसलिए इस व्यवहार का परीक्षण करने में सक्षम नहीं था, क्षमा करें।

+0

ठीक है मैं libstdC++ के साथ वैश्विक setlocale कामों को जानता हूँ। लेकिन लोकेल को इकट्ठा करने के लिए हमें स्टडीओ के साथ असंसत करने की आवश्यकता क्यों है? मुझे मानक में कुछ भी नहीं मिला। –

+0

सिंक आपको एक ही प्रोग्राम में cout और printf का उपयोग करने की अनुमति देता है। सी -+ स्ट्रीम के साथ सिंक किए जाने पर गैर-लोकेल सी स्ट्रीम यूटीएफ -8 एन्कोडिंग तोड़ देंगे। यही कारण है कि दूसरा समाधान वैश्विक सेटलोकेल का उपयोग करता है। –

+1

लेकिन मैं कोई सी स्ट्रीम I/O नहीं करता, क्यों unsync अभी भी आवश्यक है? –

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