Portál AbcLinuxu, 30. dubna 2025 16:48

Implementace ctype funkcí (Unix V7)

14.7.2018 13:34 | Přečteno: 3094× | Linux | poslední úprava: 14.7.2018 13:28

Během pročítání The C Programming Language (1988) občas narazíte na docela divoké konstrukce.
if (isdigit(c))            /* collect integer part */
    while (isdigit(s[++i] = c = getch()))
        ;
Protože funkce ze ctype.h jsou většinou implementovány jako makra, možná vás napadne, jak byste takové makro sami napsali, aby nedocházelo k side-efektům.

V Unixu V7 (1979) to řeší takto:

ctype_.c
#include    <ctype.h>

char _ctype_[] = {
    0,
    _C,    _C,    _C,    _C,    _C,    _C,    _C,    _C,
    _C,    _S,    _S,    _S,    _S,    _S,    _C,    _C,
    _C,    _C,    _C,    _C,    _C,    _C,    _C,    _C,
    _C,    _C,    _C,    _C,    _C,    _C,    _C,    _C,
    _S,    _P,    _P,    _P,    _P,    _P,    _P,    _P,
    _P,    _P,    _P,    _P,    _P,    _P,    _P,    _P,
    _N,    _N,    _N,    _N,    _N,    _N,    _N,    _N,
    _N,    _N,    _P,    _P,    _P,    _P,    _P,    _P,
    _P,    _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U|_X, _U,
    _U,    _U,    _U,    _U,    _U,    _U,    _U,    _U,
    _U,    _U,    _U,    _U,    _U,    _U,    _U,    _U,
    _U,    _U,    _U,    _P,    _P,    _P,    _P,    _P,
    _P,    _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L|_X, _L,
    _L,    _L,    _L,    _L,    _L,    _L,    _L,    _L,
    _L,    _L,    _L,    _L,    _L,    _L,    _L,    _L,
    _L,    _L,    _L,    _P,    _P,    _P,    _P,    _C
};
ctype.h
#define _U    01
#define _L    02
#define _N    04
#define _S    010
#define _P    020
#define _C    040
#define _X    0100

extern  char  _ctype_[];

#define isalpha(c)    ((_ctype_+1)[c]&(_U|_L))
#define isupper(c)    ((_ctype_+1)[c]&_U)
#define islower(c)    ((_ctype_+1)[c]&_L)
#define isdigit(c)    ((_ctype_+1)[c]&_N)
#define isxdigit(c)   ((_ctype_+1)[c]&(_N|_X))
#define isspace(c)    ((_ctype_+1)[c]&_S)
#define ispunct(c)    ((_ctype_+1)[c]&_P)
#define isalnum(c)    ((_ctype_+1)[c]&(_U|_L|_N))
#define isprint(c)    ((_ctype_+1)[c]&(_P|_U|_L|_N))
#define iscntrl(c)    ((_ctype_+1)[c]&_C)
#define isascii(c)    ((unsigned)(c)<=0177)
#define toupper(c)    ((c)-'a'+'A')
#define tolower(c)    ((c)-'A'+'a')
#define toascii(c)    ((c)&0177)
       

Hodnocení: 100 %

        špatnédobré        

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Nástroje: Začni sledovat (0) ?Zašle upozornění na váš email při vložení nového komentáře. , Tisk

Vložit další komentář

14.7.2018 19:24 Martin Mareš
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Odpovědět | Sbalit | Link | Blokovat | Admin
On je to pěkný trik, ale bohužel také důvod, proč následující přímočaře vypadající kód nefunguje:
char c = getchar();
if (isprint(c))
    putchar(c);
Vidíte, proč?
14.7.2018 20:19 sad
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Ani ne, mně ten kód funguje.
14.7.2018 21:12 pc2005 | skóre: 38 | blog: GardenOfEdenConfiguration | liberec
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
V případě, že někdo zavře stdin, tak ta tabulka přeteče. Ale závisí to na tom, zda měl v té době getchar návratový typ int, měl implementovaný EOF (= -1) nebo chybový návrat a zda byl char signed nebo unsigned (spíš signed, protože tam je ta +1) a zda může getchar číst i ascii znaky s nastaveným 7. bitem (128-255, pokud je v dané implementaci char signed, a někdo načte znak z vyšší poloviny ascii, tak tabulka naopak podteče). Nejspíš by to chtělo ten načtenej znak obalit toascii().
14.7.2018 21:25 debian
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
toascii nepomoze. pracuje s int.
int toascii(int c);
Vid man

14.7.2018 21:41 pc2005 | skóre: 38 | blog: GardenOfEdenConfiguration | liberec
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
V roce 1979 bylo typově nezávislé, viz poslední řádek blogu.
15.7.2018 22:45 .
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Jestli se bavíte o kódu z blogu, tak tam žádný problém není.

Pokud je řeč o tom od MM, tak je v první řadě použití charu prostě blbě.
16.7.2018 01:31 Martin Mareš
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Je blbě, ale je to naprosto typická začátečnická chyba: chvíli trvá, než člověk pochopí, že znaky se obvykle neukládají do charů :)

Svádí to k tomu, už jsem viděl i několik programů o statisících řádků zdrojáku, které byly takovýmihle chybami prolezlé.
16.7.2018 09:27 sad
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Bych to jen doplnil, že znaky se deklarují jako int, aby mohly nabýt hodnotu EOF, která je zpravidla -1.
14.7.2018 21:38 sad
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Tak v operačním systému Plan 9 už má ta tabulka 256 prvků.
15.7.2018 00:49 Martin Mareš
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Nejen když zavře stdin. Úplně stačí, když se na vstupu objeví jakýkoliv znak s nahozeným nejvyšším bitem (tedy aspoň na překladačích, kde char je defaultně signed).
15.7.2018 06:59 kvr
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Tak v zásadě není problém udělat buď pole se základem -128 a odečíst od parametru. Nebo lépe přetypovat parametr na (unsigned char).

Předpokládám, že výše uvedený kus kódu pocházel z doby, kdy měly kompilátory a knihovny nastavený char jako unsigned, u novějších bych čekal odolnější přístup.
14.7.2018 21:22 debian
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Mne to funguje spravne.
14.7.2018 22:42 SazeVaclav
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
me ne ??? , ja kdyz zadam 'é', tak se ten putchar neprovede - a pritom bych si myslel, ze 'é' je printable.
15.7.2018 09:31 Jindřich Makovička | skóre: 17
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Pro multibyte locale tenhle kód nefunguje už vůbec, tam je potřeba použít wchar varianty funkcí.
15.7.2018 22:48 .
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Ono to nemusí být multibyte, ale určitě je to mimo ASCII+EOF, pro které je ta tabulka definovaná.
16.7.2018 11:04 debian
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
v popise man page jasne pise, ze pracuje so 7 bitami
16.7.2018 19:51 debian
Rozbalit Rozbalit vše Re: Implementace ctype funkcí (Unix V7)
Odpovědět | Sbalit | Link | Blokovat | Admin
Zdrojaky prekladacov su dostupne, tak preco z nich nevytiahnut, co clovek potrebuje?

Založit nové vláknoNahoru

ISSN 1214-1267, (c) 1999-2007 Stickfish s.r.o.