一般情况下判断一个字符为大写的方法用if 语句来判断,比如
- If (c>=’A’&&c<=’Z’) return true;
小写的方法与之类似
因为字符A-Z,a-z在ASCII上是连续的,所以一个范围判断就可以了,假设某些字符在ASCII上是不连续的,比如十六进制数,0-9,A-H,那么if语句里面就需要两个范围判断了
- If((c>=’0’&&c<=’9’)||(c>=’A’&&c<=’H’)) return true;
再者假设有更多的范围,那么if的条件部分就越长,判断条件长了,效率自然就低了。
Linux中使用空间换时间的方法来做,基本方法为:
建立一个256个元素的unsigned char _ctypes[]全局数组,每一个数组元素的值代表其下标所对应的ASCII码的类别,比如大写字母A,其ASCII码为65,那么_ctypes[65]中的8个位代表了其所属类别,8个位最多有8中并列的属性。
在Linux中定义了8种属性,其宏为:
- #define _U 0x01 /* upper */
- #define_L 0x02 /* lower */
- #define_D 0x04 /* digit */
- #define_C 0x08 /* cntrl */
- #define_P 0x10 /* punct */
- #define_S 0x20 /* white space (space/lf/tab) */
- #define_X 0x40 /* hex digit */
- #define_SP 0x80 /* hard space (0x20) */
Linux中将_ctypes初始化为:
- const unsigned char _ctype[]= {
- _C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
- _C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
- _C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
- _C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
- _S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
- _P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
- _D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
- _D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
- _P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
- _U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
- _U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
- _U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
- _P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
- _L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
- _L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
- _L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
- 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
- _S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
- _P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
- _U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
- _U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
- _L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
- _L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
然后Linux定义了一个宏:
- #define __ismask(x)(_ctype[(int)(unsigned char)(x)])
此宏获得一个字符所对应数组中的标志值,
Linux中又定义了一些宏用以辅助判断一个字符类别:
- #define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0) //大写,小写,数字
- #define isalpha(c) ((__ismask(c)&(_U|_L)) != 0) //大写,小写
- #define iscntrl(c) ((__ismask(c)&(_C)) != 0) //控制
- #define isdigit(c) ((__ismask(c)&(_D)) != 0) //数字
- #define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0) //字符是否图形
- #define islower(c) ((__ismask(c)&(_L)) != 0) //是否小写
- #define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)//是否可打印
- #define ispunct(c) ((__ismask(c)&(_P)) != 0) /* punct */
- /* Note: isspace() must return false for %NUL-terminator */
- #define isspace(c) ((__ismask(c)&(_S)) != 0) /*(space/lf/tab) */
- #define isupper(c) ((__ismask(c)&(_U)) != 0) //是否大写
- #define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0) //是否十六进制数
- #define isascii(c) (((unsigned char)(c))<=0x7f) //是否ASCII
- #define toascii(c) (((unsigned char)(c))&0x7f) //转为ASCII
上述宏在程序中可以直接使用了,比如想判断某个字符是否为大写
- If (isupper(‘A’)) return true;
- If (isxdigit(‘B’)) return true;
比如:
- static inline unsigned char __tolower(unsigned char c)//转为小写字母
- {
- if (isupper(c))
- c -= 'A'-'a';
- return c;
- }
- static inline unsigned char __toupper(unsigned char c)//转为大写字母
- {
- if (islower(c))
- c -= 'a'-'A';
- return c;
- }
Linux中方法已经描述完了,下面对比优劣。
普通方法:
优势:简单易懂,不额外占用数据空间
劣势:效率较第二种低,需要很多条件判断指令
Linux方法:
优势:速度快,一次性位操作即可完成任务,优雅。
劣势:额外的占用了空间。
综合:
如果自己随便写个小小程序的话,第一种方法够用了。如果是一个真实的项目的,推荐第二种方法。
转载:http://blog.csdn.net/panweiguozhou/article/details/6831232