Хрестоматия по программированию на Си в Unix


Мобильность и машинная зависимость программ. Проблемы с русскими буквами. - стр. 5


Для выделения классов символов (например цифр), следует пользоваться макросами из include-файла <ctype.h> Так вместо

if( '0' <= c && c <= '9' ) ...

следует использовать

#include <ctype.h>

..... if(isdigit(c)) ...

и вместо

if((c >='a' && c <= 'z') (c >= 'A' && c <= 'Z')) ...

надо

if(isalpha(c)) ...

Дело в том, что сравнения < и > зависят от расположения букв в используемой кодировке. Но например, в кодировке КОИ-8 русские буквы расположены НЕ в алфавитном порядке. Вследствие этого, если для

char c1, c2; c1 < c2

то это еще не значит, что буква c1 предшествует букве c2 в алфавите! Лексикографическое сравнение требует специальной перекодировки букв к "упорядоченной" кодировке.

Аналогично, сравнение

if( c >= 'а' && c <= 'я' )

скорее всего не даст ожидаемого результата. Макроопределения же в <ctype.h> используют массив флагов для каждой буквы кодировки, и потому не зависят от порядка букв (и работают быстрее). Идея реализации такова:

extern unsigned char _ctype[]; /*массив флагов*/ #define US(c) (sizeof(c)==sizeof(char)?((c)&0xFF):(c)) /* подавление расширения знакового бита */ /* Ф Л А Г И */ #define _U 01 /* uppercase: большая буква */ #define _L 02 /* lowercase: малая буква */ #define _N 04 /* number: цифра */ #define _S 010 /* space: пробел */ /* ... есть и другие флаги ... */ #define isalpha(c) ((_ctype+1)[US(c)] & (_U|_L) ) #define isupper(c) ((_ctype+1)[US(c)] & _U ) #define islower(c) ((_ctype+1)[US(c)] & _L ) #define isdigit(c) ((_ctype+1)[US(c)] & _N ) #define isalnum(c) ((_ctype+1)[US(c)] & (_U|_L|_N)) #define tolower(c) ((c) + 'a' - 'A' ) #define toupper(c) ((c) + 'A' - 'a' )

где массив _ctype[] заполнен заранее (это проинициализированные статические данные) и хранится в стандартной библиотеке Си. Вот его фрагмент:

unsigned char _ctype[256 /* размер алфавита */ + 1] = { /* EOF код (-1) */ 0, ... /* '1' код 061 0x31 */ _N, ... /* 'A' код 0101 0x41 */ _U, ... /* 'a' код 0141 0x61 */ _L, ... };




- Начало -  - Назад -  - Вперед -



Книжный магазин