strtok源码剖析 位操作与空间压缩

地址:http://blog.csdn.net/morewindows/article/details/8740315转载请标明出处,谢谢。

欢迎关注微博:http://weibo.com/MoreWindows      

strtok源码剖析

       strtok函数可以用于分隔字符串,最近看了下这个函数的源代码,其中有

[cpp]  view plain copy
  1. unsigned char map[32];  
  2. /* Clear control map */  
  3. for (count = 0; count < 32; count++)  
  4. map[count] = 0;  
  5.   
  6. /* Set bits in delimiter table */  
  7. do {  
  8.     map[*ctrl >> 3] |= (1 << (*ctrl & 7));  
  9. while (*ctrl++);  

    这段代码非常有意思,第一眼可能不明白,为什么用个unsigned char map[32];数组来保存分隔字符。下面的map[*ctrl >> 3] |= (1 << (*ctrl & 7));更加有点古怪。在网上查了下,并没有文章来解释,因此写篇博客来解释说明下。

    这个长为32的数组与后面的左移,右移操作看起来迷惑,其实如果看过《位操作基础篇之位操作全面总结》(http://blog.csdn.net/morewindows/article/details/7354571)的“位操作与空间压缩”便不难想到,这里其实是个位操作的空间压缩技巧。因此char类型的数据只会从0255,因此建立一个哈希表来记录哪些字符要分割,需要则标记为1,否则标记为0,然后在分隔字符串时,就能直接判断字符串的该位置是否要分割。详细请见MyStrtok的实现。

[cpp]  view plain copy
  1. //strtok源码剖析 位操作与空间压缩  
  2. //http://blog.csdn.net/morewindows/article/details/8740315  
  3. //By MoreWindows( http://blog.csdn.net/MoreWindows )  
  4. #include <stdio.h>  
  5. // strtok源码剖析  
  6. char* __cdecl MyStrtok(char * string, const char * control)  
  7. {  
  8.     unsigned char *str;  
  9.     const unsigned char *ctrl = (const unsigned char *)control;  
  10.     static unsigned char* _TOKEN = NULL;   
  11.     //注意这里使用了static类型,实际的strtok函数出于线程安全会使用TLS  
  12.   
  13.     //由于char类型占一个字节取值范围为0~255  
  14.     //所以可以打个bool flag[255]这样的哈希表  
  15.     //来记录哪些字符为delimiter characters  
  16.     //然后根据《位操作基础篇之位操作全面总结》中的位操作与空间压缩  
  17.     //http://blog.csdn.net/morewindows/article/details/7354571#t6  
  18.     //可以将数组大小取255/8即32  
  19.     unsigned char map[32];  
  20.     int count;  
  21.   
  22.     // Clear control map  
  23.     for (count = 0; count < 32; count++)  
  24.         map[count] = 0;  
  25.   
  26.     // Set bits in delimiter table  
  27.     do {  
  28.         //map[*ctrl >> 3] |= (1 << (*ctrl & 7));//strtok原来的代码  
  29.         map[*ctrl / 8] |= (1 << (*ctrl % 8));  
  30.     } while (*ctrl++);  
  31.   
  32.     // Initialize str   
  33.     // If string is NULL, set str to the saved pointer   
  34.     //(i.e., continue breaking tokens out of the string from the last strtok call)  
  35.     if (string != NULL)  
  36.         str = (unsigned char *)string;  
  37.     else  
  38.         str = (unsigned char *)_TOKEN;  
  39.   
  40.     // Find beginning of token (skip over leading delimiters). Note that  
  41.     // there is no token iff this loop sets str to point to the terminal  
  42.     // null (*str == '\0')  
  43.     //while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )//strtok原来的代码  
  44.     while ( (map[*str / 8] & (1 << (*str % 8))) && *str )  
  45.         str++;  
  46.   
  47.     string = (char *)str;  
  48.   
  49.     // Find the end of the token. If it is not the end of the string,  
  50.     // put a null there.   
  51.     for ( ; *str ; str++ )  
  52.     {  
  53.         //if ( map[*str >> 3] & (1 << (*str & 7)) ) //strtok原来的代码  
  54.         if ( map[*str / 8] & (1 << (*str % 8)) )   
  55.         {  
  56.             *str++ = '\0';  
  57.             break;  
  58.         }  
  59.     }  
  60.   
  61.     // Update nextoken (or the corresponding field in the per-thread data structure  
  62.     _TOKEN = str;  
  63.   
  64.     // Determine if a token has been found.   
  65.     if ( string == (char *)str )  
  66.         return NULL;  
  67.     else  
  68.         return string;  
  69. }  
  70. int main()  
  71. {  
  72.     printf("   strtok源码剖析 位操作与空间压缩\n");    
  73.     printf(" - http://blog.csdn.net/morewindows/article/details/8740315 -\n");    
  74.     printf(" - By MoreWindows( http://blog.csdn.net/MoreWindows ) - \n\n");   
  75.   
  76.     //char szText[] = "MoreWindows  (By http://blog.csdn.net/MoreWindows)";  
  77.     //char szFind[] = " ";  
  78.     char szText[] = "ab,c...d(e)f(g)hj";  
  79.     char szFind[] = ",.()";  
  80.   
  81.     printf("原字符串为: %s\n", szText);  
  82.     printf("分隔后为: \n");  
  83.     char *pToken = MyStrtok(szText, szFind);  
  84.     while (pToken != NULL)  
  85.     {  
  86.         printf("%s\n", pToken);  
  87.         pToken = MyStrtok(NULL, szFind);  
  88.     }  
  89.     return 0;  
  90. }  

运行结果如图所示(图片不能打开,请访问http://blog.csdn.net/morewindows/article/details/8740315

 

 地址:http://blog.csdn.net/morewindows/article/details/8740315转载请标明出处,谢谢。

欢迎关注微博:http://weibo.com/MoreWindows

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值