[ Pobierz całość w formacie PDF ]

przykład wszystkie litery lub wszystkie znaki sterujące. Dzięki temu będziemy mogli
robić dowolne z powyższych sprawdzeń za pomocą tylko dwóch porównań. Na przy-
kład wygodnie byłoby sprawdzać, czy dany znak jest znakiem przestankowym, po-
równując go z wartościami ograniczającymi znaki przestankowe z góry i z dołu. Nie
można w ten sposób obsłużyć wszystkich możliwych zakresów porównań, ale warto
uwzględnić zakresy występujące najczęściej. Wprawdzie w ASCII pewne ciągi znaków
są ułożone bardzo sensownie, ale można je jeszcze poprawić. Na przykład nie można
tam sprawdzić, czy znak jest przestankowy, przy ograniczeniu się do dwóch porównań,
gdyż znaki te są porozrzucane po całym zestawie.
120 Profesjonalne programowanie. Część 1. Zrozumieć komputer
5.4.2. Grupowanie znaków odpowiadających cyfrom
Wezmy pod uwagę pierwsze trzy funkcje z powyższej listy  najłatwiej będzie nam
je realizować, jeśli znakom o kodach od 0 do 9 przypiszemy kolejne cyfry. Korzysta-
jąc z pojedynczego porównania wartości bez znaku, sprawdzamy, czy dany znak jest
cyfrą. Konwersja między cyfrą a jej wartością jest banalna, gdyż kod i wartość znaku
są identyczne.
5.4.3. Grupowanie liter
Kolejnym typowym problemem związanym z obsługą znaków i łańcuchów znakowych
jest obsługa liter. Zestaw ASCII, choć jest o niebo lepszy od EBCDIC, po prostu nie
nadaje się do sprawdzania i przetwarzania liter. Oto problemy z literami ASCII, które
rozwiążemy w HyCode:
Litery zostały umieszczone w dwóch osobnych częściach. Sprawdzanie,
czy znak jest literą, wymaga zrobienia czterech porównań.
Małe litery mają kody ASCII większe od wielkich liter. Jeśli chodzi
o porównania, bardziej intuicyjne jest traktowanie małych liter jako
znajdujących się wcześniej niż wielkie.
Wszystkie małe litery mają wartości większe od poszczególnych wielkich
liter. Prowadzi to do niezgodnych z intuicją efektów, kiedy a jest większe
od B, choć każde dziecko wie, że jest inaczej.
Kodowanie HyCode rozwiązuje te problemy na kilka ciekawych sposobów. Po pierw-
sze, do zapisu 52 liter używane są kody od $4C do $7F. HyCode wykorzystuje tylko
128 znaków ($00..$7F), z czego 52 to litery. Wobec tego, jeśli będziemy sprawdzać, czy
dany znak jest literą, wystarczy porównać, czy jego kod jest większy lub równy $4C.
W językach wysokiego poziomu wystarczy porównanie typu:
if( c >= 76) ...
Jeśli kompilator będzie obsługiwał HyCode, wystarczy zapis:
if( c >= 'a') ...
W asemblerze wystarczy wykorzystać dwie instrukcje:
cmp( al, 76 );
jnae NotAlphabetic;
// Instrukcje wykonywane dla liter.
NotAlphabetic:
Kolejna zaleta HyCode (istotnie różniąca to kodowanie od innych) to przeplatanie
wielkich i małych liter (czyli kolejno zapisywane są znaki a, A, b, B, c, C i tak dalej).
Dzięki temu sortowanie i porównywanie łańcuchów jest bardzo łatwe, niezależnie od
tego, czy uwzględniamy wielkość liter, czy nie. Przeplatanie powoduje, że najmłodszy
Rozdział 5. f& Dane znakowe 121
bit znaku wskazuje, czy znak jest małą literą (najmłodszy bit jest zerem), czy wielką
(najmłodszy bit jest jedynką). HyCode wykorzystuje następujące kodowanie liter:
a:76, A:77, b:78, B:79, c:80, C:81, ..., y:124, Y:125, z:126, Z:127
Sprawdzanie, czy dany znak HyCode jest wielką, czy małą literą, jest nieco trudniejsze
od sprawdzania, czy jest literą, ale w asemblerze jest to i tak prostsze od analogicznego
sprawdzenia kodu ASCII. Aby sprawdzić, czy znak jest danej wielkości, robi się dwa
porównania: najpierw sprawdza się, czy jest on literą, a potem określa jego wielkość.
W C i C++ użylibyśmy do tego następujących instrukcji:
if( (c >= 76) && (c & 1))
{
// kod wykonywany w przypadku wielkich liter
}
if( (c >= 76 && !(c & 1))
{
// kod wykonywany w przypadku małych liter
}
Wyrażenie (c & 1) zwraca prawdę, jeśli najmłodszy bit c jest jedynką, czyli kiedy
mamy do czynienia z wielką literą. Analogicznie !(c & 1) zwraca prawdę, jeśli naj-
młodszy bit c jest zerem, czyli kiedy c jest małą literą. W przypadku asemblera 80x86
można sprawdzić, czy znak jest wielką, czy małą literą, za pomocą trzech instrukcji
maszynowych:
// Uwaga: ROR(1, AL) powoduje odwzorowanie małych liter na zakres $26..$3F (38..63),
// a wielkich na zakres $A6..$BF (166..191). Wszystkie inne znaki są
// odwzorowywane na mniejsze wartości z tych zakresów.
ror( 1, al );
cmp( al, $26 );
jnae NotLower; // Uwaga: obsługujemy wartości bez znaku!
// Kod obsługujący małe znaki
NotLower:
// Zauważmy, że w instrukcja ROR tworzy kody z zakresu $A6..$BF będące
// ujemnymi wartościami 8-bitowymi. Są to przy okazji *najmniejsze* liczby
// ujemne, jakie ROR może wygenerować z zestawu znaków HyCode.
ror( 1, al );
cmp( a1, $a6 );
jge NotUpper // Uwaga: obsługujemy wartości bez znaku!
// Kod obsługujący wielkie litery.
NotUpper: [ Pobierz całość w formacie PDF ]
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • ocenkijessi.opx.pl
  • Copyright (c) 2009 - A co... - Ren zamyślił się na chwilę - a co jeśli lubię rzodkiewki? | Powered by Wordpress. Fresh News Theme by WooThemes - Premium Wordpress Themes.