कैसी है const std :: wstring एन्कोडेड और कैसे बदलकर UTF-16 करें
मैंने इस न्यूनतम कार्य C ++ उदाहरण स्निपेट को बाइट्स (उनके हेक्स प्रतिनिधित्व द्वारा) में std::string
और std::wstring
जब दोनों प्रकार में जर्मन गैर-एएससीआईआई पात्रों के साथ एक स्ट्रिंग को परिभाषित करने के लिए बनाया।
#include <iostream>
#include <iomanip>
#include <string>
int main(int, char**) {
std::wstring wstr = L"äöüß";
std::string str = "äöüß";
for ( unsigned char c : str ) {
std::cout << std::setw(2) << std::setfill('0') << std::hex << static_cast<unsigned short>(c) << ' ';
}
std::cout << std::endl;
for ( wchar_t c : wstr ) {
std::cout << std::setw(4) << std::setfill('0') << std::hex << static_cast<unsigned short>(c) << ' ';
}
std::cout << std::endl;
return 0;
}
इस स्निपेट का आउटपुट है
c3 a4 c3 b6 c3 bc c3 9f
00c3 00a4 00c3 00b6 00c3 00bc 00c3 0178
मैंने खुद को विंडोज 10 64-बिट प्रो चलाने वाले एक पीसी पर चलाया , संस्करण 16.8.1 में MSVC 2019 कम्युनिटी एडिशन के साथ संकलित करते हुए, निम्न के साथ बिल्ड सिस्टम सेमीक का उपयोग करकेCMakeLists.txt
cmake_minimum_required(VERSION 3.0.0)
project(wstring VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 17)
include(CTest)
enable_testing()
add_executable(wstring main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
मैंने पढ़ा, यह उस प्रकार std::string
पर आधारित है char
जो एक एकल बाइट है। मैं देखता हूं कि मेरे स्निपेट का आउटपुट इंगित करता है कि str
( std::string
चर) UTF-8 एन्कोडेड है। मैंने पढ़ा, कि Microsoft संकलक wchar_t
2 बाइट्स के साथ s का उपयोग करने के लिए std::wstring
s बनाता है ( wchar_t
उदाहरण के लिए, GNU gcc द्वारा 4 बाइट के बजाय ) और इसलिए (किसी भी तरह का) UTF-16 होने wstr
की उम्मीद करेगा । लेकिन मैं यह पता नहीं लगा सकता कि "ß" (लैटिन तेज एस) एन्कोडेड क्यों है क्योंकि मैंने इसके बजाय उम्मीद की थी । कृपया कोई मुझे बताए:std::wstring
0x00c30178
0x00df
- ऐसा क्यों हो रहा है?
- मैं यूटीएफ -16 एनकोडेड
std::wstring
एस के साथ कैसे समाप्त हो सकता हूं (बिग एंडियन ठीक होगा, मुझे कोई बुरा नहीं लगता)? क्या मुझे शायद किसी तरह संकलक को बताने की ज़रूरत है? - यह किस प्रकार का एन्कोडिंग है?
EDIT 1
बदला हुआ शीर्षक, क्योंकि यह प्रश्नों को ठीक से फिट नहीं करता था (और वास्तव में UTF-8 और UTF-16 अलग-अलग एन्कोडिंग हैं इसलिए मैं अपना स्वयं का उत्तर पहले से ही नया हूं ...)
EDIT 2
उल्लेख करना भूल गया: मैं amd64
उल्लिखित संकलक के लक्ष्य का उपयोग करता हूं
EDIT 3
अगर /utf-8
dxiv द्वारा टिप्पणियों में बताए गए झंडे को जोड़ना ( उनकी लिंक की गई SO- पोस्ट देखें ), मुझे वांछित आउटपुट मिलता है
c3 a4 c3 b6 c3 bc c3 9f
00e4 00f6 00fc 00df
जो मेरे लिए UTF-16-BE (कोई BOM) जैसा दिखता है। जैसा कि मैंने सीमेक कमांड के सही क्रम के साथ समस्या की थी यह मेरी वर्तमान CmakeLists.txt
फ़ाइल है। add_compile_options
कमांड से पहले कमांड रखना महत्वपूर्ण है add_executable
(मैंने सुविधा के लिए नोटिस जोड़ा)
cmake_minimum_required(VERSION 3.0.0)
project(enctest VERSION 0.1.0)
set(CMAKE_CXX_STANDARD 17)
include(CTest)
enable_testing()
if (MSVC)
message(NOTICE "compiling with MSVC")
add_compile_options(/utf-8)
endif()
add_executable(enctest main.cpp)
set(CPACK_PROJECT_NAME ${PROJECT_NAME}) set(CPACK_PROJECT_VERSION ${PROJECT_VERSION})
include(CPack)
मुझे if-endif
जनरेटर-सिंटैक्स एक की तुलना में अधिक पठनीय तरीका लगता है , लेकिन इसके बजाय लेखन भी काम करेगा।add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
नोट: Qt-Projects के लिए .pro
फ़ाइल के लिए एक अच्छा स्विच है ( यह Qt-Form पोस्ट देखें )
win32 {
QMAKE_CXXFLAGS += /utf-8
}
अभी भी मेरे सवाल का पहला हिस्सा खुला है: "एन्कोडिंग 0x00c30178
" (लैटिन तेज एस) के लिए क्या एन्कोडिंग है ?
जवाब
जैसा कि टिप्पणियों में स्पष्ट किया गया है, स्रोत .cpp
फ़ाइल UTF-8 एन्कोडेड है। BOM के बिना, और एक स्पष्ट /source-charset:utf-8
स्विच के बिना , दृश्य C ++ कंपाइलर डिफॉल्ट को स्रोत फ़ाइल मानने के लिए सक्रिय कोडपेज एन्कोडिंग में सहेजा जाता है। से सेट स्रोत वर्ण सेट प्रलेखन:
डिफ़ॉल्ट रूप से, दृश्य स्टूडियो एक बाइट-ऑर्डर चिह्न का पता लगाने के लिए निर्धारित करता है कि स्रोत फ़ाइल एक एन्कोडेड यूनिकोड प्रारूप में है, उदाहरण के लिए, UTF-16 या UTF-8। यदि कोई बाइट-ऑर्डर चिह्न नहीं मिला है, तो यह मानता है कि स्रोत फ़ाइल वर्तमान उपयोगकर्ता कोड पृष्ठ का उपयोग करके एन्कोडेड है, जब तक कि आप / source-charset विकल्प का उपयोग करके वर्ण सेट नाम या कोड पृष्ठ निर्दिष्ट नहीं करते हैं।
UTF-8 की एन्कोडिंग äöüß
है C3 A4 C3 B6 C3 BC C3 9F
, और इसलिए लाइन:
std::wstring wstr = L"äöüß";
संकलक द्वारा देखा जाता है:
std::wstring wstr = L"\xC3\xA4\xC3\xB6\xC3\xBC\xC3\x9F"`;
सक्रिय कोडपेज को सामान्य Windows-1252 मानते हुए , (विस्तारित) वर्ण मानचित्र इस प्रकार है:
win-1252 char unicode
\xC3 Ã U+00C3
\xA4 ¤ U+00A4
\xB6 ¶ U+00B6
\xBC ¼ U+00BC
\x9F Ÿ U+0178
इसलिए इसका L"\xC3\xA4\xC3\xB6\xC3\xBC\xC3\x9F"
अनुवाद किया जाता है:
std::wstring wstr = L"\u00C3\u00A4\u00C3\u00B6\u00C3\u00BC\u00C3\u0178"`;
ऐसे (गलत) अनुवाद से बचने के लिए, विजुअल C ++ को बताया जाना चाहिए कि स्रोत फ़ाइल एक स्पष्ट /source-charset:utf-8
(या /utf-8) कंपाइलर स्विच को पास करके UTF-8 के रूप में एन्कोडेड है । CMake आधारित परियोजनाओं के लिए, BOM के बिना स्रोत फ़ाइलों के लिए UTF-8 एन्कोडिंग का उपयोग करने के लिए CMake / MSVC को बाध्य करने के लिए संभव केadd_compile_options
रूप में दिखाया गया है । C4819 ।
इसलिए उम्मीद है कि wstr (std :: wstring वैरिएबल) हो सकता है (किसी भी तरह का) UTF-16 इनकोडिंग
std::wstring
एन्कोडिंग निर्दिष्ट नहीं करता है। यह "वाइड कैरेक्टर" का एक क्रम है, कुछ प्रकार के वाइड कैरेक्टर के लिए (जो कि कार्यान्वयन परिभाषित हैं)।
अलग-अलग एन्कोडिंग से / में परिवर्तित करने के लिए मानक पुस्तकालय में रूपांतरण रूपांतरण परिभाषित किए गए हैं ।