您的位置:首页 > 其它

一天一个CRT函数 strcspn

2010-02-06 12:02 274 查看
刚看到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的巧妙就在于空间和时间结合上的考虑,用查表的方式来提升速度~厉害!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: