Autor Téma: Část programu v unicode  (Přečteno 9168 krát)

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Část programu v unicode
« kdy: 04-08-2012, 13:07:15 »
Mám Cčkový (obyčejné C, ne C++) program, který je postavený na klasickém ASCII (char je osmibitový). Jde nějak jedoduše zařídit, aby část toho programu pracovala se znaky v kódování unicode? Speciálně mi jde o to, že veškerá výkonná část programu klidně může zůstat v ASCII, ale pojmenování souborů bych chtěl mít unicode. Tzn. jde mi o něco podobného, co bych v programu určeném výhradně pro Windows dosáhl pomocí záměny CreateFileA za CreateFileW.

Jaroslav Šmíd

  • Host
Re:Část programu v unicode
« Odpověď #1 kdy: 08-08-2012, 19:45:39 »
Zařídit to jde. Záleží na tom, jaké budeš požadovat kódování. Pokud se rozhodneš pro utf-8, můžeš nadále používat char s tím, že jeden unicode znak bude složen z jedno až čtyř "charů". Ve Windows API se používá UTF-16. S UTF-16 můžeš použít buď wchar_t na Windows (na Windows je 2B, ale v Linuxu je 4B, takže tam ne),

Pokud má být aplikace multiplatformní, nezbyde ti nic jiného než použít nějaký 16b typ, jako třeba uint16_t (stdint.h). Ten ale nemusí být přítomen ve všech implementacích, není to typ, co prostě musí existovat na dané platformě, máš ale standardem v podstatě zaručeno, že pokud platforma má 16bit typ, uint16_t bude existovat. stdint.h není přítomný ve Visual Studio až do verze 2010, protože MS ho bere jako C++ kompilátor, né C a proto jeho podpora standardů jazyka C může být špatná. Pokud ti nebude vadit spoléhat se na "novinky", můžeš použít char16_t z C11 a zapsat string s u literálem:
Kód: [Vybrat]
const char16_t* utf16_string = u"můj utf-16 string";
char16_t (a char32_t) jsou kromě C11 i součástí standardu C++11, takže aplikace může být zkompilována i novějšími C++ kompilátory. Možná Visual Studio by to mohlo vzít, protože nějakou tu podporu C++11 má, GCC a clang kompilátory podporují již většinu z C++11 a pár "věcí" z C11 taky.

Ať ale použiješ jakékoliv kódování a datový typ, stejně se pak nemusíš vyhnout dalším převodům kódování či znakových sad. Na Windows to bude ok, pokud použiješ utf-16, protože WinAPI fce to očekávají, na jiných platformách ale můžeš mít problém. Na linuxu se často používá utf-8.

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Část programu v unicode
« Odpověď #2 kdy: 08-08-2012, 22:21:54 »
Zní to dost složitě. Zatím jsem to obešel tak, že ve svém programu vytvořím dočasné ANSI jméno souboru, zavolám Cčkový program, a pak ten soubor zase přejmenuju zpátky. Není to úplně ono, ale funguje to a implementace byla celkem bezbolestná.

Kdybych to chtěl udělat čistě - to stačí poslat do fopen() unicode string?

Jaroslav Šmíd

  • Host
Re:Část programu v unicode
« Odpověď #3 kdy: 09-08-2012, 14:06:29 »
No pokud nutně konverzi unicode na ansi, tak můžeš mít s převodem problémy, pokud ty znaky nebudou reprezentovatelné v cílové znakové sadě. (např UTF-16 na CP-1250 může být problém s některými znaky). Měl bys teda při převodu toto kontrolovat, než to pak předáš do fopen(), které utf-16 řetězec nedávej. Pokud bys to udělal, fopen() se k tomu stejně bude chovat jako pole charů ukončené nulou a jelikož v UTF-16 jsou dvoubajtové prvky a pro asci znaky (a i jiné) je jeden byte vždy nulový, tj. fce fopen() si "řekne" "tady končí řetězec" a cesta bude "ořezaná". Proto je převod potřeba. Ve Windows můžeš použít MultiByteToWideChar a WideCharToMultiByte.

Ale pokud tedy programuješ ve Windows, je nejlepší se konverzí vůbec nezabývat a použít CreateFileW místo fopen, s kterou se jen ochuzuješ (s CreateFileW otevřeš soubor s názvem s 32k znaky, můžeš použít case-sensitive cestu, pokud to daný filesystém podporuje, ... s fopen() jen do PATH_MAX, žadné case-sensitive cesty či jiné pokročilé vlastnosti)
Pokud otevíráš s fopen, protože potřebuješ nutně FILE*, tak stále můžeš použít CreateFileW a HANDLE zabalit do FILE použitím pár fcí. Viz třeba http://stackoverflow.com/questions/7369445/is-there-a-windows-equivalent-to-fdopen-for-handles

Offline pepak

  • Padawan
  • ******
  • Příspěvků: 1574
  • Karma: 37
    • Pepak.net
Re:Část programu v unicode
« Odpověď #4 kdy: 09-08-2012, 17:09:11 »
No pokud nutně konverzi unicode na ansi, tak můžeš mít s převodem problémy, pokud ty znaky nebudou reprezentovatelné v cílové znakové sadě.
Proto píšu, "vytvořím dočasné ANSI jméno" - to nemá s původním unicodovým nic společného (no, ve skutečnosti má - používám MD5 hash původního jména).

Citace
Ale pokud tedy programuješ ve Windows, je nejlepší se konverzí vůbec nezabývat a použít CreateFileW místo fopen, s kterou se jen ochuzuješ
No mě šlo právě o to, jestli v Cčku existuje nějaký univerzální, platformově nezávislý mechanismum pro otvírání souborů s unicode názvem. Samozřejmě to můžu obejít přes CreateFileW, stejně jako to můžu udělat v jakémkoliv jiném jazyku (a jako to ve svém VFY dělám v Delphi), ale tak trochu to postrádá tu krásu toho, že stejný Cčkový zdroják můžu (plus mínus) přeložit pod Windows i na ZX Spectru.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 577
  • Karma: 25
Re:Část programu v unicode
« Odpověď #5 kdy: 09-08-2012, 19:09:13 »
ale tak trochu to postrádá tu krásu toho, že stejný Cčkový zdroják můžu (plus mínus) přeložit pod Windows i na ZX Spectru.

což platí pro Hello world, jinak je tak trochu mýtus/marketingová lež, která se šíří od vzniku jazyka a nemá s realitou moc společného.
- C neumí samo skoro nic, na všechno musíš použít nějakou knihovnu
- "multiplatformita" znamená, že do jednoho zdrojáku můžeš nacpat stovky dalších zdrojáků a při překladu se vyberou odpovídající fragmenty. Tento megamix se děje někdy na úrovni jednotlivých souborů, někdy na úrovni řádek v jediném souboru.

Takže i když něco vypadá jako volání jedné funkce fungující všude, tak to ve skutečnosti funguje na těch systémech, pro které to někdo napsal. Není zásadní rozdíl v tom, jestli si tu megafunkci na pár tisíc řádek (z nichž se použije část) napíšeš sám nebo to za tebe už napsal někdo jiný.