一天一个CRT函数 strcspn

来源:互联网 发布:win10添加网络凭证 编辑:程序博客网 时间:2024/05/19 23:13

刚看到strcspn的实现时,很是惊诧!靠,这么优秀的算法,分析了老半天才搞明白。世界上为啥聪明的人这么多呢?

1.介绍

原型:size_t strcspn(const char *pstr, const char *strCharset)

MSDN解释为:在字符串pstr中搜寻strCharsret中所出现的字符,返回strCharset中出现的第一个字符在pstr中的出现位置。简单的说,若strcspn返回的数值为n,则代表字符串strCharsrt开头连续有n个字符不包含在pstr内的字符。

2.实现

/***
int strcspn(string, control) - search for init substring w/o control chars

Purpose:
returns the index of the first character in string that belongs
to the set of characters specified by control. This is equivalent
to the length of the length of the initial substring of string
composed entirely of characters not in control. Null chars not
considered.

Entry:
char *string - string to search
char *control - set of characters not allowed in init substring

Exit:
returns the index of the first char in string
that is in the set of characters specified by control.

Uses:

Exceptions:

***/
inline int tStrCSpn(const tChar *pStr, const tChar *pStrSet)
{
// map有32个字节的大小,也就是256个bit,可把map堪称一个2维数组[32][8]
unsigned char map[32] = {0};

// 每个ASCII码(设为c)有8bit,把它分成2部分,低3位构成下标j(通过c&7(2进制为111)),
// 高5位构成下标i(通过c>>3得到)。这样在map[i][j]中置1表示字符存在
while(*pStrSet)
{
map[*pStrSet >> 3] |= (1 << (*pStrSet & 7));
pStrSet++;
}

map[0] |= 1;

int count = 0;
while(!(map[*pStr >> 3] & (1 << (*pStr & 7))))
{
count++;
pStr++;
}

return count;
}
 
3.分析

例如:对于字符’1’,其ASCII码味0x31,右移3位得到6,和7与运算得到1,也就是在map[6]中的第一位.

一个unsigend char有8位,拆违高5位与低3位。前5位的范围有0~32,所以申请32大小的数组map。直接将前5位映射成成数组下标,后3位范围0~7,正好是每一项char(8bit)。这个算法把时间与空间结合起来,效率非常高。

4.后记

如果是我自己来写个算法寻找两个字符串中相同的字符,可能就会写双重for循环了,呵呵~strcspn的巧妙就在于空间和时间结合上的考虑,用查表的方式来提升速度~厉害!!

原创粉丝点击