本来今天是计划要写进制转换的,但是博主又突然发现另一个比较好玩的东西,所以果断决定先来这个;
相信大家或多或少都用过ctype.h (标准c)/ cctype(c++)这个库中的函数:
函数原型:
函数功能:
函数返回
int isalpha(char ch)
检查ch是否是字母
是字母返回非0(在vs2015中为2),否则返回0
int isdigit(char ch)
检查ch是否是数字(0-9)
是返回非0,否则返回0
int islower(int ch)
检查ch是否小写字母(a-z)
是返回非0,否则返回0
int isupper(int ch)
检查ch是否是大写字母(A-Z)
是返回非0,否则返回0
int tolower(int ch) 将ch字符转换为小写字母 返回与ch相应的小写字母
int isalnum(int ch)
检查ch是否是字母或数字
是字母或数字返回非0,否则返回0
int isascii(int ch) 测试参数是否是ASCII码0-127 是返回非0,否则返回0
但是大家在想的时候有没有认真的思考过,这些函数是如何实现的?
先附上这个神奇好玩的代码:
#define U 0x01 //写字母
#define L 0x02 //小写字母
#define D 0x04 //数字
#define C 0x08 //控制字符
#define P 0x10 //可打印字符
#define S 0x20 //空格符/跳格符(控制字符)/换行符
#define X 0x40 //16进制基数32
#define SP 0x80 //空格
extern unsigned char ctype[];
extern char ctmp;
unsigned char ctype[] = {0, /* 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 */
//剩下的都初始化为零;
}
字数原因,只在这里贴了两个,其他的都是同一个思想,以此类推就好。int isupper(int c){ return _ctype[c] & U;}int toupper(int c){ if (_ctype[c] & L) return c - ('a' - 'A');else return c; }
今天看到的这个是通过映射和位运算的方式解释的,他先将整个ASCII表分区(按目标的分类,比如大小写字母,比如数字等每一种类用一个可以代表的值来表示),不同的部分用不同的值表示,然后用了指针在运算时进行直接读取表中数值,避免了传统方式上的遍历检索,根据相应下标映射出当前区域的定义好的值,与目标区域的值进行位运算,然后返回结果。
其实博主在看到这个神奇的东西之前觉得里面的函数功能是应该可能是这样实现的(以其中判断字符是否大写和转换大小写为例):
int isupper(int ch)
{
if (ch >=65 && ch <= 90)
return 1;
else
return 0;
}
不知道都多少人跟我之前的想法一样 哈哈.....char toupper(int ch){if (ch >=97 && ch <= 122)return (ch - 32);elsereturn ch;}