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 }