一年前的东西

本文详细解析了strtok和strtok_r函数的工作原理及实现方式,重点介绍了使用hash table delimiter进行字符串分割的方法。通过对比两种函数,强调了strtok_r在多线程环境下的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

去年的一个笔记,翻出来看看,两个程序原理是一样的,只是MS的strtok用了hash tabledelimeter(也就是匹配符)可以有很多个,满足其中一个就可以,不需要全部匹配也就是说:ct= 'abc',那么直要含有a或者b或者c的字符串都会被分割,而不是abc连着分割(刚开始都记错了,囧)PS:VC的调试技巧还是学的不够透彻啊~~~~~~~,又学了一个新技巧
char *strtok (char *s,char *ct)
{
	char *t;
	if (!s) 
		s = ts;                /* use previous token if none specified */
	if (!(s && *s))
		return NULL;        /* no tokens */
	/* find any leading delimiters */
	/* 注意是leading,就是刚开始的delimeter
	这一段do-while代码的作用是如果字符串开始就有相应的delimeter,就把他们去除,如果不加这段代码也行,
	但是光下面这两个for循环,很难简单判断输出字符的后面是否还是delimeter,会输出一些空值*/
	do 
	for (t = ct, ts = NULL; *t; t++) //t等于分隔符号,ts初始值为null,检测分隔符是否为空,弱不为空,则t++
	//ts在非第一次的时候保存着上一次的字符串,要重新赋给空置,所以循环里面一定要
	{
		if (*t == *s)
		{//如果分隔符号和那个字符串相等
			if (*(ts = ++s)) 
				break;        /* yes, restart seach if more in string */
			return ts = NULL;                /* else no more tokens */
		}
	}
	while (ts);                        /* continue until no more leading delimiters */
	/* can we find a new 注意,是new   delimiter? */
	for (ts = s; *ts; ts++) 
		for (t = ct; *t; t++) 
		{
			if (*t == *ts)
			{
				*ts++ = '\0';                /* yes, tie off token at that point */
				return s;                        /* return our token */
			}
		}
	ts = NULL;                        /* no more tokens */
	return s;                        /* return final token */
}
char*  strtok_r(char* string_org,const char* demial)
 {
	 static unsigned char* last; //保存分隔后剩余的部分
	 unsigned char* str;         //返回的字符串
	 const unsigned char* ctrl = (const unsigned char*)demial;//分隔字符
	  
	 //hash表
	 unsigned char map[32]; 
	 int count;
	 for (count =0; count <32; count++)
		     {
		     map[count] = 0;
		     }
	  
	 //把匹配字符放入表中
	 //放入的算法是把匹配字符右移3位,相当于除以8,的数值 并上(加上)
	 //匹配字符与7,得到低3位,得出的结果,是把1左移的位数。最大左移位数是7,
	 do 
	     {
		     map[*ctrl >> 3] |= (1 << (*ctrl & 7));
			 /*'a' 是97,'b'==98 都是映射到了map[12]			 
			   会映射到map1[12]的共有8个字符,要如何区分这8个字符,则是除以8的余数			   
			'a'除以8的余数是1,'b'除以8的余数是2, 
			 如果map[12] = 0000 0110,则表示'a','b'映射进来了*/
		     } 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';//当找到时,把匹配字符填为0,并且把str指向下一位。
				         break; //退出循环             
				         }
			             
			     }
		     
		 last =str; // 把剩余字符串的指针保存到静态变量last中。
		     
		 if (string_org == (char*)str)
			     {
			     return NULL; //没有找到,也就是没有移动指针的位置,返回NULL
			     }
		 else
			     {
			     return string_org; //找到了,返回之前字符串的头指针
			     }
  }





                
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值