कैसी है const std :: wstring एन्कोडेड और कैसे बदलकर UTF-16 करें

Nov 30 2020

मैंने इस न्यूनतम कार्य 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_t2 बाइट्स के साथ s का उपयोग करने के लिए std::wstrings बनाता है ( wchar_tउदाहरण के लिए, GNU gcc द्वारा 4 बाइट के बजाय ) और इसलिए (किसी भी तरह का) UTF-16 होने wstrकी उम्मीद करेगा । लेकिन मैं यह पता नहीं लगा सकता कि "ß" (लैटिन तेज एस) एन्कोडेड क्यों है क्योंकि मैंने इसके बजाय उम्मीद की थी । कृपया कोई मुझे बताए:std::wstring0x00c301780x00df

  • ऐसा क्यों हो रहा है?
  • मैं यूटीएफ -16 एनकोडेड std::wstringएस के साथ कैसे समाप्त हो सकता हूं (बिग एंडियन ठीक होगा, मुझे कोई बुरा नहीं लगता)? क्या मुझे शायद किसी तरह संकलक को बताने की ज़रूरत है?
  • यह किस प्रकार का एन्कोडिंग है?

EDIT 1

बदला हुआ शीर्षक, क्योंकि यह प्रश्नों को ठीक से फिट नहीं करता था (और वास्तव में UTF-8 और UTF-16 अलग-अलग एन्कोडिंग हैं इसलिए मैं अपना स्वयं का उत्तर पहले से ही नया हूं ...)

EDIT 2

उल्लेख करना भूल गया: मैं amd64उल्लिखित संकलक के लक्ष्य का उपयोग करता हूं

EDIT 3

अगर /utf-8dxiv द्वारा टिप्पणियों में बताए गए झंडे को जोड़ना ( उनकी लिंक की गई 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" (लैटिन तेज एस) के लिए क्या एन्कोडिंग है ?

जवाब

5 dxiv Dec 01 2020 at 16:41

जैसा कि टिप्पणियों में स्पष्ट किया गया है, स्रोत .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 ।

MarshallClow Nov 30 2020 at 20:50

इसलिए उम्मीद है कि wstr (std :: wstring वैरिएबल) हो सकता है (किसी भी तरह का) UTF-16 इनकोडिंग

std::wstringएन्कोडिंग निर्दिष्ट नहीं करता है। यह "वाइड कैरेक्टर" का एक क्रम है, कुछ प्रकार के वाइड कैरेक्टर के लिए (जो कि कार्यान्वयन परिभाषित हैं)।

अलग-अलग एन्कोडिंग से / में परिवर्तित करने के लिए मानक पुस्तकालय में रूपांतरण रूपांतरण परिभाषित किए गए हैं ।