strtok函数源码

今天用到strtok时,总感觉怪怪的,为啥第二次调用第一个参数要用NULL, 难道是函数内部保存了当前的状态,假如这样的话,那就不能对多个串交叉调用strtok了,而且保存这个状态的不是全局变量就是static变量。 于是看了他的源码,有几个不同的版本,思想是一样的。 感觉写的挺巧妙的,深深的折服这些写库函数的牛人了。 下面是源码

版本一

    char *s;            /* string to search for tokens */
    const char *delim;  /* delimiting characters */
{
    static char *lasts;
    register int ch;

    if (s == 0)
	s = lasts;
    do {
	if ((ch = *s++) == '\0')
	    return 0;
    } while (strchr(delim, ch));
    --s;
    lasts = s + strcspn(s, delim);
    if (*lasts != 0)
	*lasts++ = 0;
    return s;
}

上面用到了strcspn函数,这个函数返回值是n,表示s的前n个字符都没有在delim中出现。原理是这样的,函数在一开始判断第一个参数是不是空,假如是的话,也就是第二次调用这个函数了,那么把上一次的状态last赋值给要返回的串,然后那个do实现的功能其实就是strspn函数,这个函数的返回值是n,代表 s的前n个字符全部在delim出现。也就是说do实现的是跳过s中字符属于分隔符的字符。 然后通过下面的strcspn真正截取需要的字符数。所以last就指向了下一个分隔符或者字符末尾。然后判断last是否是末尾,假如不是的话,把当前的字符也就是分隔符标记成0,其实就是把前一段字符截断了。last指向了下一个字符。 然后返回s。


版本二 把do直接用 strspn函数代替,思想一样的


#include  /* strspn() strcspn() */
char *strtok(char * str, const char * delim)
{
    static char* p=0;
    if(str)
        p=str;
    else if(!p)
        return 0;
    str=p+strspn(p,delim);
    p=str+strcspn(str,delim);
    if(p==str)
        return p=0;
    p = *p ? *p=0,p+1 : 0;
    return str;
}


第三个版本直接是 没有使用任何函数,用的是哈希实现,这个哈希的妙处真是没谁了,这才是真正c语言程序好不好

char*  strtok_r(char* string_org,const char* demial) {
	static unsigned char* last; 
	unsigned char* str;         
	const unsigned char* ctrl = (const unsigned char*)demial;
	unsigned char map[32]; 
	int count;
	
	for (count =0; count <32; count++){
		map[count] = 0;
	}   
	do {
		map[*ctrl >> 3] |= (1 << (*ctrl & 7));
	} while (*ctrl++);     
	if (string_org){
		str = (unsigned char*)string_org;
	} else{
		str = last;
	}
	while ((map[*str >> 3] & (1 << (*str & 7)))  && *str){
		str++;
	} 
	string_org = (char*)str; 
	for (;*str; str++){
		if ( map[*str >> 3] & (1 << (*str & 7))){
			*str++ = '\0';
			break;         
		}         
	}    
	last =str;    
	if (string_org == (char*)str){
		return NULL; 
	}else{
		return string_org;
	}
}





你可能感兴趣的:(strtok函数源码)