Nepřemístitelné bloky paměti | Přemístitelné bloky paměti | |
---|---|---|
Proměnná, kterou se na blok odkazujeme | Adresa počátku bloku MemPtr | Ovladač bloku MemHandle |
Inicializace a zrušení | funkcemi MemPtrNew(), MemPtrFree() | funkcemi MemHandleNew(), MemHandleFree() |
Ukládání a čtení dat | Je možné ihned od adresy počátku bloku | Pouze z uzamknutého bloku (mezi voláním funkce MemHandleLock() a MemHandleUnlock()) |
Změna velikosti | funkce MemPtrResize() | funkce MemHandleResize(), blok nesmí být uzamčen |
Dotaz na velikost bloku paměti | funkce MemPtrSize() | funkce MemHandleSize() |
Dosud popsané postupy zacházení s přemístitelnými a nepřemístitelnými bloky paměti se vztahovaly zatím pouze na dynamickou paměť. Pokud v naší aplikaci potřebujeme použít větší množství paměti, než kolik se nám vejde do oblasti dynamické paměti, musíme bloky paměti alokovat v oblasti úložné paměti. O práci s úložnou pamětí si povíme při popisu správce databází PalmOS v některé z příštích kapitol.
3.7. Funkce PalmOS pro zacházení s řetězci
Jádro operačního systému PalmOS v sobě obsahuje funkce pro práci s řetězci. Podobně jako v jazyce C/C++ jsou podporovány řetězce jako pole znaků libovolné délky ukončené znakem '\0'. Protože funkce pro práci s řetězci jsou již obsažené v jádru operačního systému, tak nepotřebujeme při překladu připojovat k naší aplikaci žádnou speciální knihovnu pro práci s řetězci.
Doporučované datové typy pro práci se znaky a s řetězci v PalmOS ve verzi 3.0 a vyšší jsou uvedeny v následující tabulce:
standardní C/C++ | PalmOS | |
---|---|---|
Jednotlivé znaky | char nebo unsigned char (8bitový datový typ) | WChar (16bitový datový typ, ve kterém mohou být uloženy i dvoubytové znaky UNICODE) |
Řetězec | char text[100];(pole 8bitových znaků) |
Char text[100];(pole osmibitových znaků, ve kterém však mohou být zařazeny i dvoubytové znaky UNICODE |
Ukazatel na řetězec | char* ukazatel; |
Char* ukazatel; |
Doporučení používat pro uložení jednotlivých znaků 16bitový datový typ WChar místo 8bitového (Char) má základ v široké podpoře PalmOS pro jazyky používající nestandardní abecedy. Samotné řetězce jsou uloženy z důvodů úspory paměti jako pole 8bitových znaků Char a systémové funkce dovedou správně rozlišit jedno a dvoubytové znaky, které se v řetězcích nacházejí.
Char* s1 = "ahoj"; // Deklarace řetězcové konstanty s hodnotou "ahoj". Tato konstanta // zabírá v paměti 5 byte: // s1[0] = 'a' // s1[1] = 'h' // s1[2] = 'o' // s1[3] = 'j' // s1[4] = '\0' WChar znak = s1[3]; // znak má hodnotu 'o' Char s2[30]; // Deklarace řetězce, který může obsahovat nejvíce 29 znaků // (poslední znak bude ukončující '\0') Char* s3 = s1; // s3 ukazuje na stejný řetězec jako s1 (obsahující "ahoj") |
Funkce PalmOS pro práci s řetězci
Při psaní aplikací pro PalmOS doporučují vývojáři společnosti Palm, Inc. nepoužívat funkce standardní knihovny C/C++ (jako strlen(), strcat(), toupper() a podobně). Pokud kteroukoliv z těchto funkcí použijeme, bude při překladu k naší aplikaci připojena standardní knihovna C/C++, která zvětší velikost naší aplikace o 1-10 kB.
UInt16 StrLen(const Char* src) Zjistí délku řetězce. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Char* StrCopy(Char* kam, const Char* odkud) Zkopíruje jeden řetězec do druhého. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Pokud se zdrojový i cílový řetězec překrývají, tak se může funkce StrCopy() chovat nepředvídatelně. Použití funkce je následující (pro připomenutí budu ve většině příkladů v této kapitole používat i bloky paměti):
Char* a = "abcde"; // řetězcová konstanta Char b[100]; Char* c = (Char*)MemPtrNew(100); // můžeme použít i blok paměti n = StrLen(a); // n bude rovné pěti n = StrLen(""); // n bude rovno nule StrCopy(b, a); // b bude mít hodnotu "abcde" StrCopy(c, "kocka"); // c bude mít hodnotu "kocka" MemPtrFree((MemPtr)c); // nesmíme zapomenout uvolnit paměť |
Char* StrNCopy(Char* cíl, const Char* zdroj, Int16 n) Zkopíruje zdrojový řetězec na místo cílového. Ohlídá přitom, aby nebyla překročena největší délka cílového řetězce. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Po volání funkce StrNCopy() bude cílový řetězec dlouhý nejvýše (n - 1) znaků a bude ukončen znakem '\0'. Celý se tedy vejde do oblasti paměti o délce n byte. Tuto funkci je vhodné používat ve všech případech, kdy kopírujeme řetězce proto, aby nedocházelo k překročení maximální povolené délky řetězce. Funkce v následujícím rámečku zkopíruje text do oblasti přemístitelného bloku paměti a ohlídá si, aby nebyla překročena jeho délka:
void Kopiruj(MemHandle hKam, Char* odkud) { StrNCopy((Char*)MemHandleLock(hKam), odkud, MemHandleSize(hKam)); MemHandleUnlock(hKam); } |
Funkce StrCopy() a StrNCopy() jsou ekvivalenty funkcí strcpy() a strncpy() z knihovny řetězcových funkcí jazyka C/C++.
Char* StrCat(Char* cíl, const Char* text) Spojí dva řetězce - zkopíruje řetězec text na konec řetězce cíl. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Funkce StrCopy() a StrCat() vrací adresu výsledného řetězce - to je možné využít - například po volání
Char text[10]; StrCopy(text, StrCat("a", "b"))obsahuje proměnná text text "ab".
Char* StrNCat(Char* cíl, const Char* text, Int16 n) Spojí dva řetězce - zkopíruje řetězec text na konec řetězce cíl a ohlídá, aby se výsledný řetězec vešel do n byte. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Při kopírování řetězců zadaných uživatelem nebo takových, u kterých neznáme přesně jejich délku, se doporučuje použít funkcí StrNCopy() a StrNCat(). Tím zabráníme chybám, které vzniknou při překročení místa v paměti vyhrazeného proměnné.
Char* StrToLower(Char* cíl, const Char* zdroj) Zkopíruje řetězce a převede všechny znaky na malá písmena. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Na systémech, které podporují mezinárodní znaky (PalmOS 3.3 a vyšší) nebo v aplikacích, které speciálně připravíme pro zpracování mezinárodních znaků na starších operačních systémech, převádí tato funkce správně i česká akcentovaná písmena. O správné lokalizaci našich aplikací si povíme později.
Int16 StrCompare(const Char* s1, const Char* s2) Int16 StrCaselessCompare(const Char* s1, const Char* s2) Porovná řetězce s1 a s2. Funkce StrCaselessCompare() porovnává bez ohledu na velká a malá písmena. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Pro správné abecední porovnání dvou řetězců je nutné volat obě tyto funkce - nejprve StrCaselessCompare() a poté teprve funkci StrCompare() jako v následujícím příkladu:
Int16 PorovnejAbecedne(Char* s1, Char* s2) { Int16 vysledek = StrCaselessCompare(s1, s2); return vysledek == 0 ? StrCompare(s1, s2) : vysledek; } |
Int16 StrNCompare(const Char* s1, const Char* s2, UInt32 n) Int16 StrNCaselessCompare(const Char* s1, const Char* s2, Int32 n) Porovná prvních n (nebo méně) znaků s1 a s2. Funkce StrNCaselessCompare() porovnává bez ohledu na velká a malá písmena. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Ve verzích operačního systému, které podporují mezinárodní znaky řadí porovnávací funkce české akcentované znaky správně.
Char* StrStr(const Char* kde, const Char* co) Vyhledá první výskyt řetězce co v řetězci kde. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Char* StrChr(const Char* kde, WChar znak) Vyhledá první výskyt znaku znak v řetězci kde. | |
Vstupní parametry |
|
Vrácená hodnota |
|
Předáme-li funkci StrChr() znak, který bude větší než 255, tak zobrazí chybovou hlášku. Bude-li znak roven '\0', tak nebude ve verzi PalmOS 1.0 nalezen správně.
Příště si dokončíme popis funkcí pro práci s řetězci popisem funkcí pro převod čísel na text.