Char w Delphi XE - jak rozpoznać polskie litery (unicode)

Char w Delphi XE - jak rozpoznać polskie litery (unicode)
RD
  • Rejestracja:około 12 lat
  • Ostatnio:12 miesięcy
  • Postów:212
0

Mam problem z poniższą procedurą.

Kopiuj
procedure EditKeyPress(Sender: TObject; var Key: Char);
begin
  if Key in ['a'..'z','ę','ł'] then else Key := #0;
end;

Procedura działa w D7 ale w XE już nie a to z tego powodu że typ char zajmuje 2 bajty i jest to typ widechar. I teraz jeśli Key = 'ł' to nie rozpoznaje tej literki pośród zdeklarowanych w nawiasach kwadratowych. Jakiś pomysł jak to ugryść?

Próbowałem tak ale też nie działa

Kopiuj
  If AnsiUpperCase(Key)[1] in ['ę','ó','ą','ś','ł','ż','ź','ć','ń','Ę','Ó','Ą','Ś','Ł','Ż','Ź','Ć','Ń','0'..'9','a'..'z','A'..'Z','"',' ','-',#13,#8,#2,#22] then else Key:=#0;

Oraz także tak jak w dokumentacji Delphi

Kopiuj
var
  charSet: set of AnsiChar;
begin
  charSet := ['ę','ó','ą','ś','ł','ż','ź','ć','ń','Ę','Ó','Ą','Ś','Ł','Ż','Ź','Ć','Ń','0'..'9','a'..'z','A'..'Z','"',' ','-',#13,#8,#2,#22];
  If AnsiChar(Key) in charSet then else Key:=#0;
end;

Rożnica taka że rozpoznaję ł oraz ń ale ś, ć nadal nie rozpoznaje

edytowany 2x, ostatnio: Rafał D
flowCRANE
Popraw tytuł wątku na taki, który w sposób sensowny i w miarę wyczerpujący będzie opisywać Twój problem, albo wątek wyląduje w koszu;
flowCRANE
I edytuj swoje posty, jeśli chcesz coś jeszcze dodać;
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Tuchów
  • Postów:12175
0

Wszystko dlatego, że polskie znaki diakrytyczne w kodzie ASCII mają inne kody, niż w Unicode; Zobacz pod ten link - http://en.wikipedia.org/wiki/Polish_code_pages - są tam podane heksadecymalne kody znaków diakrytycznych w Unicode (pierwszy wiersz tabelki), które są inne, niż w ASCII;

Na przykład znak Ą - w ASCII ma kod 0xA5, a w Unicode 0x104;

Dodatkowo jeśli kod ten ma być przenośny między różnymi wersjami Delphi, to odpowiednimi dyrektywami możesz sprawdzić wersję kompilatora i jeśli jest stara - wykorzystać stary kod, a jeśli jest nowsza (z Unicode) to wykonać sprawdzenie według kodów Unicode;

PS. Skasowałem poprzednie wywody z posta (szkoda miejsca); Za utrudnienia przepraszam - zamotałem się.


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
edytowany 10x, ostatnio: flowCRANE
KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Gorlice
1

Pod starymi i nowymi Delphi nawet bez dyrektyw kompilatora zadziała:

Kopiuj
if not ((Key in ['a'..'z']) or (Key = string('ę')[1]) or (Key = string('ł')[1])) then
   Key:= #0;

PS:
Nie pytajcie mnie dlaczego tak jak niżej się skompiluje a NIE działa:

Kopiuj
if not (Key in ['a'..'z', string('ę')[1], string('ł')[1]]) then
   Key:= #0;

Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
flowCRANE
PS. - a kto by wiedział jaki humor dziś ma kompilator ;)
flowCRANE
Moderator Delphi/Pascal
  • Rejestracja:ponad 13 lat
  • Ostatnio:około 8 godzin
  • Lokalizacja:Tuchów
  • Postów:12175
0

W racja @kAzek - nie pomyślałem, że można wykorzystać do tego rzutowanie; Jednak niepotrzebnie wykorzystujesz do tego typ String, skoro można krócej zapisać z rzutowaniem na Char:

Kopiuj
if not (Key in ['a' .. 'z', Char('ę'), Char('ł')]) then
  Key := #0;

i nie będzie problemów z tym, że nie wiadomo czemu nie będzie poprawnie działać :]


Pracuję nad własną, arcade'ową, docelowo komercyjną grą z gatunku action/adventure w stylu retro (pixel art), programując silnik i powłokę gry od zupełnych podstaw, przy użyciu Free Pascala i SDL3. Więcej informacji znajdziesz na moim mikroblogu.
szopenfx
Zbiory mogą przyjąć maksymalnie 256 elementów 0..255 zapewne jest brana tylko młodsza połówka unicode, ale nie mam tego jak sprawdzić czyli jeśli dobrze myślę Ą będzie miało wartość 0x4 a nie 0x104 po takim rzutowaniu.
flowCRANE
Faktycznie - całkiem zapomniałem o tym...
KA
a no to by tłumaczyło sprawę
KA
  • Rejestracja:prawie 20 lat
  • Ostatnio:około 5 godzin
  • Lokalizacja:Gorlice
2

@furious programming Przykro mi muszę Cię rozczarować to też nie zadziała pod XE5 (i pod innymi Unicode pewnie też a w D7 działa) ale faktycznie można tak jak podałem tylko rzutować od razu na Char czyli:

Kopiuj
if not ((Key in ['a'..'z']) or (Key = Char('ę')) or (Key = Char('ł'))) then
   Key:= #0;

Sugerowane przez środowisko użycie funkcji CharInSet jak niżej też NIE działa:

Kopiuj
if not CharInSet(Key, ['a' .. 'z', Char('ę'), Char('ł')]) then
    Key := #0;

Nie odpowiadam na PW w sprawie pomocy programistycznej.
Pytania zadawaj na forum, bo:
od tego ono jest ;) | celowo nie zawracasz gitary | przeczyta to więcej osób a więc większe szanse że ktoś pomoże.
edytowany 1x, ostatnio: kAzek
flowCRANE
Kurde - dziwne to...
KA
No ja logiki w tym nie widzę to się do działu WTF nadaje ;)
flowCRANE
Jednak nie - zapomnieliśmy, że zbiory mogą zawierać elementy o maksymalnej wartości 255 (czyli i elementów może być maksymalnie 256); Stąd podczas kompilacji brany jest pod uwagę tylko jeden bajt znaku Unicode i całość nie ma prawa działać prawidłowo; Dobrze, że @szopenfx przypomniał ;)
Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 2 godziny
0

Pytanie brzmi, po co chcesz rozpoznawać polskie litery.
W 100% przypadków, w których chcemy „rozpoznawać polskie litery” tak naprawdę powinno się obsłużyć takie czy inne kodowanie znaków - w pełni - konwertując czy sortując znaki według tego właśnie kodowania i określonych ustawień regionalnych.

Tak więc źle do tematu podchodzisz.

RD
  • Rejestracja:około 12 lat
  • Ostatnio:12 miesięcy
  • Postów:212
0

Dzięki wam za wszelką pomoc bardzo się przydała.

Azarien Dlaczego źle, a jak mam innym sposobem obsłużyć to co jest np wpisywane do edita? Chyba najprościej wykorzystać zdarzenie

Kopiuj
onKeyPress(Sender: TObject; var Key: Char);
edytowany 1x, ostatnio: Rafał D
Zobacz pozostałe 2 komentarze
Azarien
no ale po co. dlaczego ś ma być poprawne a é już nie?
flowCRANE
Pewnie dlatego, że é nie jest polskim diakrytykiem; Trzeba pytacza o to zapytać ;)
Azarien
100 lat temu jeszcze było. może ktoś ma stary tekst? :-)
flowCRANE
A jakie było wtedy kodowanie? ;P
Azarien
Unicode, zawsze i wszędzie! :-P
MA
  • Rejestracja:prawie 17 lat
  • Ostatnio:11 dni
0

Też kiedyś walczyłem z problemem CharInSet + polskie znaki i tak wykombinowałem (działa pod Unicode):

Kopiuj
function PolskiZnak(Znak: Char): Boolean; //sprawdzenie, czy znak należy do grupy polskich znaków
begin
  result := false;
  case Znak of
   'ą','ę','ć','ł','ń','ó','ś','ź','ż',
   'Ą','Ę','Ć','Ł','Ń','Ó','Ś','Ź','Ż': result := true;
  end;
end;

czyli zamiast:

Kopiuj
 
if Key in ['ą','ę','ć','ł',...] then ...
 lub
if CharInSet(Key, ['ą','ę','ć','ł',...]) then ... 

dajesz:

Kopiuj
 
if PolskiZnak(Key) then ...
hnb
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 2 lata
  • Postów:28
0

Jeśli chcesz sprawdzić w elegancki sposób czy dany znak jest literą w unicode, należy użyć funkcji

Kopiuj
function IsLetter(C: Char): Boolean;

z modułu System.Character. Nie jestem pewny czy funkcja i moduł istnieje dla XE (od XE2 na pewno).


NewPascal.org
edytowany 1x, ostatnio: hnb

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.