2013-04-05 4 views
8

सी ++ में एन्कोडिंग सेट करने के लिए सबसे अच्छा कैसे है?सी ++ में एन्कोडिंग सेट करने का सबसे सही तरीका क्या है?

मैं यूनिकोड के साथ काम करने के लिए इस्तेमाल किया गया है (और wchar_t, wstring, wcin, wcout और एल "...")। मैं यूटीएफ -8 में स्रोत भी बचाता हूं।

फिलहाल मैं मिनीजीडब्लू (विंडोज 7) का उपयोग करता हूं और विंडोज कंसोल (cmd.exe) में अपना प्रोग्राम चलाता हूं, लेकिन कभी-कभी मैं जीएनयू \ लिनक्स पर जीसीसी का उपयोग कर सकता हूं और यूटीएफ -8 एन्कोडिंग के साथ लिनक्स कंसोल में प्रोम्राम चला सकता हूं।

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

जब मुझे एन्कोडिंग के साथ अगली समस्या का सामना करना पड़ा, तो मैंने गुगल किया। <windows.h> और कई, कई अन्य लोगों से setlocale(LC_ALL, "") और setlocale(LC_ALL, "xx_XX.UTF-8"), std::setlocale(LC_ALL, "") और std::setlocale(LC_ALL, "xx_XX.UTF-8")<clocale> से,

SetConsoleCP() और SetConsoleOutputCP(): इसके अलावा, मैं सबसे अलग परिषदों पाया।

अंत में मुझे इस शमनवाद से परेशान था और मैं आपसे पूछना चाहता हूं: एन्कोडिंग स्थापित करना सही कैसे है?

+0

क्या, आप वास्तव में बदलना चाहते हैं? क्या आप थ्रेड लोकेल को बदलना चाहते हैं? सिस्टम लोकेल? यूआई भाषा? या सक्रिय कोड पेज? धागे, कंसोल, या सिस्टम के लिए? एक बहुत सारे विकल्प हैं, जो एकल 'सेटलोकेल' फ़ंक्शन द्वारा निहित किए गए हैं। इससे पहले कि हम आपको बता सकें कि फ्लिप करने के लिए स्विच करने से पहले आपको * प्रभाव * को देखना होगा। –

+0

@ कोडीग्रे, मुझे चाहिए कि किसी भी यूनिकोड प्रतीक/स्ट्रिंग को सही ढंग से इनपुट और आउटपुट किया गया हो। _effect_ का यह पर्याप्त विवरण? मुझे लगता है, इसका मतलब है कि मुझे कंसोल के एन्कोडिंग को बदलने की ज़रूरत है जिसमें प्रोग्राम शुरू हो गया है। –

+0

आम तौर पर, मैं कहूंगा कि एक कार्यक्रम लोकेल को संशोधित नहीं करना चाहिए - इसे प्रदान किए गए लोकेल के भीतर काम करना चाहिए। अन्यथा, यह "अंतर्राष्ट्रीयकरण" के उद्देश्य को हरा देता है। –

उत्तर

5

मुझे चाहिए कि किसी भी यूनिकोड प्रतीक/स्ट्रिंग को सही ढंग से इनपुट और आउटपुट किया गया हो।

यह निश्चित रूप से संभव है, हालांकि विंडोज कमांड प्रॉम्प्ट कंसोल ठीक से बना रहा है यूनिकोड-जागरूक कुछ विशेष जादू लेता है। मुझे गंभीरता से संदेह है कि दुर्भाग्यवश, मानक पुस्तकालय कार्यों के किसी भी कार्यान्वयन के लिए ऐसा करने जा रहे हैं।

आपको स्टैक ओवरफ़्लो पर इसके बारे में कई प्रश्न मिलेंगे, लेकिन this one is a good one पर। असल में, कंसोल डिफ़ॉल्ट रूप से "OEM" कोड पृष्ठ कहलाता है (कुछ हद तक गलती से)। आप इसे यूटीएफ -8 कोड पेज में बदलना चाहते हैं, जिसका मान CP_UTF8 द्वारा परिभाषित किया गया है। ऐसा करने के लिए, आपको SetConsoleCP फ़ंक्शन (इनपुट कोड पृष्ठ सेट करने के लिए) और SetConsoleOutputCP फ़ंक्शन (आउटपुट कोड पृष्ठ सेट करने के लिए) को कॉल करने की आवश्यकता होगी। कोड कुछ इस तरह दिखेगा:

if (!SetConsoleCP(CP_UTF8)) 
{ 
    // An error occurred; handle it. Call GetLastError() for more information. 
    // ... 
} 
if (!SetConsoleOutputCP(CP_UTF8)) 
{ 
    // An error occurred; handle it. Call GetLastError() for more information. 
    // ... 
} 

अतिरिक्त मजबूती के लिए, आप यह भी सुनिश्चित करें कि UTF-8 कोड पेज पहले समर्थित है, की स्थापना की और इसका इस्तेमाल करने के प्रयास करने से पहले बनाने के लिए चाहते हो सकता है। आप IsValidCodePage फ़ंक्शन को कॉल करके ऐसा करेंगे। उदाहरण के लिए:।

if (IsValidCodePage(CP_UTF8)) 
{ 
    // We're all good, so set the console code page... 
} 

तुम भी डिफ़ॉल्ट ("रेखापुंज फ़ॉन्ट्स") कुछ करने के लिए है कि अपेक्षित यूनिकोड वर्ण ग्लिफ़-उदा, ल्युसिडा कंसोल या Consolas (reference) शामिल हैं से फ़ॉन्ट बदलने करना होगा। SetCurrentConsoleFontEx फ़ंक्शन का उपयोग करना मुश्किल है।

दुर्भाग्यवश, यह फ़ंक्शन Vista से पहले विंडोज के संस्करणों में मौजूद नहीं है। यदि आपको इन पुराने ऑपरेटिंग सिस्टमों को पूरी तरह से समर्थन करने की ज़रूरत है, तो केवल एक चीज जिसे मैं जानता हूं वह अनियंत्रित SetConsoleFont फ़ंक्शन को कॉल करना है। आम तौर पर, मैं अनियंत्रित कार्यों का उपयोग करने के खिलाफ दृढ़ता से सलाह दूंगा, लेकिन मुझे लगता है कि यह एक समस्या से कम है क्योंकि आप केवल ऑपरेटिंग सिस्टम के पुराने संस्करणों में इसका उपयोग कर रहे हैं।आप जानते हैं कि वे बदलने जा रहे हैं। नए संस्करणों पर जहां यह उपलब्ध है, आप समर्थित फ़ंक्शन को कॉल करते हैं। नमूना अनचाहे कोड:

bool IsWinVistaOrLater() 
{ 
    OSVERSIONINFOEX osvi; 
    osvi.dwOSVersionInfoSize = sizeof(osvi); 
    GetVersionEx(reinterpret_cast<LPOSVERSIONINFO>(&osvi)); 

    if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT) 
    { 
     return osvi.dwMajorVersion >= 6; 
    } 
    return false; 
} 

void SetConsoleToUnicodeFont() 
{ 
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
    if (IsWinVistaOrLater()) 
    { 
     // Call the documented function. 
     typedef BOOL (WINAPI * pfSetCurrentConsoleFontEx)(HANDLE, BOOL, PCONSOLE_FONT_INFOEX); 
     HMODULE hMod = GetModuleHandle(TEXT("kernel32.dll")); 
     pfSetCurrentConsoleFontEx pfSCCFX = (pfSetCurrentConsoleFontEx)GetProcAddress(hMod, "SetCurrentConsoleFontEx"); 

     CONSOLE_FONT_INFOEX cfix; 
     cfix.cbSize  = sizeof(cfix); 
     cfix.nFont  = 12; 
     cfix.dwFontSize.X = 8; 
     cfix.dwFontSize.Y = 14; 
     cfix.FontFamily = FF_DONTCARE; 
     cfix.FontWeight = 400; // normal weight 
     lstrcpy(cfix.FaceName, TEXT("Lucida Console")); 

     pfSCCFX(hConsole, 
       FALSE, /* set font for current window size */ 
       &cfix); 
    } 
    else 
    { 
     // There is no supported function on these older versions, 
     // so we have to call the undocumented one. 
     typedef BOOL (WINAPI * pfSetConsoleFont)(HANDLE, DWORD); 
     HMODULE hMod = GetModuleHandle(TEXT("kernel32.dll")); 
     pfSetConsoleFont pfSCF = (pfSetConsoleFont)GetProcAddress(hMod, "SetConsoleFont"); 
     pfSCF(hConsole, 12); 
    } 
} 

ध्यान दें कि मैंने पाठक के लिए अभ्यास के रूप में आवश्यक त्रुटि जांच को छोड़ दिया है। यहां फोकस तकनीक और पठनीयता पर है; त्रुटि प्रबंधन के साथ इसे छेड़छाड़ करना सिर्फ मामलों को भ्रमित करेगा।

मुझे नहीं पता कि लिनक्स पर इनमें से कोई भी कैसे करें। मुझे संदेह है कि यह बहुत कम काम है, क्योंकि लोग मुझे बताते हैं कि ओएस आंतरिक रूप से यूटीएफ -8 का उपयोग करता है। किसी भी तरह से, आप इसके लिए अपने ही हैं; विंडोज़ purr एक जवाब के लिए पर्याप्त काम है!

0

मैं सिर्फ उत्पादन यूनिकोड पाठ कंसोल और केवल इस समारोह WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), ...); मदद की करने के लिए करने के लिए आवश्यक है। इनपुट के लिए मुझे लगता है कि ReadConsoleW(GetStdHandle(STD_INPUT_HANDLE), ...); चाल है।

पीएस: WriteOutput आउटपुट स्ट्रिंग आकार में एक सीमा है। तो यदि आप लंबे समय तक इसे घटकों में पुन: प्रयास करना चाहते हैं।

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