#include <stdio.h> #include <string.h> #include <assert.h> #include <stdlib.h> int main(int argc, char* argv[]) { char dst[] = "abcxdeyf"; char *src = "afbecd"; printf("%d", strspn(dst, src)); return 0; }
输出:
3
strspn返回dst中第一个不在src中出现的字符下标。
上面dst中的字符x是第一个不在字符串src中出现的字符,下标为3.
y是第二个不在src中出现的字符,其余字符都在src中出现过。
;*** ;int strspn(string, control) - find init substring of control chars ; ;Purpose: ; Finds the index of the first character in string that does belong ; to the set of characters specified by control. This is ; equivalent to the length of the initial substring of string that ; consists entirely of characters from control. The '\0' character ; that terminates control is not considered in the matching process. ; ; Algorithm: ; int ; strspn (string, control) ; unsigned char *string, *control; ; { ; unsigned char map[32]; ; int count; ; ; for (count = 0; count < 32; count++) ; map[count] = 0; ; while (*control) ; { ; map[*control >> 3] |= (1 << (*control & 7)); ; control++; ; } ; if (*string) ; { ; while (map[*string >> 3] & (1 << (*string & 7))) ; { ; count++; ; string++; ; } ; return(count); ; } ; return(0); ; } ; ;Entry: ; char *string - string to search ; char *control - string containing characters not to search for ; ;Exit: ; returns index of first char in string not in control ; ;Uses: ; ;Exceptions: ; ;*******************************************************************************
该算法的巧妙之处是map的设计和使用。map是一个由32个字节组成的数组,它相当于有256个二进制位,每位映射到一个ASCII码。每个ASCII码(设为c)有8位,把它分为2部分,低3位构成下标j(通过c & 7得到),高5位构成下标i(通过c>>3得到),下标j就是在map[i]中的第j位。
例如,对于字符‘1’,其ASCII码是0x31,>>3得6,&7得1,也就是它在map[6]的第1位,通过1 << 1得1,然后与map[6]相与使map[6]的第一位为1。
又如,对于字符’C’,其ASCII码为十进制67,即二进制01000 011,
求map[i]中的i,
*control >> 3,即01000 011右移3位得高5位01000,所以i为8;
求j,j的意思是map[i]中的第几位为1(map[i]是一个字节8个bit)
(1 << (*control & 7)),(*control & 7)得*control的低3位,这里为011
然后1 << (*control & 7)即1<<3即1左移3位100,所以
map[i]=二进制100,
所以字符C用map表示即为:map[6]这个字节的第3个bit为1,其余bit为0.