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

Odpowiedz Nowy wątek
2014-02-05 20:47

Rejestracja: 7 lat temu

Ostatnio: 1 tydzień temu

0

Mam problem z poniższą procedurą.

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

  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

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, 2014-02-05 21:28
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; - furious programming 2014-02-05 21:21
I edytuj swoje posty, jeśli chcesz coś jeszcze dodać; - furious programming 2014-02-05 21:22

Pozostało 580 znaków

2014-02-05 21:29
Moderator Delphi/Pascal

Rejestracja: 8 lat temu

Ostatnio: 3 minuty temu

Lokalizacja: Tuchów

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ę.


edytowany 10x, ostatnio: furious programming, 2014-02-05 22:39

Pozostało 580 znaków

2014-02-05 23:44

Rejestracja: 14 lat temu

Ostatnio: 14 sekund temu

Lokalizacja: Gorlice

1

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

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:

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.
PS. - a kto by wiedział jaki humor dziś ma kompilator ;) - furious programming 2014-02-06 15:09

Pozostało 580 znaków

2014-02-06 15:25
Moderator Delphi/Pascal

Rejestracja: 8 lat temu

Ostatnio: 3 minuty temu

Lokalizacja: Tuchów

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:

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ć :]


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. - szopenfx 2014-02-06 16:09
Faktycznie - całkiem zapomniałem o tym... - furious programming 2014-02-06 16:24
a no to by tłumaczyło sprawę - kAzek 2014-02-06 16:29

Pozostało 580 znaków

2014-02-06 16:06

Rejestracja: 14 lat temu

Ostatnio: 14 sekund temu

Lokalizacja: Gorlice

@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:

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:

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, 2014-02-06 16:09
Kurde - dziwne to... - furious programming 2014-02-06 16:22
No ja logiki w tym nie widzę to się do działu WTF nadaje ;) - kAzek 2014-02-06 16:25
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ł ;) - furious programming 2014-02-06 16:31

Pozostało 580 znaków

2014-02-06 17:22

Rejestracja: 16 lat temu

Ostatnio: 4 godziny temu

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.

Pozostało 580 znaków

2014-02-07 20:57

Rejestracja: 7 lat temu

Ostatnio: 1 tydzień temu

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

onKeyPress(Sender: TObject; var Key: Char);
edytowany 1x, ostatnio: Rafał D, 2014-02-07 20:58
Pokaż pozostałe 2 komentarze
no ale po co. dlaczego ś ma być poprawne a é już nie? - Azarien 2014-02-08 05:58
Pewnie dlatego, że é nie jest polskim diakrytykiem; Trzeba pytacza o to zapytać ;) - furious programming 2014-02-08 17:48
100 lat temu jeszcze było. może ktoś ma stary tekst? :-) - Azarien 2014-02-08 17:56
A jakie było wtedy kodowanie? ;P - furious programming 2014-02-08 18:13
Unicode, zawsze i wszędzie! :-P - Azarien 2014-02-08 18:15

Pozostało 580 znaków

2014-02-07 21:45

Rejestracja: 11 lat temu

Ostatnio: 6 dni temu

0

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

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:


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

dajesz:


if PolskiZnak(Key) then ...

Pozostało 580 znaków

hnb
2014-02-12 11:04
hnb

Rejestracja: 6 lat temu

Ostatnio: 5 miesięcy temu

0

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

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, 2014-02-12 11:13

Pozostało 580 znaków

Odpowiedz

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0