2011-12-14 12 views
10

Aby dowiedzieć się, czy C++ jest właściwym językiem dla mojego projektu, chcę przetestować możliwości UTF-8. Według referencji, zbudowałem ten przykład:Obsługa UTF-8 w C++

#include <string> 
#include <iostream> 

using namespace std; 

int main() { 
    wstring str; 
    while(getline(wcin, str)) { 
     wcout << str << endl; 
     if(str.empty()) break; 
    } 

    return 0; 
} 

Ale kiedy wpisuję w UTF-8 znaków, to misbehaves:

$ > ./utf8 
Hello 
Hello 
für 
f 
$ > 

Nie tylko nie wydrukować ü, ale również zamykany natychmiast. gdb powiedział mi, że nie było awarii, ale normalne wyjście, ale trudno mi w to uwierzyć.

+0

Którą platformą kierujesz (Windows, Linux itp.)? –

+0

Linux, faktycznie. Jeśli działa również na windows, jest to swego rodzaju bonus. – Lanbo

+2

Czy Twój język ustawiony jest na kodowanie UTF-8? –

Odpowiedz

8

Nie używaj wstring w systemie Linux.

std::wstring VS std::string

Spójrz na pierwszej odpowiedzi. Jestem pewien, że odpowiada na twoje pytanie.

  1. Kiedy należy używać std :: wstring nad std :: string?

W systemie Linux? Prawie nigdy (§).

W systemie Windows? Prawie zawsze (§).

+0

+1: Spójrz na tę odpowiedź. Jestem pewien, że zawiera on link do odpowiedzi na twoje pytanie. – Klaim

+0

W komentarzach 'boost :: spirit' na UTF-8 zawsze mówią o użyciu' wchar_t'. – Lanbo

+0

@ Scán: Sądzę, że używają 'wchar_t' przez cały czas dla punktów kodowych, używanych podczas tłumaczenia UTF8 na i od czegokolwiek. 'wchar_t' nie jest jednak dobrym znakiem dla samego UTF8. –

7

Sam język nie ma nic wspólnego z kodowaniem znaków Unicode lub innych znaków. Jest związany z systemem operacyjnym. Windows używa UTF16 do obsługi Unicode, co implikuje użycie szerokich znaków (16-bitowych znaków) - wchar_t lub std: wstring. Każda funkcja Win Api działająca z ciągami wymaga szerokiego wejścia char.

Ale systemy oparte na Uniksie, np. Mac OS X lub Linux, używają UTF8. Oczywiście - chodzi tylko o to, jak sobie poradzisz z bajtami w tablicy, więc możesz mieć ciąg znaków UTF16 przechowywany we wspólnym C tablicy lub std: ciąg znaków. Dlatego nie widać żadnych znaków w kodzie między platformami; zamiast tego wszystkie ciągi są traktowane jako UTF8 i ponownie zakodowane w razie potrzeby do UTF16 (w oknach).

Masz więcej opcji, jak sobie z tym poradzić. Osobiście robię to, o czym wspominałem wcześniej - ściśle używając kodowania UTF8 we wszystkich aplikacjach, ponownie kodując ciągi podczas interakcji z Windows Api i bezpośrednio używając ich na Mac OS X. Do ponownego kodowania wygranych używam świetnych pomocników konwersji:

C++ UTF-8 Conversion Helpers (w witrynie MSDN, dostępne na licencji Apache w wersji 2.0).

Można również użyć wieloplatformowego ciągu Qt, który definiuje funkcje konwersji z UTF8 do/z UTF16 i innych kodowań (ANSI, Latin ...).

Tak więc powyższa odpowiedź - w systemie Unix używa zawsze UTF8 (std :: string, char), na Windows UTF16 (std :: wstring, wchar_t) jest prawdziwa.

+0

Co zatem powinienem zrobić, gdy chcę utworzyć kompilator/interpreter językowy, który traktuje wszystko jako UTF-8 w obu systemach? – Lanbo

+0

Cóż, nie ma prostej odpowiedzi i "ostatecznego" rozwiązania. To zależy od kompilatorów, IDE i interfejsów API, z których korzystasz. Polecam Ci korzystanie z platformy między platformami, najlepiej Qt firmy Nokia - http://qt.nokia.com. Jest to całkowicie darmowy dla projektów open source, a nawet dla tych dostawczych - jeśli zapewnienia zgodności z GNU General Public License (LGPL). – vitakot

3

Należy pamiętać, że po uruchomieniu programu głównego domyślnie wybrane jest ustawienie "C". Prawdopodobnie nie chcesz tego, jeśli zajmujesz się utf-8. Wywołanie setlocale(LC_CTYPE, "") powoduje wyłączenie tej wartości domyślnej, a otrzymasz wszystko, co jest zdefiniowane w środowisku (prawdopodobnie ustawienie lokalne utf-8).

+1

Tak! W przeciwieństwie do innych odpowiedzi, używanie 'wchar_t' w Linuksie jest całkowicie OK. Musisz jednak koniecznie użyć właściwego ustawienia narodowego. –