strlok源代码理解
看到strlok的源代码,有几个地方不明白,高手指教。函数实现的功能:
原型:extern char *strtok(char *s, char *delim);
用法:#include <string.h>
功能:分解字符串为一组标记串。s为要分解的字符串,delim为分隔符字符串。
说明:首次调用时,s必须指向要分解的字符串,随后调用要把s设成NULL。
strtok在s中查找包含在delim中的字符并用NULL('\0')来替换,直到找遍整个字符串。
返回指向下一个标记串。当没有标记串时则返回空字符NULL。
char * __cdecl strtok (char * string,const char * control)
{
unsigned char *str;
const unsigned char *ctrl = control;
unsigned char map[32];
int count;
#ifdef _MT
_ptiddata ptd = _getptd();
#else /* _MT */
static char *nextoken;
#endif /* _MT */
/* Clear control map */
for (count = 0; count < 32; count++)
map[count] = 0;
//下面这段代码是做什么用的啊?特别是 map[*ctrl >> 3] |= (1 << (*ctrl & 7))是实现什么啊?????
do {
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
} while (*ctrl++);
if (string)
str = string;
else
#ifdef _MT
str = ptd->_token;
#else /* _MT */
str = nextoken;
#endif /* _MT */
while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
str++;
string = str;
//这个也不是很明白
for ( ; *str ; str++ )
if ( map[*str >> 3] & (1 << (*str & 7)) ) {
*str++ = '\0';
break;
}
#ifdef _MT
ptd->_token = str;
#else /* _MT */
nextoken = str;
#endif /* _MT */
if ( string == str )
return NULL;
else
return string;
} --------------------编程问答-------------------- 帮忙 up
--------------------编程问答-------------------- 我也不是很清楚
不过
unsigned char map[32];
map字符数组就像当与一个map表了
unsigned char的0-255被映射到map表里
//下面这段代码是做什么用的啊?特别是 map[*ctrl >> 3] |= (1 << (*ctrl & 7))是实现什么
这里的*ctrl >> 3 就像当于表号
256个数被映射到32个表里的列数
而1 << (*ctrl & 7) 相当于表值
比如字符"01234567"
它们就会被映射到map(6)里
而对应的map(6)对应的值就会是1111 1111 从左到右依次对应"01234567"里面的01234567。
这样做的好处就是节省空间了 至少我现在看来
if (string)
str = string;
else
#ifdef _MT
str = ptd->_token;
#else /* _MT */
str = nextoken;
#endif /* _MT */
就是第二次输入NULL的原因吧~
其他的也类似吧~
能力有限 出错不负责! --------------------编程问答-------------------- lmlmlmnew():
map[*ctrl >> 3] |= (1 << (*ctrl & 7))
看了你说的这个,好象还是不太明白,能不能说详细点啊! --------------------编程问答-------------------- const unsigned char *ctrl = control;
*ctrl 是unsigned char 的 所以他的范围是0-255
*ctrl>>3 右移3位 相当于除8
0-255 除 8之后 就在 0-31之间
好比假设*ctrl = '0'的ASCII码为 48
那么 *ctrl>>3 就是 6了
map[*ctrl>>3] 就相当于 map[6]
(1 << (*ctrl & 7))呢
(*ctrl & 7)就是1 左移的位数
比如'0'-'7'属于属于map6[6]里面的
假若 *ctrl = '0',因为(*ctrl & 7) = 0 所以 1就左移 1 << 0位, map[6] = 0000 0001
假若 *ctrl = '1',其ASCII为49也就是0011 0001, *ctrl & 7 = 0000 0001,所以1就左移 1 << 1位, 就是说map[6] = 0000 0010;
同理 *ctrl = '2', ASCII为 0011 0010,*ctrl & 7 = 2,所以1就左移 1 << 2,
map[6] = 0000 0100
因此可以看出 这个简单的运算把0-255的ASCII都映射到了 map[32]里面 这不就相当于减少了转换所需要的内存空间么.....
--------------------编程问答-------------------- map[*ctrl >> 3] |= (1 << (*ctrl & 7))
之所以用 |= 就是把*ctrl里面的所有字符都映射到map[6]里~~
结贴吧 大兄弟 就等你100分下锅呢。。。。
~不看功劳看苦劳~
虽然说的不定全对 不过打这么多字也不容易啊~ --------------------编程问答-------------------- 错了
map[*ctrl >> 3] |= (1 << (*ctrl & 7))
之所以用 |= 就是要把*ctrl里面的所有字符通过循环都映射到map里~~ --------------------编程问答-------------------- lmlmlmnew() :
很感谢你,你说的大概明白了,不过还在进一步的查资料,你的分肯定是会给你的!
非常感谢!
--------------------编程问答-------------------- 以前对ASCII这个东西没仔细想,这下才知道这几个句子的用处了,还需多多努力,多多学习啊! --------------------编程问答-------------------- lmlmlmnew() :
do {
map[*ctrl >> 3] |= (1 << (*ctrl & 7));
} while (*ctrl++);
这段中,你说是做256到32的映射,还是很同意的,但是对于映射的具体方式觉得你理解有误,首先(1 << (*ctrl & 7))我觉得是取(*ctrl)低3位然后右移(不是左移)即相当于除2,就是说取第2,3位,然后循环映射到map[*ctrl >> 3]上!
但是在后面的检测过程中:
//这个也不是很明白
for ( ; *str ; str++ )
if ( map[*str >> 3] & (1 << (*str & 7)) ) {
*str++ = '\0';
break;
}
这个过程实际上就是检册过程,但是还是不是很理解,如果说刚才ctr="0",0的ASCII码是48,则映射的时候把它映射到map[6]|=(1<<(*ctrl&7))=0,则map[6]=0;这个时候不满足判断的条件,则检测不到啊~ --------------------编程问答-------------------- 这段中,你说是做256到32的映射,还是很同意的,但是对于映射的具体方式觉得你理解有误,首先(1 << (*ctrl & 7))我觉得是取(*ctrl)低3位然后右移(不是左移)即相当于除2,就是说取第2,3位,然后循环映射到map[*ctrl >> 3]上!
首先 << 这个符号:
按位左移运算符 (<<)
左移表达式的位。
result = expression1 << expression2
参数
result
任何变量。
expression1
任何表达式。
expression2
任何表达式。
说明
<< 运算符把 expression1 的所有位向左移 expression2 指定的位数。例如:
var temp
temp = 14 << 2
变量 temp 的值为 56,因为 14 (即二进制的 00001110)向左移两位等于 56 (即二进制的 00111000)。
我不知道你为什么说它是“(*ctrl)低3位然后右移”。
这是个左移的符号阿 不可能是右移的。 --------------------编程问答-------------------- 对于 << 这个运算符 没有左值和右值之分
常量也能作为左值的~~
--------------------编程问答-------------------- 但是在后面的检测过程中:
//这个也不是很明白
for ( ; *str ; str++ )
if ( map[*str >> 3] & (1 << (*str & 7)) ) {
*str++ = '\0';
break;
}
这个过程实际上就是检册过程,但是还是不是很理解,如果说刚才ctr="0",0的ASCII码是48,则映射的时候把它映射到map[6]|=(1<<(*ctrl&7))=0,则map[6]=0;这个时候不满足判断的条件,则检测不到啊~
这就得在调试中看看了,我也发现如果这么简单的理解的话还有一些问题。
手头没环境 得晚上回家去试试~~
不过得加班>.<"" --------------------编程问答-------------------- mark 学习 --------------------编程问答--------------------
映射前:
map[6] = 0 | (00000001 << (00110000 & 00000111)
map[6] = 00000001 //map[6] 是第7组的标志, 一组8个元素。
验证:
map[*str > > 3] & (1 < < (*str & 7))
map[6] & (00000001 << (00110000 & 00000111)
00000001 & 00000001 = 1
验证成功,将下一位设置为*str++ = '\0'; over!
补充:.NET技术 , VC.NET