1 /*my_ctype.h*/ 2 #ifndef _MY_CTYPE_H_ 3 #define _MY_CTYPE_H_ 4 5 /* 6 * 字符类别 7 * 数字,0-9之间的十进制数;十六进制数字,数字+a-f或A-F; 8 * 小写字母,a-z;大写字母,A-Z;字母,小写+大写字母; 9 * 字母数字,字母+数组;图形字符,占据一个打印位置,输出到显示设备时可见的字符。 10 * 标点符号,非字母数字的图形字符,29个; 11 * 打印字符,图形字符或者空格符;空白,空格字符和5个标准的运动控制字符(换页符FF,换行符NL,回车符CR,水平制表符HT,垂直制表符VT); 12 * 控制字符,5个标准的运动字符,退格符BS,警报符BEL。 13 */ 14 15 /* 16 * -->A-F a-f 17 * isxdigit--| 18 * --isdigit--->0-9 19 * __isalnum--| --isupper-->A-Z 20 * __isgraph-------| --isalpha------------------| 21 * isprint--| --ispunct-->!'#%&'();<=>?{\}*+,-./:^ --islower-->a-z 22 * -->space 23 * isspace--| 24 * -->FF NL CR HT VT 25 * iscntrl--| 26 * -->BEL BS 27 * 28 * iscntrl(0-31,127);isprint(其余为可显示字符) 29 */ 30 31 /*code bits,转换位*/ 32 #define XA 0x200 /*extra alphabetic*/ 33 #define XS 0x100 /*extra space*/ 34 #define BB 0x80 /*BEL BS etc*/ 35 #define CN 0x40 /*CR FF HT NL VT*/ 36 #define DI 0x20 /*'0'-'9'*/ 37 #define LO 0x10 /*'a'-'z'*/ 38 #define PU 0x08 /*punctuation标点符号*/ 39 #define SP 0x04 /*space*/ 40 #define UP 0x02 /*'A'-'Z'*/ 41 #define XD 0x01 /*'0'-'9','A'-'F','a'-'f'*/ 42 43 int my_isalnum(int); 44 int my_isalpha(int); 45 int my_iscntrl(int); 46 int my_isdigit(int); 47 int my_isgraph(int); 48 int my_islower(int); 49 int my_isprint(int); 50 int my_ispunct(int); 51 int my_isspace(int); 52 int my_isupper(int); 53 int my_isxdigit(int); 54 55 int my_tolower(int); 56 int my_toupper(int); 57 58 extern const short *my_ctype, *my_xtolower, *my_xtoupper; 59 60 /* 61 * 函数与宏重名 62 * 宏只是起替换功能,编译器在预处理时处理; 63 * 可以#undef my_isalnum来屏蔽宏,使用函数, 64 * 或者宏定义在函数下面控制, 65 * 66 * 还有如果函数与宏重名,加括号是使用函数,如(my_isalnum) 67 * (因为宏是替换,(my_isalnum)和my_isalnum(c)不同,同理下), 68 * 如 int (*p)(int) = my_isalnum; 69 * 另外宏和函数重名可以便于后期扩展(此种情形不是),如 70 * #define print() printa() 71 * 可以修改printa()为printa_ex(),便于扩展; 72 * 73 * 因为标准定义,宏函数处理是,从左到右处理,找到宏名,碰到(, 74 * 然后如果宏参数有#或##,参数是宏也不展开,没有才展开,先扩展宏参数再扩展宏。 75 * 宏扩展后同名宏不再扩展,非同名扩展(是同一宏,而不宏参数,宏参数与宏为同一宏,先扩展宏参数再宏); 76 * 虽然#和##存在不会对参数做宏扩展,但对展开后的宏还是会扩展。 77 * 78 * 字符串化操作符#,#x会变成"x"; 79 * 连接符##,x##y会变成xy; 80 * c语言是按词扫描的,如MYFUNCXX中MYFUNC不会被展开; 81 * 预处理器搜索#define定义的符号,字符串常量的内容并不进行检查, 82 * 所以被引号引起的部分也不进行宏扩展 83 * 84 * 头文件如果函数在后,重名宏在前,函数是会被替换的 85 * 86 */ 87 88 /* 89 * (my_ctype[(int)(c)] & (DI|LO|UP|XA)) 可修改成 90 * ((c>=UCHAR_MAX || c<=EOF)? EOF:my_ctype[(int)(c)] & (DI|LO|UP|XA)) 91 */ 92 #define my_isalnum(c) (my_ctype[(int)(c)] & (DI|LO|UP|XA)) 93 #define my_isaplha(c) (my_ctype[(int)(c)] & (LO|UP|XA)) 94 #define my_iscntrl(c) (my_ctype[(int)(c)] & (BB|CN)) 95 #define my_isdigit(c) (my_ctype[(int)(c)] & DI) 96 #define my_isgraph(c) (my_ctype[(int)(c)] & (DI|LO|PU|UP|XA)) 97 #define my_islower(c) (my_ctype[(int)(c)] & LO) 98 #define my_isprint(c) (my_ctype[(int)(c)] & (DI|LO|PU|SP|UP|XA)) 99 #define my_ispunct(c) (my_ctype[(int)(c)] & PU) 100 #define my_isspace(c) (my_ctype[(int)(c)] & (CN|SP|XS)) 101 #define my_isupper(c) (my_ctype[(int)(c)] & UP) 102 #define my_isxdigit(c) (my_ctype[(int)(c)] & XD) 103 #define my_tolower(c) my_tolower[(int)(c)] 104 #define my_toupper(c) my_toupper[(int)(c)] 105 #endif
1 /*my_ctype.c*/ 2 #include <stdio.h> 3 #include "my_ctype.h" 4 /*函数名加上括号,参数宏就不进行替换,因为字符不一致了,无参数宏会替换*/ 5 int (my_isalnum)(int c) 6 { 7 return (my_ctype[c] & (DI|LO|UP|XA)); 8 } 9 10 int (my_isalpha)(int c) 11 { 12 return (my_ctype[c] & (LO|UP|XA)); 13 } 14 15 int (my_iscntrl)(int c) 16 { 17 return (my_ctype[c] & (BB|CN)); 18 } 19 20 int (my_isdigit)(int c) 21 { 22 return (my_ctype[c] & DI); 23 } 24 25 int (my_isgraph)(int c)/*除空格之外的可打印字符*/ 26 { 27 return (my_ctype[c] & (DI|LO|PU|UP|XA)); 28 } 29 30 int (my_islower)(int c) 31 { 32 return (my_ctype[c] & LO); 33 } 34 35 int (my_isprint)(int c) 36 { 37 return (my_ctype[c] & (DI|LO|PU|SP|UP|XA)); 38 } 39 40 int (my_ispunct)(int c)/*除空格、字母、数字之外的可打印字符*/ 41 { 42 return (my_ctype[c] & PU); 43 } 44 45 int (my_isspace)(int c) 46 { 47 return (my_ctype[c] & (CN|SP|XS)); 48 } 49 50 int (my_isupper)(int c) 51 { 52 return (my_ctype[c] & UP); 53 } 54 55 int (my_isxdigit)(int c) 56 { 57 return (my_ctype[c] & XD); 58 } 59 60 int (my_tolower)(int c) 61 { 62 return (my_xtolower[c]); 63 } 64 65 int (my_toupper)(int c) 66 { 67 return (my_xtoupper[c]); 68 }
1 /*my_xctype.c*/ 2 #include <limits.h> 3 #include <stdio.h> 4 #include "my_ctype.h" 5 #if EOF != -1 || UCHAR_MAX != 255 6 #error WORNG CTYPE TABLE 7 #endif 8 /*XLO,XUP是因为字母是26个,XDI为什么?*/ 9 #define XDI (DI|XD) /*0x20|0x01=0x21*/ 10 #define XLO (LO|XD) /*0x10|0x01=0x11*/ 11 #define XUP (UP|XD) /*0x02|0x01=0x03*/ 12 /*转换表*/ 13 static const short my_ctype_tab[257] = {0, 14 BB, BB, BB, BB, BB, BB, BB, BB, 15 BB, CN, CN, CN, CN, CN, BB, BB, 16 BB, BB, BB, BB, BB, BB, BB, BB, 17 BB, BB, BB, BB, BB, BB, BB, BB, 18 SP, PU, PU, PU, PU, PU, PU, PU, 19 PU, PU, PU, PU, PU, PU, PU, PU, 20 XDI, XDI, XDI, XDI ,XDI, XDI, XDI, XDI, 21 XDI, XDI, PU, PU, PU, PU, PU, PU, 22 PU, XUP, XUP, XUP, XUP, XUP, XUP, UP, 23 UP, UP, UP, UP, UP, UP, UP, UP, 24 UP, UP, UP, UP, UP, UP, UP, UP, 25 UP, UP, UP, PU, PU, PU, PU, PU, 26 PU, XLO, XLO, XLO, XLO, XLO, XLO, LO, 27 LO, LO, LO, LO, LO, LO, LO, LO, 28 LO, LO, LO, LO, LO, LO, LO, LO, 29 LO, LO, LO, PU, PU, PU, PU, BB, 30 }; 31 32 const short *my_ctype = &my_ctype_tab[1];
1 /*my_xtolower.c*/ 2 #include <limits.h> 3 #include <stdio.h> 4 #include "my_ctype.h" 5 #if EOF != -1 || UCHAR_MAX != 255 6 #error WRONG TOLOWER TABLE 7 #endif 8 9 static const short tolow_tab[257] = {EOF, 10 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 11 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 12 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 13 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 14 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 15 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 16 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 17 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 18 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 19 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 20 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 21 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 22 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 23 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 24 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 25 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, 26 27 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 28 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 29 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 30 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 31 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 32 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 33 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 34 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, 35 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 36 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 37 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 38 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 39 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 40 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 41 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 42 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff}; 43 44 const short *my_xtolower = &tolow_tab[1];
1 /*my_t_ctype.c*/ 2 #include <assert.h> 3 #include <limits.h> 4 #include <stdio.h> 5 #include "my_ctype.h" 6 7 static void prclass(const char *name, int (*fn)(int)) 8 { 9 int c; 10 11 fputs(name, stdout); 12 fputs(": ", stdout); 13 for(c = EOF; c <= UCHAR_MAX; ++c) 14 if((*fn)(c)) 15 fputc(c, stdout); 16 fputs("\n", stdout); 17 } 18 19 int main(void) 20 { 21 char *s; 22 int c; 23 24 prclass("my_ispunct", &my_ispunct); 25 prclass("my_isdigit", &my_isdigit); 26 prclass("my_islower", &my_islower); 27 prclass("my_isupper", &my_isupper); 28 prclass("my_isalpha", &my_isalpha); 29 prclass("my_isalnum", &my_isalnum); 30 31 for(s = "0123456789"; *s; ++s) 32 assert(my_isdigit(*s) && my_isxdigit(*s)); 33 for(s = "abcdefABCDEF"; *s; ++s) 34 assert(my_isxdigit(*s)); 35 for(s = "abcdefghigklmnopqrstuvwxyz"; *s; ++s) 36 assert(my_islower(*s)); 37 for(s = "ABCDEFGHIGKLMNOPQRSTUVWXYZ"; *s; ++s) 38 assert(my_isupper(*s)); 39 for(s = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~"; *s; ++s) 40 assert(my_ispunct(*s)); 41 for(s = "\f\n\r\t\v"; *s; ++s) 42 assert(my_isspace(*s) && my_iscntrl(*s)); 43 assert(my_isspace(' ') && my_isprint(' ')); 44 assert(my_iscntrl('\a') && my_iscntrl('\b')); 45 46 for(c = EOF; c < UCHAR_MAX; ++c){ 47 if(my_isdigit(c)) 48 assert(my_isalnum(c)); 49 if(my_isupper(c)) 50 assert(my_isalpha(c)); 51 if(my_islower(c)) 52 assert(my_isalpha(c)); 53 if(my_isalpha(c)) 54 assert(my_isgraph(c) && !my_isdigit(c)); 55 if(my_isalnum(c)) 56 assert(my_isgraph(c) && !my_ispunct(c)); 57 if(my_ispunct(c)) 58 assert(my_isgraph(c)); 59 if(my_isgraph(c)) 60 assert(my_isprint(c)); 61 if(my_isspace(c)) 62 assert(c == ' ' || !my_isprint(c)); 63 if(my_iscntrl(c)) 64 assert(!my_isalnum(c)); 65 } 66 67 for(s = "0123456789"; *s; ++s) 68 assert((my_isdigit)(*s) && (my_isxdigit)(*s)); 69 for(s = "abcdefABCDEF"; *s; ++s) 70 assert((my_isxdigit)(*s)); 71 for(s = "abcdefghigklmnopqrstuvwxyz"; *s; ++s) 72 assert((my_islower)(*s)); 73 for(s = "ABCDEFGHIGKLMNOPQRSTUVWXYZ"; *s; ++s) 74 assert((my_isupper)(*s)); 75 for(s = "!\"#%&'();<=>?[\\]*+,-./:^_{|}~"; *s; ++s) 76 assert((my_ispunct)(*s)); 77 for(s = "\f\n\r\t\v"; *s; ++s) 78 assert((my_isspace)(*s) && (my_iscntrl)(*s)); 79 assert((my_isspace)(' ') && (my_isprint)(' ')); 80 assert((my_iscntrl)('\a') && (my_iscntrl)('\b')); 81 82 for(c = EOF; c <= UCHAR_MAX; ++c){ 83 if((my_isdigit)(c)) 84 assert((my_isalnum)(c)); 85 if((my_isupper)(c)) 86 assert((my_isalpha)(c)); 87 if((my_islower)(c)) 88 assert((my_isalpha)(c)); 89 if((my_isalpha)(c)) 90 assert((my_isalnum)(c) && !(my_isdigit)(c)); 91 if((my_isalnum)(c)) 92 assert((my_isgraph)(c) && !(my_ispunct)(c)); 93 if((my_ispunct)(c)) 94 assert((my_isprint)(c)); 95 if((my_isspace)(c)) 96 assert(c == ' ' || !(my_isprint)(c)); 97 if((my_iscntrl)(c)) 98 assert(!(my_isalnum)(c)); 99 } 100 puts("success testing 'my_ctype.h'"); 101 return 0; 102 }