Nie jestem w stanie zrozumieć różnic między std::string
i std::wstring
. Wiem, że wstring
obsługuje szerokie znaki, takie jak znaki Unicode. Mam następujące pytania:
- Kiedy należy używać
std::wstring
w ciągustd::string
? - Czy
std::string
pomieści cały zestaw znaków ASCII, w tym znaki specjalne? - Czy jest
std::wstring
obsługiwany przez wszystkie popularne kompilatory C ++? - Czym jest dokładnie „ szeroki charakter ”?
Odpowiedzi:
string
?wstring
?std::string
jestbasic_string
szablonem nachar
istd::wstring
nawchar_t
.char
vs.wchar_t
char
ma zawierać postać, zwykle 8-bitową.wchar_t
ma mieć szeroki znak, a potem sprawy stają się trudne: wLinuksie a
wchar_t
ma 4 bajty, podczas gdy w Windowsie ma 2 bajty.Co zatem z Unicode ?
Problem polega na tym, że ani
char
ani niewchar_t
jest bezpośrednio związany z Unicode.W systemie Linux?
Weźmy Linux OS: Mój system Ubuntu jest już świadomy Unicode. Kiedy pracuję z ciągiem znaków, jest on natywnie kodowany w UTF-8 (tj. Ciąg znaków Unicode). Poniższy kod:
wyświetla następujący tekst:
Zobaczysz, że tekst „olé”
char
jest w rzeczywistości zbudowany z czterech znaków: 110, 108, 195 i 169 (nie licząc końcowego zera). (Pozwolę ci przestudiowaćwchar_t
kod jako ćwiczenie)Tak więc, pracując z
char
Linuksem, zwykle powinieneś używać Unicode, nawet o tym nie wiedząc. I jakstd::string
działachar
,std::string
jest już gotowy na Unicode.Zauważ, że
std::string
podobnie jak interfejs API łańcucha C, łańcuch „olé” będzie traktował 4 znaki, a nie trzy. Dlatego należy zachować ostrożność podczas obcinania / gry znakami Unicode, ponieważ niektóre kombinacje znaków są zabronione w UTF-8.W systemie Windows?
W systemie Windows jest to nieco inne. Przed pojawieniem się Unicode Win32 musiał obsługiwać wiele aplikacji współpracujących z
char
różnymi zestawami znaków i stronami kodowymi produkowanymi na całym świecie.Ich rozwiązanie było więc interesujące: jeśli aplikacja współpracuje
char
, łańcuchy znaków są kodowane / drukowane / wyświetlane na etykietach GUI przy użyciu lokalnego zestawu znaków / strony kodowej na komputerze. Na przykład „olé” byłoby „olé” w systemie Windows zlokalizowanym we Francji, ale byłoby czymś innym w systemie Windows zlokalizowanym w cyrylicy („olé”, jeśli używasz Windows-1251 ). Dlatego „aplikacje historyczne” zwykle będą nadal działać w ten sam stary sposób.W przypadku aplikacji opartych na Unicode, Windows używa
wchar_t
2-bajtowej szerokości i jest zakodowany w UTF-16 , który jest Unicode zakodowany na 2-bajtowych znakach (lub przynajmniej w większości kompatybilnym UCS-2, który jest prawie to samo IIRC).Używające aplikacje
char
są nazywane „wielobajtowymi” (ponieważ każdy glif składa się z jednego lub więcejchar
s), podczas gdy aplikacje używającewchar_t
są nazywane „widechar” (ponieważ każdy glif składa się z jednego lub dwóchwchar_t
. Zobacz API konwersji MultiByteToWideChar i WideCharToMultiByte Win32, aby uzyskać więcej informacji.Tak więc, jeśli pracujesz w systemie Windows, bardzo chcesz go używać
wchar_t
(chyba że używasz frameworku, który to ukrywa, np. GTK + lub QT ...). Faktem jest, że za kulisami system Windows działa zwchar_t
ciągami, więc nawet aplikacje historyczne będą miałychar
przekonwertowane ciągiwchar_t
podczas korzystania z interfejsu API podobnegoSetWindowText()
(funkcja API niskiego poziomu do ustawiania etykiety w interfejsie GUI Win32).Problemy z pamięcią?
UTF-32 ma 4 bajty na znak, więc nie ma wiele do dodania, choćby tylko tekst UTF-8 i tekst UTF-16 zawsze zużywały mniej lub tyle samo pamięci niż tekst UTF-32 (i zwykle mniej ).
Jeśli występuje problem z pamięcią, powinieneś wiedzieć, że w przypadku większości języków zachodnich tekst UTF-8 zużyje mniej pamięci niż ten sam język UTF-16.
Jednak w przypadku innych języków (chiński, japoński itp.) Używana pamięć będzie taka sama lub nieco większa dla UTF-8 niż dla UTF-16.
Podsumowując, UTF-16 zużywa głównie 2, a czasami 4 bajty na znaki (chyba że masz do czynienia z jakimś ezoterycznym glifem języka (Klingon? Elvish?), Podczas gdy UTF-8 wyda od 1 do 4 bajtów.
Zobacz http://en.wikipedia.org/wiki/UTF-8#Compared_to_UTF-16, aby uzyskać więcej informacji.
Wniosek
Kiedy powinienem używać std :: wstring zamiast std :: string?
W systemie Linux? Prawie nigdy (§).
W systemie Windows? Prawie zawsze (§).
Na kodzie międzyplatformowym? Zależy od zestawu narzędzi ...
(§): chyba że używasz zestawu narzędzi / frameworku, który mówi inaczej
Czy
std::string
pomieści cały zestaw znaków ASCII, w tym znaki specjalne?Uwaga: A
std::string
nadaje się do przechowywania bufora „binarnego”, gdziestd::wstring
nie ma!W systemie Linux? Tak.
W systemie Windows? Dostępne są tylko znaki specjalne dla bieżących ustawień regionalnych użytkownika systemu Windows.
Edit (po komentarzu od Johann Gerell ): będzie wystarczająco, aby obsłużyć wszystkie sznurki opartych (każdy jest liczbą od 0 do 255). Ale:
std::string
char
char
char
NIE są ASCII.char
od 0 do 127 odbędzie się prawidłowochar
od 128 do 255 będzie miało znaczenie w zależności od twojego kodowania (Unicode, non-Unicode itp.), ale będzie w stanie pomieścić wszystkie glify Unicode, o ile są one zakodowane w UTF-8.Jest
std::wstring
obsługiwany przez prawie wszystkie popularne kompilatory C ++?Głównie, z wyjątkiem kompilatorów opartych na GCC, które są portowane w systemie Windows.
Działa na moim g ++ 4.3.2 (pod Linuksem), a ja użyłem Unicode API w Win32 od Visual C ++ 6.
Jaka jest dokładnie szeroka postać?
W C / C ++ jest to napisany typ znaków,
wchar_t
który jest większy niż prostychar
typ znaków. Powinien być używany do wstawiania znaków, których indeksy (takie jak glify Unicode) są większe niż 255 (lub 127, zależnie od ...).źródło
olè
kodowane jest jako UTF-8, czy nie. Co więcej, powód nie może natywnie strumieniowowchar_t *
dostd::cout
dlatego, że typy są niezgodne skutkuje źle utworzonego programu i to nie ma nic wspólnego z wykorzystaniem kodowania. Warto podkreślić, że to, czy używaszstd::string
lubstd::wstring
zależy od własnych preferencji kodowania zamiast platformy, zwłaszcza, jeśli chcesz, aby Twój kod być przenośne.std::wstring
powinien być stosowany w systemie Windows, ponieważ lepiej pasuje do interfejsu Windows Unicode API, który moim zdaniem jest błędny. Jeśli Twoim jedynym zmartwieniem było wywoływanie interfejsu API systemu Windows w standardzie Unicode, a nie zbieranie ciągów, to na pewno, ale nie kupuję tego jako ogólnej sprawy.If your only concern was calling into the Unicode Windows API and not marshalling strings then sure
Zgadzamy się. Piszę w C ++, a nie JavaScript. Unikanie zbędnego gromadzenia danych lub innego potencjalnie kosztownego przetwarzania w czasie wykonywania, gdy można tego dokonać w czasie kompilacji, jest sercem tego języka. Kodowanie w oparciu o WinAPI i używaniestd::string
to tylko nieuzasadnione marnowanie zasobów środowiska wykonawczego. Uważasz to za błędne i jest w porządku, ponieważ jest to twój punkt widzenia. Po swojemu nie piszę kodu z pesymizacją w systemie Windows tylko dlatego, że wygląda lepiej od strony Linuksa.Zalecam unikanie
std::wstring
w systemie Windows lub gdzie indziej, z wyjątkiem sytuacji, gdy wymaga tego interfejs lub gdziekolwiek w pobliżu wywołań interfejsu API systemu Windows i odpowiednich konwersji kodowania jako cukru syntaktycznego.Mój pogląd został streszczony na stronie http://utf8everywhere.org, której jestem współautorem.
O ile twoja aplikacja nie jest API-call-centric, np. Głównie aplikacja UI, sugeruje się przechowywanie ciągów Unicode w std :: string i kodowanych w UTF-8, wykonując konwersję w pobliżu wywołań API. Korzyści przedstawione w artykule przewyższają pozorną irytację konwersji, szczególnie w złożonych aplikacjach. Dzieje się tak podwójnie w przypadku rozwoju wielu platform i bibliotek.
A teraz odpowiadając na twoje pytania:
źródło
Tak więc każdy czytelnik tutaj powinien mieć jasne zrozumienie faktów i sytuacji. Jeśli nie, musisz przeczytać niezwykle wyczerpującą odpowiedź paercebala [btw: dzięki!].
Mój pragmatyczny wniosek jest szokująco prosty: wszystkie te „kodujące” znaki C ++ (i STL) są w znacznym stopniu zepsute i bezużyteczne. Obwiniaj to Microsoft, czy nie, to i tak nie pomoże.
Moje rozwiązanie, po dogłębnym badaniu, dużej frustracji i związanych z tym doświadczeniach, jest następujące:
zaakceptuj, że musisz samodzielnie ponosić odpowiedzialność za kodowanie i konwersję (i zobaczysz, że większość z nich jest dość trywialna)
użyj std :: string dla dowolnych łańcuchów kodowanych w UTF-8 (tylko a
typedef std::string UTF8String
)zaakceptować, że taki obiekt UTF8String to tylko głupi, ale tani kontener. Nigdy nie otwieraj i / lub nie manipuluj bezpośrednio w nim znakami (bez wyszukiwania, zamiany itp.). Możesz, ale naprawdę, naprawdę, nie chcesz tracić czasu na pisanie algorytmów manipulacji tekstem dla ciągów wielobajtowych! Nawet jeśli inni ludzie robili już takie głupie rzeczy, nie rób tego! Niech będzie! (Cóż, istnieją scenariusze, w których ma to sens ... wystarczy użyć biblioteki ICU).
użyj std :: wstring dla łańcuchów zakodowanych w UCS-2 (
typedef std::wstring UCS2String
) - jest to kompromis i ustępstwo w stosunku do bałaganu wprowadzonego przez interfejs API WIN32). UCS-2 jest wystarczający dla większości z nas (więcej o tym później ...).używaj instancji UCS2String, ilekroć wymagany jest dostęp znak po znaku (czytaj, manipuluj itd.). Wszelkie przetwarzanie oparte na znakach powinno odbywać się w reprezentacji innej niż wielobajtowa. To jest proste, szybkie, łatwe.
dodaj dwie funkcje narzędziowe do konwersji w obie strony między UTF-8 i UCS-2:
Konwersje są proste, Google powinien tutaj pomóc ...
Otóż to. Używaj UTF8String wszędzie tam, gdzie cenna jest pamięć i dla wszystkich I / O UTF-8. Użyj UCS2String wszędzie tam, gdzie ciąg musi zostać przeanalizowany i / lub zmanipulowany. Możesz konwertować między tymi dwoma reprezentacjami w dowolnym momencie.
Alternatywy i ulepszenia
konwersje z & na jednobajtowe kodowanie znaków (np. ISO-8859-1) można zrealizować za pomocą zwykłych tabel translacji, np.
const wchar_t tt_iso88951[256] = {0,1,2,...};
i odpowiedniego kodu do konwersji do i z UCS2.jeśli UCS-2 nie jest wystarczający, przełącz się na UCS-4 (
typedef std::basic_string<uint32_t> UCS2String
)ICU lub inne biblioteki Unicode?
Dla zaawansowanych rzeczy.
źródło
Gdy chcesz mieć szerokie znaki w swoim ciągu.
wide
zależy od wdrożenia. Domyślnie Visual C ++ to 16 bitów, jeśli dobrze pamiętam, podczas gdy GCC domyślnie w zależności od celu. Ma tutaj 32 bity. Uwaga: wchar_t (szeroki typ znaków) nie ma nic wspólnego z Unicode. Jest tylko zagwarantowane, że może przechowywać wszystkich członków największego zestawu znaków obsługiwanego przez implementację przez jej ustawienia regionalne, a przynajmniej tak długo, jak char. Możesz również zapisać łańcuchy Unicode, abystd::string
używaćutf-8
kodowania. Ale nie zrozumie znaczenia punktów kodu Unicode. Więcstr.size()
nie da ci ilości logicznych znaków w twoim ciągu, ale jedynie ilość elementów char lub wchar_t przechowywanych w tym ciągu / łańcuchu. Z tego powodu ludzie korzystający z pakietu C ++ gtk / glib opracowaliGlib::ustring
klasę, która może obsługiwać utf-8.Jeśli twój wchar_t ma 32 bity, możesz użyć go
utf-32
jako kodowania Unicode, a także możesz przechowywać i obsługiwać ciągi Unicode za pomocą stałego kodowania (utf-32 ma stałą długość). Oznacza to, że funkcja twojego ciągus.size()
zwróci następnie odpowiednią liczbę elementów wchar_t i znaków logicznych.źródło
std::wstring
.Często używam std :: string do przechowywania znaków utf-8 bez żadnych problemów. Polecam to zrobić w przypadku interfejsów API, które używają utf-8 jako rodzimego typu łańcucha.
Na przykład używam utf-8 podczas łączenia mojego kodu z interpreterem Tcl.
Głównym zastrzeżeniem jest długość std :: string, nie jest to już liczba znaków w ciągu.
źródło
źródło
źródło
Aplikacje, które nie są usatysfakcjonowane tylko 256 różnymi znakami, mają opcje użycia szerokich znaków (więcej niż 8 bitów) lub kodowania o zmiennej długości (kodowanie wielobajtowe w terminologii C ++), takiego jak UTF-8. Szerokie znaki zwykle wymagają więcej miejsca niż kodowanie o zmiennej długości, ale ich przetwarzanie jest szybsze. Aplikacje wielojęzyczne przetwarzające duże ilości tekstu zwykle używają szerokich znaków podczas przetwarzania tekstu, ale konwertują go na UTF-8 podczas przechowywania na dysku.
Jedyną różnicą między a
string
i awstring
jest typ danych przechowywanych znaków. Ciąg znaków przechowujechar
s, których rozmiar gwarantuje co najmniej 8 bitów, więc możesz używać ciągów do przetwarzania np. Tekstu ASCII, ISO-8859-15 lub UTF-8. Standard nie mówi nic o zestawie znaków ani kodowaniu.Praktycznie każdy kompilator używa zestawu znaków, którego pierwsze 128 znaków odpowiada ASCII. Dotyczy to również kompilatorów korzystających z kodowania UTF-8. Ważną rzeczą, o której należy pamiętać, używając ciągów znaków w UTF-8 lub innym kodowaniu o zmiennej długości, jest to, że wskaźniki i długości są mierzone w bajtach, a nie znakach.
Typ danych ciągu jest taki
wchar_t
, którego rozmiar nie jest zdefiniowany w standardzie, z tym wyjątkiem, że musi on być co najmniej tak duży jak znak, zwykle 16 bitów lub 32 bity. Wstring może być wykorzystywany do przetwarzania tekstu w kodowaniu szerokopasmowym zdefiniowanym przez implementację. Ponieważ kodowanie nie jest zdefiniowane w standardzie, konwersja między łańcuchami i łańcuchami nie jest prosta. Nie można również zakładać, że łańcuchy mają kodowanie o stałej długości.Jeśli nie potrzebujesz obsługi wielu języków, możesz używać tylko zwykłych ciągów znaków. Z drugiej strony, jeśli piszesz aplikację graficzną, często zdarza się, że API obsługuje tylko szerokie znaki. Wtedy prawdopodobnie będziesz chciał użyć tych samych szerokich znaków podczas przetwarzania tekstu. Pamiętaj, że UTF-16 jest kodowaniem o zmiennej długości, co oznacza, że nie możesz założyć,
length()
że zwrócisz liczbę znaków. Jeśli interfejs API używa kodowania o stałej długości, takiego jak UCS-2, przetwarzanie staje się łatwe. Konwersja szerokich znaków i UTF-8 jest trudna w przenośny sposób, ale z drugiej strony interfejs API interfejsu użytkownika prawdopodobnie obsługuje konwersję.źródło
Dobre pytanie! Myślę, że KODOWANIE DANYCH (czasami także CHARSET ) to MECHANIZM WYRAŻANIA PAMIĘCI w celu zapisania danych do pliku lub przesłania danych przez sieć, dlatego odpowiadam na to pytanie jako:
1. Kiedy powinienem używać std :: wstring zamiast std :: string?
Jeśli platforma programistyczna lub funkcja API jest jednobajtowa i chcemy przetwarzać lub analizować niektóre dane Unicode, np. Odczytane z pliku Windows'.REG lub sieciowego 2-bajtowego strumienia, powinniśmy zadeklarować zmienną std :: wstring, aby łatwo przetwarzaj je. np .: wstring ws = L "中国 a" (pamięć 6 oktetów: 0x4E2D 0x56FD 0x0061), możemy użyć ws [0], aby uzyskać znak „中” i ws [1], aby uzyskać znak „国”, a ws [2] do zdobądź znak „a” itp.
2. Czy std :: string może przechowywać cały zestaw znaków ASCII, w tym znaki specjalne?
Tak. Ale zauważ: amerykański ASCII oznacza, że każdy oktet 0x00 ~ 0xFF oznacza jeden znak, w tym tekst do wydrukowania, taki jak „123abc & * _ &”, i powiedziałeś, że specjalny, najczęściej drukuj go jako „.” unikaj mylących edytorów lub terminali. A niektóre inne kraje rozszerzają swój własny zestaw znaków „ASCII”, np. Chiński, używają 2 oktetów, aby zastąpić jedną postać.
3.Czy std :: wstring jest obsługiwany przez wszystkie popularne kompilatory C ++?
Może lub głównie. Użyłem: VC ++ 6 i GCC 3.3, TAK
4. Czym dokładnie jest „szeroki charakter”?
szeroki znak oznacza najczęściej użycie 2 lub 4 oktetów do przechowywania znaków wszystkich krajów. 2 oktet UCS2 jest reprezentatywną próbką, a ponadto np. Angielski „a”, jego pamięć to 2 oktety 0x0061 (w porównaniu do ASCII „a pamięć to 1 oktet 0x61)
źródło
Jest tu kilka bardzo dobrych odpowiedzi, ale myślę, że mogę dodać kilka rzeczy dotyczących Windows / Visual Studio. To jest oparte na moich doświadczeniach z VS2015. W Linuksie w zasadzie odpowiedzią jest używanie
std::string
wszędzie zakodowanych w UTF-8 . W systemie Windows / VS staje się bardziej złożony. Oto dlaczego. System Windows oczekuje, że ciągi przechowywane przy użyciuchar
s zostaną zakodowane przy użyciu lokalnej strony kodowej. Jest to prawie zawsze zestaw znaków ASCII, po którym następuje 128 innych znaków specjalnych, w zależności od lokalizacji. Pozwolę sobie tylko stwierdzić, że nie tylko przy korzystaniu z Windows API, istnieją trzy inne główne miejsca, w których te ciągi wchodzą w interakcje ze standardowym C ++. Są to literały łańcuchowe, dane wyjściowe dostd::cout
używania<<
i przekazywania nazwy plikustd::fstream
.Będę tutaj z góry, że jestem programistą, a nie specjalistą od języków. Rozumiem, że USC2 i UTF-16 nie są takie same, ale dla moich celów są wystarczająco blisko, aby były wymienne i używam ich jako takich tutaj. Nie jestem pewien, którego systemu Windows używa, ale generalnie nie muszę też wiedzieć. W tej odpowiedzi podałem UCS2, więc z góry przepraszam, jeśli zdenerwowałem kogoś swoją niewiedzą w tej sprawie i cieszę się, że mogę go zmienić, jeśli coś jest nie tak.
Literały łańcuchowe
Jeśli wpiszesz literały łańcuchowe zawierające tylko znaki, które mogą być reprezentowane przez twoją stronę kodową, VS zapisze je w twoim pliku z 1 bajtem na kodowanie znaków na podstawie twojej strony kodowej. Zauważ, że jeśli zmienisz stronę kodową lub przekażesz swoje źródło innemu programistowi, używając innej strony kodowej, to myślę (ale nie przetestowałem), że znak skończy się inaczej. Jeśli uruchomisz kod na komputerze przy użyciu innej strony kodowej, nie jestem pewien, czy znak również się zmieni.
Jeśli wpiszesz literały ciągów, które nie mogą być reprezentowane przez twoją stronę kodową, VS poprosi cię o zapisanie pliku jako Unicode. Plik zostanie następnie zakodowany jako UTF-8. Oznacza to, że wszystkie znaki spoza ASCII (w tym te, które znajdują się na stronie kodowej) będą reprezentowane przez 2 lub więcej bajtów. Oznacza to, że jeśli podasz swoje źródło komuś innemu, źródło będzie wyglądać tak samo. Jednak przed przekazaniem źródła do kompilatora VS konwertuje tekst zakodowany w UTF-8 na tekst zakodowany na stronie kodowej, a wszelkie znaki brakujące na stronie kodowej są zastępowane przez
?
.Jedynym sposobem, aby zagwarantować prawidłowe odwzorowanie literału ciągów Unicode w VS, jest poprzedzenie literału ciągów literą
L
szeroką. W takim przypadku VS skonwertuje tekst zakodowany w UTF-8 z pliku na UCS2. Następnie musisz przekazać dosłowny ciąg znaków dostd::wstring
konstruktora lub przekonwertować go na utf-8 i umieścić w plikustd::string
. Lub jeśli chcesz, możesz użyć funkcji Windows API do zakodowania go za pomocą strony kodowej, aby umieścić go wstd::string
, ale równie dobrze możesz nie użyć szerokiego ciągu literałów.std :: cout
Podczas wysyłania do konsoli za pomocą
<<
możesz używać tylkostd::string
,std::wstring
a nie, a tekst musi być zakodowany przy użyciu lokalnej strony kodowej. Jeśli takstd::wstring
, musisz go przekonwertować za pomocą jednej z funkcji Windows API, a wszelkie znaki spoza twojej strony kodowej zostaną zastąpione przez?
(być może możesz zmienić znak, nie pamiętam).std :: nazwy plików fstream
System operacyjny Windows używa UCS2 / UTF-16 dla swoich nazw plików, więc bez względu na stronę kodową możesz mieć pliki o dowolnym znaku Unicode. Oznacza to jednak, że aby uzyskać dostęp do plików ze znakami spoza strony kodowej lub tworzyć je, musisz ich użyć
std::wstring
. Nie ma innego wyjścia. Jest to rozszerzenie specyficzne dla Microsoft,std::fstream
więc prawdopodobnie nie będzie się kompilowało w innych systemach. Jeśli używasz std :: string, możesz używać tylko nazw plików zawierających tylko znaki na stronie kodowej.Twoje opcje
Jeśli pracujesz tylko w systemie Linux, prawdopodobnie nie zaszedłeś tak daleko. Po prostu użyj UTF-8
std::string
wszędzie.Jeśli pracujesz tylko w systemie Windows, użyj UCS2
std::wstring
wszędzie. Niektórzy puriści mogą powiedzieć, że używają UTF8, a następnie konwertują w razie potrzeby, ale po co zawracać sobie głowę kłopotami.Jeśli jesteś wieloplatformowy, to szczerze mówiąc, to bałagan. Jeśli próbujesz używać UTF-8 wszędzie w systemie Windows, musisz być bardzo ostrożny z literałami ciągów i przesyłaniem ich do konsoli. Możesz łatwo zepsuć tam swoje łańcuchy. Jeśli używasz
std::wstring
wszędzie w systemie Linux, możesz nie mieć dostępu do szerokiej wersjistd::fstream
, więc musisz wykonać konwersję, ale nie ma ryzyka uszkodzenia. Więc osobiście uważam, że jest to lepsza opcja. Wielu by się nie zgodziło, ale nie jestem sam - jest to ścieżka podana na przykład przez wxWidgets.Inną opcją może być wpisanieef
unicodestring
jakstd::string
w Linuksie istd::wstring
Windowsie i posiadanie makra o nazwie UNI (), które ma prefiks L w Windows i nic w Linuksie, a następnie kodmyślę, że byłoby dobrze na każdej platformie.
Odpowiedzi
Aby odpowiedzieć na twoje pytania
1) Jeśli programujesz dla systemu Windows, to cały czas, jeśli masz wiele platform, to może cały czas, chyba że chcesz poradzić sobie z możliwymi problemami z korupcją w systemie Windows lub napisać kod z konkretną platformą
#ifdefs
aby obejść różnice, jeśli tylko używasz Linux wtedy nigdy.2) Tak. Ponadto w systemie Linux możesz używać go również do wszystkich znaków Unicode. W systemie Windows możesz go używać tylko dla wszystkich kodów Unicode, jeśli wybierzesz ręczne kodowanie przy użyciu UTF-8. Ale interfejs API systemu Windows i standardowe klasy C ++ będą oczekiwać
std::string
kodowania przy użyciu lokalnej strony kodowej. Obejmuje to wszystkie znaki ASCII oraz kolejne 128 znaków, które zmieniają się w zależności od strony kodowej, z której komputer ma korzystać.3) Uważam, że tak, ale jeśli nie, to jest to po prostu zwykła czcionka „std :: basic_string” używająca
wchar_t
zamiastchar
4) Szeroki znak to typ znaku, który jest większy niż standardowy 1-bajtowy
char
typ. W systemie Windows jest to 2 bajty, w systemie Linux - 4 bajty.źródło
/utf-8
) UTF-8 .1) Jak wspomniał Greg, wstring jest pomocny w internacjonalizacji, wtedy wydasz swój produkt w językach innych niż angielski
4) Sprawdź to, aby zobaczyć szeroką postać http://en.wikipedia.org/wiki/Wide_character
źródło
Kiedy NIE powinieneś używać szerokich znaków?
Kiedy piszesz kod przed rokiem 1990.
Oczywiście jestem przerzucany, ale tak naprawdę to jest teraz 21 wiek. 127 znaków już dawno przestało wystarczać. Tak, możesz użyć UTF8, ale po co męczyć się z bólami głowy?
źródło
wchar_t
polega na tym, że jego rozmiar i znaczenie zależą od systemu operacyjnego. Po prostu zamienia stare problemy na nowe. Natomiast achar
jestchar
niezależnym od systemu operacyjnego (przynajmniej na podobnych platformach). Więc równie dobrze możemy po prostu użyć UTF-8, spakować wszystko w sekwencjechar
s i lamentować, że C ++ pozostawia nas całkowicie samodzielnie bez żadnych standardowych metod pomiaru, indeksowania, znajdowania itp. W takich sekwencjach.wchar_t
jest typem danych o stałej szerokości, więc tablica 10wchar_t
zawsze będzie zajmowaćsizeof(wchar_t) * 10
bajty platformy. A UTF-16 jest kodowaniem o zmiennej szerokości, w którym znaki mogą składać się z 1 lub 2 16-bitowych punktów kodowych (i s / 16/8 / g dla UTF-8).