<< , >> , Úvod

Víceslabikové znaky

Většina funkcí, definovaných standardy POSIX a XPG, pracuje výlučně se znaky o velikosti slabiky. Sady znaků, které obsahují více než 256 znaků, nelze reprezentovat datovým typem o velikosti slabiky. Ideální by byla redefinice všech standardních funkcí tak, aby pracovaly s libovolnou velikostí znaků, což je z důvodů kompatibility nereálné. Proto byly zavedeny pro reprezentaci znaků v jazycích s velkou abecedou dvě metody - víceslabikové znaky (multibyte characters) a široké znaky (wide characters). Víceslabikové znaky se mohou skládat z proměnného počtu slabik, jejich počet je určen definicí víceslabikového kódu. Hodnota první slabiky znaku obvykle signalizuje, z kolika slabik se znak skládá. Hodnota 0 se může objevit pouze v první slabice znaku a znamená ukončovač řetězce víceslabikových znaků. Maximální délka jednoho znaku kódu je dána symbolem MB_LEN_MAX definovaným v hlavičkovém souboru <stdlib.h>. Víceslabiková reprezentace je vhodná pro uchovávání textu, přenášení textu a zpracování textu, které nevyžaduje analýzu obsahu textu. S víceslabikovými znaky lze manipulovat standardními funkcemi pro práci s řetězci, znaky mohou být čteny standardními funkcemi pro práci se soubory a ukládány do znakových polí. Pro práci s textem však není víceslabiková reprezentace vhodná, protože různá délka znaků komplikuje i jednoduché algoritmy.

Pro analýzu obsahu textu je vhodnější reprezentace znaků s konstantní velikostí - pomocí širokých znaků. Široké znaky mají konstantní velikost, větší než 8 bitů na znak. Široké znaky jsou definovány typem wchar_t hlavičkovém souboru <stdlib.h>. Pro práci se širokými znaky však musí být k dispozici kompletní sada funkcí, nahrazující standardní funkce pro práci se znaky a řetězci. Příkladem kódu, který využívá široké znaky, je šestnáctibitový kód Unicode, resp. 32-bitový kód ISO 10646.

Víceslabikový kód může být buď stavově nezávislý anebo stavově závislý. Pokud je stavově nezávislý, pak dekódování řetězce nezávisí na předchozích dekódovaných řetězcích. Kód obvykle obsahuje několik prefixů, které uvozují jednu, či více následujících slabik, tvořících jeden znak. Stavově závislý kód obvykle obsahuje znaky, které přepínají platnou kódovou sadu (podobně jako v kódu ASCII řídicí znaky SI a SO). Dekódování je pak závislé na stavu těchto přepínačů. V počátečním stavu by oba typy kódů měly obsahovat v intervalu 0 až 127 kódy znaků ASCII, tzv. přenositelnou sadu znaků.

Příklad:

Příkladem víceslabikového kódu může být Extended Unix Code (EUC), používaný v systémech Unix V.4. Tento kód definuje čtyři sady znaků, dvě stavově nezávislé a dvě s prefixovými znaky SS2 (0x8e) a SS3 (0x8f). Prefixové znaky platí jen pro bezprostředně následující znak. Sada znaků 0 obsahuje 7 bitový kód ASCII. Znaky ostatních sad znaků obsahují pouze slabiky s nastaveným nejvyšším bitem. Počet slabik použitých pro definici znaků v sadách 1 až 3 je volitelný. Například kódování použité pro reprezentaci japonského kódu JIS X208 v systémech Unix V.4 používá znaky v sadě 1 a 3 o délce dvě slabiky a znaky v sadě 2 o délce 1 slabiky:

Sada	EUC Reprezentace			kód
0	0aaaaaaa			0000000000000000000000000aaaaaaa
1	1aaaaaaa 1bbbbbb		001100000000000000aaaaaaabbbbbbb
2	10001101 1aaaaaa		0001000000000000000000000aaaaaaa
3	10001111 1aaaaaa 1bbbbbb	001000000000000000aaaaaaabbbbbbb
Protože texty jsou většinou uloženy ve víceslabikové reprezentaci, musí programátor při zpracování nejprve převést víceslabikové znaky na široké znaky. Například uvedený kód JIS X208 v reprezentaci EUC je transformován tímto algoritmem:
wchar_t getwchar()
{
	wchar_t highbits, wc;
	int length;
	int c = getchar();
	if (c < 0x80) wc = c;
	else {
		if (c == SS2) {
			highbits = 0x10000000;
			length = 1;
			wc = 0;
		} else
		if (c == SS3) {
			highbits = 0x20000000;
			length = 2;
			wc = 0;
		} else {
			highbits = 0x30000000;
			length = 2;
			wc = c & 0x7f;
		}
		while (length--) {
			c = getchar();
			wc = (wc << 7) | (c & 0x7f);
		}
		wc |= highbits;
	}
	return(wc);
}

V uvedeném příkladu je problém stavově závislého dekódování vyřešen tím, že funkce vždy dokončí stavově závislou sekvenci. Univerzální konverzní funkce si však musí pamatovat stav přepínačů a prefixů z předchozího dekódování, aby mohla dále pokračovat. Konverzní funkce může být totiž vyvolána s libovolným počtem připravených vstupních slabik (například jedinou). Konverzní funkce definované normou ISO jazyka C tuto vlastnost zahrnují a umožňují i po částech konvertovat stavově závislé kódy. Funkce si interně ukládají stav kódování mezi jednotilivými voláními. Stav kódóvání je nezávislý pro jednotlivé funkce a není ovlivněn voláním žádných knihovních funkcí dle normy ISO a standardu XPG4. Stav kódóvání lze nastavit pro danou funkci do počátečního stavu vyvoláním této funkce s adresou víceslabikového znakového pole rovou NULL. Výsledkem takového volání je zároveň indikace, zda je používaný kód stavově závislý. Pokud je stavově závislý, je vrácena nenulová hodnota.

Norma ISO jazyka C nezaručuje platný počáteční stav stavově závislého kódování po volání funkce setlocale() s argumentem LC_ALL nebo LC_CTYPE. Proto by měl program, používající tyto konverzní funkce vždy inicializovat stav kódování. Maximální délka víceslabikového znaku pro prostředí nastavené funkcí setlocale() je dána hodnotou makra MB_CUR_MAX z hlavičkového souboru <stdlib.h>. Tato hodnota musí být menší nebo rovna maximální délce víceslabikových znaků v dané implementaci, kterou lze zjistit výsledkem makra MB_LEN_MAX z hlavičkového souboru <limits.h>.

Norma jazyka C definuje pouze základních 5 funkcí pro převody mezi víceslabikovými znaky a širokými znaky. Další funkce pro práci se širokými znaky jsou zatím definovány pouze jako volitelné rozšíření standardu XPG4.

#include <stdlib.h>
int mblen(const char *s, size_t n);
Výsledkem funkce je počet slabik tvořících víceslabikový znak v poli s. Parametr n určuje počet platných slabik v poli s. Pokud pole s obsahuje pouze znak '\0', je výsledkem 0. Pokud prvních n nebo méně slabik tvoří platný víceslabikový znak, pak je výsledkem počet slabik tohoto znaku. Pokud netvoří slabiky kód platného víceslabikového znaku, je výsledkem -1. Funkce má interně uložen svůj stav kódování, který není ovlivněn voláním ostatních funkcí pro práci s víceslabikovými znaky. Stav kódování lze inicializovat funkcí mblen() s parametrem s rovným NULL. Výsledkem je v tomto případě nenulová hodnota, pokud je používaný kód stavově závislý.
#include <stdlib.h>
int mbtowc(wchar_t *pwc, const char *s, size_t n);
Transformace jednoho víceslabikového znaku v poli s na široký znak do proměnné adresované parametrem pwc. Při transformaci je použito nanejvýš prvních n slabik pole s. Pokud prvních n nebo méně slabik pole s tvoří platný víceslabikový znak, pak je výsledkem tento počet a do pwc je uložen odpovídající široký znak. Pokud pole s obsahuje znak '\0', je uložen do pwc znak (wchar_t)0 a výsledkem je 0. Pokud netvoří slabiky kód platného víceslabikového znaku, je výsledkem -1. Funkce má interně uložen svůj stav kódování, který není ovlivněn voláním ostatních funkcí pro práci s víceslabikovými znaky. Stav kódování lze inicializovat funkcí mbtowc() s parametrem s rovným NULL. Výsledkem je v tomto případě nenulová hodnota, pokud je používaný kód stavově závislý.
#include <stdlib.h>
size_t mbstowcs(wchar_t *pwcs, const char *s, size_t n);
Transformace řetězce víceslabikových znaků s na řetězec širokých znaků do pole pwcs. Převod začíná s počátečním stavem kódování. Transformace je ukončena znakem '\0', který je transformován na hodnotu (wchar_t)0. Parametr n určuje maximální počet uložených širokých znaků (včetně ukončujícího 0). Pokud je znaků více nebo rovno n, není pole pwcs ukončeno znakem (wchar_t)0. Výsledkem je skutečný počet uložených širokých znaků (bez ukončujícího 0). Pokud je zadán nesprávný znak, je výsledkem -1. Pokud má parametr pwcs hodnotu NULL, je výsledkem potřebná velikost pole pwcs pro uložení všech znaků.
#include <stdlib.h>
int wctomb(char *s, wchar_t wc);
Převod širokého znaku wc na víceslabikový znak do pole s. Délka víceslabikového znaku je omezena hodnotou MB_CUR_MAX. Výsledkem je počet slabik, uložených do pole s. Převod zahrnuje uložení slabik reprezentujících daný znak, včetně příznaků pro změnu stavu kódu u vícestavových kódů. Konečný stav kódování má funkce interně uložen a při následujícím převodu pokračuje v tomto stavu. Interně uložený stav kódování není ovlivněn voláním ostatních funkcí pro práci s víceslabikovými znaky. Stav kódování lze inicializovat funkcí mbtowc() s parametrem s rovným NULL. Výsledkem je v tomto případě nenulová hodnota, pokud je používaný kód stavově závislý.
#include <stdlib.h>
size_t wcstombs(char *s, const wchar_t *pwcs, size_t n);
Transformace řetězce širokých znaků pwcs na řetězec víceslabikových znaků s. Transformace znaků nemění stav kódování jiných funkcí. Transformace končí dosažením ukončovacího znaku nebo překročením maximálního počtu uložených slabik n. Počet slabik zahrnuje ukončovací znak. Pokud je maximální počet slabik menší, než je třeba pro uložení řetězce, nemusí být na konci pole dostatek prostoru pro uložení celého víceslabikového znaku nebo ukončovacího znaku. Necelý znak nebo ukončovací znak není v tomto případě uložen. Výsledkem funkce je počet slabik, uložených do pole s, bez ukončovacího znaku. Pokud je výslená hodnota rovna n, není transformovaný řetězec ukončen ukončovacím znakem. Pokud je parametr s roven NULL, pak je výsledkem potřebný počet slabik pro uložení řetězce.


<< , >> , Úvod
Poslední změna: 1. June 1998
Pokud máte námět na vylepšení této stránky nebo na ní naleznete chybu, zašlete dopis na adresu lampa@fee.vutbr.cz.