W sumie to Lazarus już od dawien dawna używa UTF-8 dla łańcuchów znaków :]
karpov napisał(a)
Niestety taka konstrukcja ifa nie działa bo nie wykrywa mi w ten sposób 'ą'.
Dlatego że literał ą
jest dwubajtowy, czyli jest literałem łańcuchowym, a nie znakowym; Zresztą to nie jest dziwne, bo teoretycznie próbujesz porównać jeden bajt do dwóch bajtów;
W swoim projekcie wykorzystuję funkcję do translacji kodów znaków na kody wewnętrzne, w celu przyporządkowania ich do konkretnych wycinków obrazu PNG; Mechanizm tłumaczący kody znaków otrzymuje na wejściu ciąg typu String, czyli natywnie kodowany w UTF-8, a na wyjściu wypluwa jednobajtowe kody wewnętrzne wszystkich znaków z łańcucha; To tak ogólnie pisząc, niezbyt precyzyjnie;
Do czego zmierzam - mechanizm ten bazuje na wskaźnikach na znaki (typ PChar), z których korzysta funkcja UTF8CharacterToUnicode
z modułu LazUTF8
- funkcja ta pobiera wskaźnik, a zwraca kod znaku oraz ilość bajtów przez niego zajmowanych;
Wszystko już wiemy, więc można napisać przykładową funkcję, która sprawdzi czy w zadanym łańcuchu znaków znajduje się zadany znak:
uses
LazUTF8;
function IsLetterInString(const AString, ALetter: String): Boolean;
var
LCurrChar, LLastChar: PChar;
LCharCode, LLetterCode: UInt32;
LCharLen: Integer;
begin
LLetterCode := UTF8CharacterToUnicode(PChar(ALetter), LCharLen);
LCurrChar := @AString[1];
LLastChar := @AString[Length(AString)];
while LCurrChar <= LLastChar do
begin
LCharCode := UTF8CharacterToUnicode(LCurrChar, LCharLen);
if LCharCode = LLetterCode then
Exit(True);
LCurrChar += LCharLen;
end;
Result := False;
end;
Funkcja ta najpierw pobiera kod znaku z argumentu ALetter
i zapamiętuje go; Następnie ustawia wskaźnik na pierwszy i statni bajt łańcucha wejściowego (użycie funkcji Length jest celowe!), po czym przystępuje do pętli; W pętli pobierany jest kod znaku, na który wskazuje zmienna LCurrChar
, a także jego długość (tutaj dummy); Jeśli kod bieżącego znaku jest równy kodowi szukanego znaku to funkcja przerywa swoje działanie i zwraca True; A jeżeli kod jest inny to wskaźnik LCurrChar
inkrementowany jest o tyle bajtów, ile bajtów zajmuje sprawdzany znak - i wracamy do początku pętli; Jeśli znak nie zostanie znaleziony, funkcja zwraca False;
Przykłady wywołania:
Write('Result: ', IsLetterInString('furious programming', 'ą')); // wypisze w konsoli False
Write('Result: ', IsLetterInString('furiąs programming', 'ą')); // wypisze w konsoli True