Portál AbcLinuxu, 25. dubna 2024 18:57


Dotaz: C/C++ podpora UTF-8, jak to funguje?

11.11.2011 23:26 Jarda
C/C++ podpora UTF-8, jak to funguje?
Přečteno: 1379×
Odpovědět | Admin
Zdravím, nerozumím následující věci, popíšu příklad...

Mám zdroják v C, který zobrazí znak 'Ω', tj. Unicode Character 'OHM SIGN' (U+2126).

#include <stdio.h>
#include <wchar.h>
#include <locale.h>
 
int main() {
  setlocale(LC_ALL,"");
  wchar_t myChar1 = L'Ω';
  wchar_t myChar2 = 0x2126;  // hexadecimal encoding of char Ω using UTF-16
  wchar_t myChar3 = L'\xe2\x84\xa6';

  wprintf(L"%lc \n", myChar1);
  wprintf(L"%lc \n", myChar2);
  wprintf(L"%lc \n", myChar3); 

  return 0;
}

Zdroják je na disku uložen v souboru jako UTF-8, tj. znak 'Ω' je v něm jako 0xe2 0x84 0xa6. Ovšem pokud ho chci zapsat v C jako posloupnost bytů tak musím přes UTF-16 (\u2126), já bych ho chtěl ale zapsat jako UTF-8, jako posloupnost těch 3 bytů myChar3.

Z mého pohledu se hodnota u myChar1 a myChar3 zdá stejná (jen trochu jinak zapsaná), ale ve výsledku není, poslední wprintf vypíše znak '¦', tj. \u00a6 neboli UTF-8 0xC2 0xA6.

No jsem z toho nějakej zblblej, používám gcc version 4.6.1 20110908 a glibc-2.14-5.x86_64 :D

Když si v bashi dám echo -e "\xe2\x84\xa6\u2126", tak to na obrazovku normálně vypíše ΩΩ.
Nástroje: Začni sledovat (2) ?Zašle upozornění na váš email při vložení nového komentáře.

Odpovědi

12.11.2011 00:15 l4m4
Rozbalit Rozbalit vše Re: C/C++ podpora UTF-8, jak to funguje?
Odpovědět | | Sbalit | Link | Blokovat | Admin
wchar_t není UTF-8.

UTF-8 je representace znaků Unicode pomocí různě dlouhých sekvencí bajtů.

wchar_t je nějaký blíže nespecifikovaný platformově závislý vícebytový typ v C. Na MS Windows 16bitový integer (representující UCS-2), na Unixu spíš 32bitový integer (representující UCS-4), taky to ale klidně může být něco ještě podivnějšího, a Unicode Consortium nedoporučuje to používat kvůli přenositelnosti.

Takže běžnější (alespoň na Uninxu; na MS Windows platformová závislost málokoho trápí, když jejich veškerá platforma je MS Windows) je represntovat Unicode řetězce pomocí char v UTF-8, přičemž potom samozřejmě je rozdíl mezi znaky a bajty, protože znak může být více bajtů. Tvoje oblíbená knihovna/framework určitě má funkce pro práci s UTF-8 kódovanými řetězci, tudíž zapisuješ zdroják přímo v UTF-8 (vyžaduje, aby 8bitové znaky bral kompilátor, dnes už nebývá problém) a používáš příslušné UTF-8 (ne wide-char!) funkce.
12.11.2011 02:35 Michal Kubeček | skóre: 72 | Luštěnice
Rozbalit Rozbalit vše Re: C/C++ podpora UTF-8, jak to funguje?
Druhou možností je převést UTF-8 na tu interní reprezentaci, s tou pracovat interně a před uložením zase konvertovat zpátky. To se hodí hlavně tam, kde by proměnná délka znaku příliš komplikovala život a naopak nevadí větší spotřeba paměti. V C na to lze použít např. funkce mbsrtowcs() a wcsrtombs(), v C++ se přiřadí locale I/O streamu (metoda imbue()).
12.11.2011 12:55 petr_p | skóre: 59 | blog: pb
Rozbalit Rozbalit vše Re: C/C++ podpora UTF-8, jak to funguje?
Na druhou stranu wchar_t podle ISO C99 musí splňovat podmínku, že pojme libovolný znak z libovolného locale podporovaného danou implementaci standardní knihovny. A navíc jediný způsob, jak (pomocí standardní knihovny) zjistit zobrazovanou šířku znaku (0 sloupců pro wor-joiner, 1 pro běžnou latinku, 2 pro CJK) je přes typ wchar_t, takže se mu ani tak nevyhnete.
12.11.2011 13:24 l4m4
Rozbalit Rozbalit vše Re: C/C++ podpora UTF-8, jak to funguje?
Chci vidět program, který pracuje smysluplně s mezinárodním textem pouze pomocí standardní knihovny...

Nicméně je dobře, že jsi upozornil, na vlastnost pojme libovolný znak z libovolného locale podporovaného danou implementaci standardní knihovny, protože standard C umožňuje dokonce i pouze 8bitový wchar_t (a na nějakých obskurních/historických systémech to tak i je, akorát bych musel najít kde a jak, byl to nějaký, co měl jako největší vymoženost podporu Latin1).

Tudíž chceš-li používat Unicode, tak ho používej, použij nějakou knihovnu pro práci s Unicode (ať už representované v UTF-8 jako bajty nebo v UCS-4 jako 32bitové integery), a nematlej do toho wchar_t.

Stačí-li ti nepřenositelně podporovat cokoli, co tvůj kompilátor a standardní knihovna zrovna prohlásily za wide-char, a používat pouze funkce standardní knihovny, tak používej to.
Josef Kufner avatar 20.11.2011 23:39 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: C/C++ podpora UTF-8, jak to funguje?
Odpovědět | | Sbalit | Link | Blokovat | Admin
V podstatě můžeš kódování ignorovat a použít prosté char * v UTF-8 – tak jak to dostaneš, tak to vypíšeš.

Řešit to musíš až v okamžiku, kdy tě zajímá, kolik místa to zabere na obrazovce (strlen() nestačí) nebo pokud chceš seřadit seznam (strcmp() nestačí), případně zkracovat řetězce (abys nerozpůlil znak).
Hello world ! Segmentation fault (core dumped)

Založit nové vláknoNahoru

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.