2015-09-01 4 views
5

सारांश: क्या मैं सही ढंग से एक स्ट्रिंग शाब्दिक स्रोत कोड में परिभाषित किया गया है कि एक cmdstd::cout धारा का उपयोग कर कंसोल के लिए UTF-8 एन्कोडिंग (विंडोज सी.पी. 65001) में जमा हो गया था मुद्रित करने के लिए क्या करना चाहिए?सी ++ 11 std :: cout << "विंडोज सीटीडी कंसोल में यूटीएफ -8 में स्ट्रिंग अक्षर"? (विजुअल स्टूडियो 2015)

प्रेरणा: मैं उच्चारण चिह्न पात्रों के साथ उत्कृष्ट Catch unit-testing framework (एक प्रयोग के रूप में) इतना है कि यह प्रदर्शित होता my texts संशोधित करना चाहते हैं। संशोधन सरल, भरोसेमंद होना चाहिए, और अन्य भाषाओं और कामकाजी वातावरण के लिए भी उपयोगी होना चाहिए ताकि लेखक द्वारा इसे एक वृद्धि के रूप में स्वीकार किया जा सके। या यदि आप पकड़ते हैं और यदि कोई वैकल्पिक समाधान है, तो क्या आप इसे पोस्ट कर सकते हैं?

विवरण: के चेक संस्करण साथ शुरू करते हैं "जल्दी भूरी लोमड़ी ..."

#include <iostream> 
#include "windows.h" 

using namespace std; 

int main() 
{ 
    cout << "\n-------------------------- default cmd encoding = 852 -------------------\n"; 
    cout << "Příšerně žluťoučký kůň úpěl ďábelské ódy!" << endl; 

    cout << "\n-------- Windows Central European (1250) set for the cmd console --------\n"; 
    SetConsoleOutputCP(1250); 
    std::cout << "Příšerně žluťoučký kůň úpěl ďábelské ódy!" << std::endl; 

    cout << "\n------------- Windows UTF-8 (65001) set for the cmd console -------------\n"; 
    SetConsoleOutputCP(CP_UTF8); 
    std::cout << "Příšerně žluťoučký kůň úpěl ďábelské ódy!" << std::endl; 
} 

यह निम्न (ल्युसिडा कंसोल के लिए सेट फ़ॉन्ट) प्रिंट: enter image description here

cmd डिफ़ॉल्ट एन्कोडिंग 852 है, डिफ़ॉल्ट विंडोज एन्कोडिंग 1250 है, और स्रोत कोड 65001 एन्कोडिंग (बीओएम के साथ यूटीएफ -8) का उपयोग करके सहेजा गया था। SetConsoleOutputCP(1250);cmd एन्कोडिंग (प्रोग्रामेटिक रूप से) को chcp 1250 करता है जैसा ही बदलता है।

निरीक्षण: 1250 एन्कोडिंग सेट करते समय, यूटीएफ -8 स्ट्रिंग शाब्दिक सही ढंग से मुद्रित किया जाता है। मेरा मानना ​​है कि इसे समझाया जा सकता है, लेकिन यह वास्तव में अजीब है। क्या कोई सभ्य, मानव है, समस्या को हल करने का सामान्य तरीका है?

अद्यतन:"narrow string literal" मेरे मामले में विंडोज -1250 एन्कोडिंग (मध्य यूरोपीय के लिए मूल विंडोज एन्कोडिंग) का उपयोग करके संग्रहीत किया जाता है। यह स्रोत कोड के एन्कोडिंग पर स्वतंत्र प्रतीत होता है। संकलक इसे विंडोज मूल एन्कोडिंग में सहेजता है। उस वजह से, उस एन्कोडिंग में cmd स्विच करना वांछित आउटपुट देता है। यह बदसूरत है, लेकिन मैं देशी विंडोज एन्कोडिंग प्रोग्रामेटिक रूप से कैसे प्राप्त कर सकता हूं (इसे SetConsoleOutputCP(cpX) पर पास करने के लिए)? मुझे जो चाहिए वह स्थिर है जो मशीन के लिए मान्य है जहां संकलन हुआ। यह मशीन के लिए मूल एन्कोडिंग नहीं होना चाहिए जहां निष्पादन योग्य चलता है।

सी ++ 11 भी पेश u8"the UTF-8 string literal", लेकिन यह SetConsoleOutputCP(CP_UTF8);

+1

संभवतः संबंधित: http://stackoverflow.com/questions/18904081/printing-unicode-characters-c/18906295#18906295 – luk32

+0

@ luk32: संदर्भ के लिए धन्यवाद। मुझे इसे देखना होगा। – pepr

+1

एमएसवीसी में यूटीएफ -8 स्रोत को संकलित करते समय, यह स्ट्रिंग अक्षर का मूल एन्कोडिंग में अनुवाद करेगा यदि फ़ाइल _UTF-8 BOM_ के साथ शुरू होती है। जब आप इसे हटाते हैं, तो आपकी टेस्ट स्ट्रिंग को तीसरे मामले में सही ढंग से मुद्रित किया जाना चाहिए। – Melebius

उत्तर

2

यह एक आंशिक जवाब luk32 से लिंक हॉपिंग और Melebius टिप्पणियों की पुष्टि के माध्यम से पाया जाता है के साथ फिट करने के लिए (प्रश्न नीचे देखें) प्रतीत नहीं होता। यह पूरा जवाब नहीं है, और मुझे आपकी अनुवर्ती टिप्पणी स्वीकार करने में खुशी होगी।

मुझे अभी UTF-8 Everywhere Manifesto समस्या मिली है जो समस्या को छूता है। बिंदु 17. Q: How do I write UTF-8 string literal in my C++ code? (यह भी माइक्रोसॉफ्ट C++ कम्पाइलर के लिए स्पष्ट) का कहना है:

हालांकि सबसे सरल तरीका है बस के रूप में-है स्ट्रिंग लिखने और स्रोत में encoded फ़ाइल को बचाने के लिए है UTF-8:

       "∃y ∀x ¬(x ≺ y)" 

दुर्भाग्यवश, एमएसवीसी स्ट्रिंग को दूषित करने, इसे कुछ एएनएसआई कोडपेज में परिवर्तित करता है।इस के आसपास काम करने के लिए, बीओएम के बिना फ़ाइल को यूटीएफ -8 में सहेजें। एमएसवीसी मान लेगा कि यह सही कोडपेज में है और आपके तारों को छूएगा नहीं। हालांकि, यह यूनिकोड पहचानकर्ताओं और विस्तृत स्ट्रिंग अक्षरों का उपयोग करना असंभव है (कि आप वैसे भी उपयोग नहीं करेंगे)।

मुझे वास्तव में घोषणापत्र पसंद है। यह छोटा है, अशिष्ट शब्दों का उपयोग कर, और संभवतः oversimplified बनाने के लिए, यह कहते हैं:

पर ध्यान न दें wstring, wchar_t, और तरह बातें। कोडपेज को अनदेखा करें। L, u, U, u8 जैसे स्ट्रिंग शाब्दिक उपसर्गों को अनदेखा करें। यूटीएफ -8 हर जगह प्रयोग करें। सभी अक्षर "naturally" लिखें। सुनिश्चित करें कि यह संकलित बाइनरी में भी संग्रहीत है।

निम्नलिखित कोड बीओएम बिना UTF-8 के साथ संग्रहीत है, तो ...

#include <iomanip> 
#include <iostream> 
#include "windows.h" 

using namespace std; 

int main() 
{ 
    SetConsoleOutputCP(CP_UTF8); 
    cout << "Příšerně žluťoučký kůň úpěl ďábelské ódy!" << endl; 

    int cnt = 0; 
    for (unsigned int c : "Příšerně žluťoučký kůň úpěl ďábelské ódy!") 
    { 
     cout << hex << setw(2) << setfill('0') << (c & 0xff); 
     ++cnt; 
     if (cnt % 16 == 0)  cout << endl; 
     else if (cnt % 8 == 0) cout << " | "; 
     else if (cnt % 4 == 0) cout << " "; 
     else     cout << ' '; 
    } 
    cout << endl; 
} 

यह प्रिंट ... (UTF-8 एन्कोडेड होना चाहिए)

enter image description here

बीओएम के साथ स्रोत को यूटीएफ -8 के रूप में सहेजते समय, यह एक अलग परिणाम प्रिंट करता है ...

enter image description here

हालांकि, समस्या बनी हुई है - कंसोल एन्कोडिंग प्रोग्रामेटिक रूप से कैसे सेट करें ताकि यूटीएफ -8 स्ट्रिंग सही ढंग से मुद्रित हो।

मैंने छोड़ दिया।cmd कंसोल बस अपंग है, और इसे बाहर से ठीक करने के लिए उचित नहीं है। मैं केवल प्रश्न को बंद करने के लिए अपनी टिप्पणी स्वीकार कर रहा हूं। अगर किसी को कैच यूनिट टेस्ट फ्रेमवर्क से संबंधित एक सभ्य समाधान मिल जाता है (पूरी तरह से अलग हो सकता है), तो मुझे जवाब के रूप में उसकी टिप्पणी स्वीकार करने में खुशी होगी।

+1

मैं स्वीडिश ग्रंथों को आउटपुट करने के लिए यूटीएफ -8 का भी उपयोग करता हूं, यह एमएसवीसी2015 के साथ ठीक काम करता है जब तक कि .cpp फ़ाइल में कोई BOM नहीं है।नोट: ** नोटपैड का उपयोग करके फ़ाइल को कभी भी संपादित नहीं करें, यह एक बीओएम बनाएगा। वर्डपैड का प्रयोग करें। –

+0

@ हेनरीस्कोग्लंड: संकेत के लिए धन्यवाद। (मैं सरल चीजों के लिए नोटपैड ++ का उपयोग कर रहा हूं। उस संपादक में बीओएम के साथ या उसके बिना भी चयन करना संभव है,) क्या आप 'std :: cout' के माध्यम से' cmd' कंसोल पर यूटीएफ -8 टेक्स्ट भेजते हैं? – pepr

0

एमएसवीसी कंपाइलर आपके स्थानीय एन्कोडिंग के साथ कोड में अपने कॉन्स स्ट्रिंग को एन्कोड करने का प्रयास करता है। आपके मामले में, यह code page 852 का उपयोग करता है। तो आपका cmd आउटपुट भी code page 1250 के साथ स्ट्रिंग को पढ़ने और आउटपुट करने का प्रयास करता है, स्ट्रिंग वास्तव में code page 852 के साथ संग्रहीत होती है। भंडारण और पढ़ने के बीच ऐसी असंगतता गलत आउटपुट बनाती है।
इसे हल करने का एक तरीका स्ट्रिंग को code page 1250 से एन्कोडेड फ़ाइल में संग्रहीत करना है। Visual Studio Code ऐसी कार्यक्षमता प्रदान करता है। आप फ़ाइल को एक बाइनरी फ़ाइल (i.e बाइट द्वारा बाइट) के रूप में एक चार बफर में पढ़ सकते हैं, और उसके बाद बफर आउटपुट कर सकते हैं।

char * memblock = new char[1024]; 
std::ifstream file("src.txt", std::ios::in | std::ios::binary | std::ios::ate); 
int size; 
if (file.is_open()) 
{ 
    size = file.tellg(); 
    memblock = new char[size]; 
    file.seekg(0, std::ios::beg); 
    file.read(memblock, size); 
    file.close(); 
} 
else 
{ 
    std::cout << "File not opened." << std::endl; 
} 
memblock[size] = 0; 
std::cout << memblock << std::endl; 

enter image description here

+0

धन्यवाद, फॉक्स। समस्या यह है कि मुझे अन्य कारणों से यूटीएफ -8 में फ़ाइल को स्टोर करने की आवश्यकता है। – pepr

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