博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字符串处理——判断是否是数字或字母
阅读量:3958 次
发布时间:2019-05-24

本文共 3142 字,大约阅读时间需要 10 分钟。

最近写的代码涉及到字符串的判断,主要是判断一个字符是否是十进制数字、十六进制数字、大写字母、小写字母。学到了一些新知识。

最开始我采用最简单暴力的方法:

char ch;if(ch >= '0' && ch <= '9')  //十进制数字if(ch >= '0' && ch <= '9' || (ch >= 'A' && ch <= 'F') || (ch >= 'a' && ch <= 'f')) //十六进制if(ch >= 'A' && ch <= 'Z') //大写字母if(ch >= 'a' && ch <= 'z') //小写字母if(ch >= 'A' && ch <= 'Z' || (ch >= 'a' && ch <= 'z')) //字母

后来由于需要性能优化,我就想,能不能更快呢?有没有别的什么办法呢?

于是我查了查ASCII码,搞了一个位操作版

if((ch & 0xf8) == 0x30 || (ch & 0xfe) == 0x38) // 十进制if((ch & 0xd8) == 0x40 && (ch & 0x07) != 0x00 && (ch & 0x07) != 0x07) // 'a'- 'f' or 'A' - 'F'

(咳咳,这里由于字母的ASCII码太难以归纳,还不如直接用最暴力的办法,我就没搞位操作版)

这里解释一下,‘0’ - '9’可以拆成两部分:
‘0’ - ‘7’ : 0011 0000 - 0011 0111
‘8’ - ‘9’ : 0011 1000 - 0011 1001
前者是前5位为0011 0,后者是前7位为0011 100。

至于’a’- ‘f’ 和 ‘A’ - ‘F’,前5位分别为:0110 0 和0100 0。(ch & 0xd8) == 0x40就是确定这前5位。然后后三位全0和全1的不是a-f,所以再进行两次判断。

写到这里,我本来美汁儿汁儿,直到我看到……别人的代码用了一个函数:isdigit

嗯?介系嘛?一查,人家C++早就想好了、做好了这个功能……orz

话说回来,这个函数包含在ctype.h头文件中。这个头文件中包含了我最开始说的那些各种判断:

isdigit(int)   //十进制数字isxdigit(int)  //十六进制数字isalpha(int)   //字母isupper(int)   //大写字母islower(int)   //小写字母

(当然,除了这些还有一些别的功能,感兴趣的可以看一看这个头文件)

那么,C++是怎么实现这些功能的呢?

简单来说就是:空间换时间。

#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) */unsigned char _ctype[] = {
0x00, /* EOF */_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 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 160-175 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 176-191 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 192-207 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 208-223 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 224-239 */0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; /* 240-255 */}#define isdigit(c) ((_ctype+1)[c]&(_D))

可以看到,C语言做了一个长度为257的数组,将每一个可能的字符都做了对应,然后为其设置标志位,然后只要查询对应字符的标志位,就知道是否是数字、字母、或者其他了。

这里以数字为例,字符’0’-‘9’,就对应48-57(十进制),可以看到,在_ctype数组中,将其全部赋值为_D,这样调用isdigit时,就是查看是否设置了_D标志位,设置了就是数字,否则就不是。

转载地址:http://ltxzi.baihongyu.com/

你可能感兴趣的文章
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Mysql索引
查看>>
OGNL投影查询
查看>>
OGNL投影查询
查看>>
OGNL投影查询
查看>>
Redis之RDB和AOF持久化
查看>>
Redis之RDB和AOF持久化
查看>>
Servlet3.0
查看>>
Servlet3.0
查看>>
Servlet3.0
查看>>
SQL 语句的解析过程
查看>>
SQL 语句的解析过程
查看>>
SQL 语句的解析过程
查看>>
Java类文件结构
查看>>