2011-07-22 13 views
10

Możesz napisać ciągi znaków UTF-8/16/32 w C++ 11, poprzedzając literowanie ciągu literami odpowiednio u8/u/U. W jaki sposób kompilator musi interpretować plik UTF-8 zawierający znaki spoza ASCII w tych nowych typach literałów łańcuchowych? Rozumiem, że standard nie określa kodowania plików, a sam ten fakt spowodowałby, że interpretacja znaków spoza ASCII w kodzie źródłowym byłaaby całkowicie niezdefiniowana, co czyni tę funkcję mniej przydatną.W jaki sposób kodowanie plików wpływa na literały ciągów C++ 11?

Rozumiem, że nadal można uciec z pojedynczych znaków Unicode z \uNNNN, ale to nie jest bardzo czytelne, na przykład, w pełnym rosyjskim lub francuskim zdaniu, które zazwyczaj zawierają więcej niż jeden znak Unicode.

Z różnych źródeł rozumiem, że u powinien stać się równoważny z L na obecnych implementacjach Windows i U na przykład Wdrożenia Linuksa. Tak więc biorąc to pod uwagę, jestem też zastanawiać, co wymagane jest zachowanie dla starego smyczkowych dosłownych modyfikatorów ...

Dla małp próbki kodu:

string utf8string a = u8"L'hôtel de ville doit être là-bas. Ça c'est un fait!"; 
string utf16string b = u"L'hôtel de ville doit être là-bas. Ça c'est un fait!"; 
string utf32string c = U"L'hôtel de ville doit être là-bas. Ça c'est un fait!"; 

W idealnym świecie, wszystkie ciągi te wytwarzają tę samą treść (jak w: znaki po konwersji), ale moje doświadczenie z C++ nauczyło mnie, że jest to definitywnie zdefiniowana implementacja i prawdopodobnie tylko pierwsza zrobi to, co chcę.

Odpowiedz

7

W GCC, użyj -finput-charset=charset:

Ustaw zestaw znaków wejścia, używany do tłumaczenia z zestawu znaków pliku wejściowego do zestawu znaków źródło używanego przez GCC. Jeśli ustawienia regionalne nie zostaną określone lub GCC nie może uzyskać tych informacji z ustawień narodowych, domyślną wartością jest UTF-8. Może to być przesłonięte przez ustawienia regionalne lub tę opcję wiersza poleceń. Obecnie opcja wiersza poleceń ma pierwszeństwo w przypadku konfliktu. zestaw znaków może być dowolnym kodowaniem obsługiwanym przez systemową procedurę biblioteki "iconv".

Sprawdź również opcje -fexec-charset i -fwide-exec-charset.

Wreszcie o napisowych:

char  a[] = "Hello"; 
wchar_t b[] = L"Hello"; 
char16_t c[] = u"Hello"; 
char32_t d[] = U"Hello"; 

Modyfikator wielkość łańcuch znaków (L, u, U) określa jedynie typu dosłownego.

+1

Potrzebujesz "const" przed tymi literałami. –

+6

@Nicol Nie. Nawet zakładając, że masz na myśli deklarowane zmienne, nie. –

+2

@Nicol: Dlaczego co kto? 'char x [] =" a "; x [0] = b; ' –

4

W jaki sposób kompilator musi interpretować plik UTF-8 zawierający znaki spoza ASCII w nowych typach literałów łańcuchowych. Rozumiem, że standard nie określa kodowania plików, a sam ten fakt spowodowałby, że interpretacja znaków spoza ASCII w kodzie źródłowym byłaaby całkowicie niezdefiniowana, co czyni tę funkcję mniej przydatną.

Od n3290, 2,2 Fazy tłumaczeniu [lex.phases]

znaków pliku źródłowego fizyczne są odwzorowane, w realizacji zdefiniowanej sposób do podstawowego źródła zestaw znaków (wprowadzenie wczesne wykrywanie chorób znaki linii dla wskaźników końca wiersza), jeśli konieczne jest: .Zbiór zaakceptowanych fizycznych znaków pliku źródłowego to zdefiniowany przez implementację. [Tutaj jest trochę o trigrafach.] Dowolny plik źródłowy o numerze , który nie znajduje się w podstawowym źródłowym zestawie znaków (2.3), jest zastępowany przez nazwę uniwersalnego znaku, który oznacza tę postać. (Implementacja może korzystać z dowolnego wewnętrznego kodowania, o ile w pliku źródłowym występuje rzeczywisty rozszerzony znak i ten sam rozszerzony znak, wyrażony w pliku źródłowym jako uniwersalna nazwa znakowa o numerze (tj. Z użyciem \ uXXXX notacja), są traktowane równoważnie wyjątkiem przypadków, gdy jest to wymiana powrócił w surowego ciąg dosłownym.)

Istnieje wiele terminów standardowych są używane do opisania w jaki sposób oferty wdrożeniowe z kodowania. Oto moja próba jako nieco prostsze, krok po kroku opis tego, co się dzieje:

znaków pliku źródłowego fizyczne są odwzorowane, w realizacji zdefiniowanej sposób na zasadowy charakter źródłowy ustaw [...]

Kwestia kodowania plików jest ręczna; Standard tylko dba o podstawowy zestaw znaków źródłowych i pozostawia miejsce na implementację, aby się tam dostać.

Każdy plik źródłowy postać nie w podstawowym zestawie znaków źródło (2.3) otrzymuje przez znakowy imię uniwersalnego, który wyznacza ten znak.

Podstawowy zestaw źródeł to prosta lista dozwolonych znaków. To nie jest ASCII (patrz dalej). Wszystko, co nie znajduje się na tej liście, jest "przekształcane" (przynajmniej koncepcyjnie) w formularz \uXXXX.

Więc bez względu na to, jaki rodzaj literału lub kodowania pliku jest używany, kod źródłowy jest konceptualnie przekształcany w podstawowy zestaw znaków + pęczek \uXXXX. Mówię konceptualnie, ponieważ to, co faktycznie robią implementacje, jest zwykle prostsze, np. ponieważ mogą obsługiwać Unicode bezpośrednio. Ważną częścią jest to, że to, co Standard wywołuje rozszerzony znak (tj. Nie z podstawowego zestawu źródłowego), powinno być nierozróżnialne w użyciu od równoważnego formularza \uXXXX. Zauważ, że C++ 03 jest dostępny na przykład Platformy EBCDIC, więc twoje rozumowanie w kategoriach ASCII jest wadliwe od samego początku.

Wreszcie, opisany przeze mnie proces dotyczy literałów ciągłych (nieskodowanych). Oznacza to, że kod jest równoważny jakby zostały napisane:

string utf8string a = u8"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!"; 
string utf16string b = u"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!"; 
string utf32string c = U"L'h\u00F4tel de ville doit \u00EAtre l\u00E0-bas. \u00C7a c'est un fait!"; 
+0

To jest interesujące. Czy '\ u00F4' w literale' u8' faktycznie rozszerza się na dwa bajty? –

+0

@Kerrek Przetestowałem na mojej implementacji i '' \ u8XXXX "' może rzeczywiście mieć rozmiar większy niż dwa. Nie zacytowałem tego Standardu, ponieważ nie jestem pewien, gdzie szukać poza "Literał łańcuchowy zaczynający się od u8, na przykład u8" asdf ", jest literałem ciągów UTF-8 i jest inicjowany podanymi znakami jako zakodowane w UTF-8. " (od 2.14.5 Literały do ​​słów [lex.string], paragraf 7). To może być osobne pytanie. –

+1

Nawet słabe 'U + F4' ma już dwa bajty w UTF-8 - to całkiem fajne, nie zdawałem sobie sprawy, że faktycznie istnieje prawdziwa obsługa UTF w nowym C++ (poza dostarczaniem typów danych). Miły! Co dzieje się w 'utf16string', jeśli przekazujesz' \ U0010FFFF'? –

0

W zasadzie pytań kodowania tylko znaczenia, jeśli wyjście struny, czyniąc je widoczne dla ludzi, którym nie jest to kwestia, w jaki sposób programowania język jest zdefiniowany, ponieważ jego definicja dotyczy tylko obliczeń kodowania. Kiedy więc zdecydujesz, czy to, co widzisz w swoim edytorze, będzie takie samo jak to, co widzisz na wyjściu (wszelkiego rodzaju obrazy, czy to na ekranie, czy w pliku PDF), powinieneś zapytać się, którą konwencję sposób, w jaki została zakodowana twoja biblioteka interakcji użytkownika i twój system operacyjny. (Oto na przykład ten rodzaj informacji: for Qt5: z Qt5, co widzisz jako użytkownik aplikacji i to, co widzisz jako programator, pokrywa się, jeśli zawartość staroświeckich literałów łańcuchowych dla twoich QStrings jest zakodowana jako utf8 w plikach źródłowych, chyba że włączysz inne ustawienie podczas wykonywania aplikacji).

Podsumowując, uważam, że Kerrek SB ma rację, a Damon się myli. Rzeczywiście, metody określania literału w kodzie powinny określać jego typ, a nie kodowanie używane w pliku źródłowym do wypełnienia jego kodu. treść, ponieważ typ literału dotyczy przetwarzania danych. Coś takiego jak u"string" jest po prostu tablicą "unicode codeunits" (to jest wartości typu char16_t), niezależnie od tego, czy system operacyjny, czy jakikolwiek inny program serwisowy robi to później, a ich praca będzie wyglądać dla ciebie lub dla innego użytkownika. Dochodzisz tylko do problemu dodania sobie innej konwencji, która tworzy powiązanie między "znaczeniem" liczb w obliczeniach (a mianowicie, przedstawia kody Unicode) i ich reprezentacją na ekranie podczas pracy w edytorze tekstu . Jak i czy jako programista używasz tego "znaczenia", to jest inne pytanie i jak możesz wymusić tę drugą korespondencję, naturalnie zostanie zdefiniowana implementacja, ponieważ nie ma ona nic wspólnego z obliczaniem kodu, tylko z komfortem użycia narzędzia .

Powiązane problemy