一、 Strpbrk (string pointer break)
//////////////////////////////////////////////////////////////////////////////////////////////////
// 函 数: char * strpbrk(const char * string,const char * control)
// 功 能: 检查字符串string和control中第一个相同的字符
// 参 数:
// 返 回: 返回字符串string和control中第一个相同的字符后面的string字符串
//////////////////////////////////////////////////////////////////////////////////////////////////
char * strpbrk(const char * string,const char * control)
{
const char * str = (const char *)string;
const char * ctrl = (const char *)control;
unsigned char map[32];
int count = 0;
/*clear the map*/
memset(map,0,32*sizeof(unsigned char));
/*set bits in control map*/
while( *ctrl )
{
map[*ctrl >> 3] |= (0x01 << (*ctrl & 7));
ctrl++;
}
while ( *str )
{
if (map[*str >> 3] & (1 << (*str & 7)))
{
return((char *)str);
}
str++;
}
return(NULL);
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// 例:string = "129th";
// control = "b295";
//////////////////////////////////////////////////////////////////////////////////////////////////
仔细体会下上面的代码,不禁暗暗叫绝。
1、 首先定义个大小为32个字符的map,为什么要这么划一道呢?因为在ASCII表能表示128个字符,而扩展后的ASCII却能表示256个字符,一个字符是8位,32 X 8 = 256,即:在这个map里,每个字符的8各位可以表示8个字符。
2、 把map初始化后,便开始设定每个控制字符的map,这里可以提出个问题:为什么取3和7作为操作数?原因在这儿:左移3位即是除以8(*ctrl >> 3),表示数组的下标,map数组的每个下标才能对应8个目标,这样才能构造出容纳256个字符的能力,比如:map[0]可以表示出0~7的字符,map[1]可以表示出8~15的字符,… map[6]就能表示出48~55的字符(即字符’0’~’7’)。如图1-1所示:
图1-1 字符map构造
把字符串control = "b295";构造进map,首先字符’b’,二进制为:0110 0010,右移3位(除以8):0000 1100,即十进制数:12;也就是map[32]的下标12确定了,也就是表面字符 ’b’ 在map里的位置是第12位。
(0x01 << (*ctrl & 7):b & 7后的结果为:0000 0010,十进制2; 0x01左移2位(即1乘以4),结果为:0000 0100,十进制为4;
最后用map[12]的初始值0 与上面的结果做位逻辑或赋值,得到map[12] = 4即0000 0100,见上图1-1所示,下标为12的时候,从低位数到第三个数据是1,而对应的十进制数中第三个数字98正是字符’b’。
依此计行之,挨个把字符构造进了map。
3、 剩下的就是查找了,思路就是:把该字符依照上面的方法定位该字符在map里的对应下标,然后把该字符串与map里对应下标的值进行判断。 先把字符’1’ & 7,结果如图1-2所示:
图1-2 查找逻辑
把最后的结果(0000 0010)与map[12]中的(0000 0100)做按位与计算的(0000 0000),显然不是需要的结果,果断str++ ;
轮到字符’2’了,冲入上面的操作后,得到的结果(0000 0100),再与map[12]按位与,得到结果(0000 0100),返回剩下的字符串。