2016-12-15 2 views
1

unter Windows mit Visual Studio 2015vergleichen Unicode std :: string mit üblichen "" wörtlichen oder u8 "" declartion

// Ü 
    // UTF-8 (hex) 0xC3 0x9C 
    // UTF-16 (hex) 0x00DC 
    // UTF-32 (hex) 0x000000DC 

    using namespace std::string_literals; 
    const auto narrow_multibyte_string_s = "\u00dc"s; 
    const auto wide_string_s    = L"\u00dc"s; 
    const auto utf8_encoded_string_s  = u8"\u00dc"s; 
    const auto utf16_encoded_string_s = u"\u00dc"s; 
    const auto utf32_encoded_string_s = U"\u00dc"s; 

    assert(utf8_encoded_string_s  == "\xC3\x9C"); 
    assert(narrow_multibyte_string_s ==  "Ü"); 
    assert(utf8_encoded_string_s  ==  u8"Ü"); 

    // here is the question 
    assert(utf8_encoded_string_s != narrow_multibyte_string_s); 

"\ u00dc" s ist nicht die gleiche wie u8 "\ u00dc" s oder "Ü" s ist nicht die gleiche wie u8

Anscheinend ist die Standard-Kodierung für üblich String s "Ü" wörtliche ist nicht UTF-8 (wahrscheinlich UTF-16), und ich kann nicht nur zwei vergleichen std :: string ohne zu wissen, dass die Kodierung eve ist n sie haben die gleiche Semantik.

Was ist die Praxis, solche Zeichenfolge Vergleich in Unicode-fähigen C++ - Anwendungsentwicklung zu führen?

Zum Beispiel ein API wie folgt aus:

class MyDatabase 
    { 
     bool isAvailable(const std::string& key) 
     { 
     // *compare* key in database 
     if (key == "Ü") 
      return true; 
     else 
      return false; 
     } 
    } 

Andere Programme aufrufen können isAvailable mit std :: string in UTF-8 oder Standard (UTF-16?) Codierung. Wie kann ich den richtigen Vergleich garantieren?

Kann ich bei der Kompilierungszeit eine Kodierungsabweichung feststellen?

Hinweis: Ich bevorzuge C++ 11/14 Sachen. Antwort std :: string als std :: wstring

+0

UTF-16 wird nur mit 'wstring' verwendet, jede Erwähnung in Ihrer Frage ist definitiv eine falsche Vermutung. Die Standardcodierung ist wahrscheinlich die aktuelle ANSI-Codepage zum Zeitpunkt der Kompilierung. Genauer gesagt, Standard ist keine Neukodierung, die Kodierung der Quelldatei wird beibehalten und zu Zwecken der Grammatikverarbeitung übernimmt der Compiler ANSI. –

Antwort

2

"\u00dc" ein char[] in welcher der Compiler/OS-Standard 8-Bit-Codierung passiert zu sein, codiert ist, so kann es auf verschiedenen Maschinen unterschiedlich sein. Unter Windows ist dies meist die standardmäßige Ansi-Codierung des Betriebssystems, oder es könnte die Codierung sein, unter der die Quelldatei gespeichert wird.

L"\u00dc" ist ein wchar_t[] codierte entweder mit UTF-16 oder UTF-32, je nach Definition des Compilers von wchar_t (die 16-Bit-Windows ist, so UTF-16).

u8"\u00dc" ist ein char[] codiert in UTF-8.

u"\u00dc" ist ein char16_t[] in UTF-16 codiert.

U"\u00dc" ist ein char32_t[] codiert in UTF-32.

Das ""s Suffix gibt einfach eine std::string, std::wstring, std::u16string oder std::u32string, je nachdem, ob ein char[], wchar_t[], char16_t[] oder char32_t[] an sie übergeben wird.

Wenn Sie zwei Strings vergleichen, vergewissern Sie sich, dass sie sich zuerst in derselben Codierung befinden. Dies ist besonders wichtig für Ihre char[]/std::string Daten, wie es in einer beliebigen Anzahl von 8-Bit-Codierungen sein könnte, abhängig von den beteiligten Systemen. Dies ist nicht so sehr ein Problem, wenn die App die Strings selbst generiert, aber es ist wichtig, wenn eine oder mehrere Strings von einer externen Quelle kommen (Datei, Benutzereingabe, Netzwerkprotokoll usw.).

In Ihrem Beispiel, "\u00dc" und "Ü" sind nicht unbedingt garantiert, um die gleiche char[] Sequenz zu erzeugen, abhängig davon, wie der Compiler diese verschiedenen Literale interpretiert.Aber selbst wenn sie es taten (was in Ihrem Beispiel der Fall zu sein scheint), wird wahrscheinlich keiner von ihnen UTF-8 produzieren (Sie müssen zusätzliche Maßnahmen ergreifen, um dies zu erzwingen), weshalb Ihr Vergleich mit utf8_encoded_string_s fehlschlägt.

Wenn Sie also ein Zeichenfolgeliteral als UTF-8 erwarten, verwenden Sie , um dies sicherzustellen. Wenn Sie Zeichenkettendaten von einer externen Quelle erhalten und in UTF-8 vorliegen müssen, konvertieren Sie sie so schnell wie möglich in UTF-8, falls noch nicht geschehen (was bedeutet, dass Sie die von der externe Quelle).

+1

'L" \ u00dc "' ist in dem "größten erweiterten Zeichensatz, der unter den unterstützten Gebietsschemata angegeben ist" [basic.fundamental] codiert, der nicht garantiert UTF-16/32 ist (z. B. kann er mit 'LC_CTYPE' variieren) . –