免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 4837 | 回复: 15
打印 上一主题 下一主题

[算法] 优化版flw的超强版 Trim ,欢迎高手拍砖 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-10-07 21:13 |只看该作者 |倒序浏览
本帖最后由 snowboy9859 于 2011-10-07 21:15 编辑

本人不才,站在牛人的肩膀上学习写代码,其中代码引用了flw的思路,在此表示感谢。下面这段代码可能存在哪些漏洞,欢迎专家们点评
由于flw的代码需要移动字符串中元素,可能效率较慢,本人的思路是将第一个非空格字符处做一
标记(将一局部指针指向此处),找到右边第一个空格并将其赋值为字符串结束符。最后返回局部指针。程序实现如下:
  1. /*************************************************
  2. *函数功能:去除字符串左右两边的空格

  3. *传入参数:str:需要处理的字符串

  4. *传出参数:无

  5. *返回值:处理后的字符串

  6. ************************************************/
  7. char * trim( char *str )
  8. {
  9.     char *head, *tail = NULL;
  10.    
  11.     if ( str == NULL )
  12.         return str;
  13.    
  14.     for( head = str; *str; str++ )
  15.     {
  16.         if ( *str != ' ' && *str != '\t' )
  17.         {            
  18.             if (tail == NULL)
  19.             {
  20.                 head = str;//tail为NULL时,此处为第一个非空格字符,将此位置保存下来
  21.             }
  22.             tail = str+1;//更新tail指针的指向为非空格字符的下一个位置
  23.         }        
  24.     }
  25.     /*由于tail始终指向非空格字符的下一个位置,当循环退出时,tail指向右边第一个空格*/
  26.     if ( tail )
  27.         *tail = 0;
  28.     else
  29.         *head = 0;
  30.    
  31.     return head;
  32. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-10-07 21:18 |只看该作者
那是flw当年情窦初开时的作品

论坛徽章:
0
3 [报告]
发表于 2011-10-08 00:36 |只看该作者
有一个小问题,因为没有移动数据,所以存放原字符串的数组开头还是保存着空白符,相反结尾的空白已经截掉,直接使用原数组的时候也不会得到尾部空白。虽然返回了第一个非空白符的地址,但这样一来,就有必要把返回值保存起来,还要记住下面的程序不能再用原来那个数组名来表示字符串了。这样的代码会有点混乱。。。还是移动数据的设计比较合理

论坛徽章:
89
水瓶座
日期:2014-04-01 08:53:31天蝎座
日期:2014-04-01 08:53:53天秤座
日期:2014-04-01 08:54:02射手座
日期:2014-04-01 08:54:15子鼠
日期:2014-04-01 08:55:35辰龙
日期:2014-04-01 08:56:36未羊
日期:2014-04-01 08:56:27戌狗
日期:2014-04-01 08:56:13亥猪
日期:2014-04-01 08:56:02亥猪
日期:2014-04-08 08:38:58程序设计版块每日发帖之星
日期:2016-01-05 06:20:00程序设计版块每日发帖之星
日期:2016-01-07 06:20:00
4 [报告]
发表于 2011-10-08 00:42 |只看该作者
那是flw当年情窦初开时的作品
AD8018 发表于 2011-10-07 21:18


论坛徽章:
0
5 [报告]
发表于 2011-10-08 00:48 |只看该作者
有一个小问题,因为没有移动数据,所以存放原字符串的数组开头还是保存着空白符,相反结尾的空白已经截掉, ...
suosuopuo 发表于 2011-10-08 00:36



    不同的地方不同的用法, 当然,都遍历一遍了, 顺便移动一下也没什么

论坛徽章:
0
6 [报告]
发表于 2011-10-08 09:54 |只看该作者
回复 3# suosuopuo


    这样的代码会有点混乱。。。还是移动数据的设计比较合理?难道移动数据就不会破坏原来字符数组了么?

论坛徽章:
0
7 [报告]
发表于 2011-11-07 01:48 |只看该作者
回复 6# snowboy9859


    不是不会破坏,是保持各个地方一致,想想用户的使用体验啊。。。

论坛徽章:
0
8 [报告]
发表于 2011-11-07 02:02 |只看该作者
回复 6# snowboy9859


    你见过把原数据改掉一半的标准库函数吗?要么就加const限制改动原数据,要么就确保各个地方能得到一致的数据。。。

论坛徽章:
0
9 [报告]
发表于 2011-11-07 04:25 |只看该作者
本帖最后由 fallening 于 2011-11-07 04:27 编辑

我觉得有两个地方可以优化:
1) 查找前边一个空格的时候,可以参照 glibc 的 strlen 实现优化:
  1. size_t
  2. strlen (str)
  3.      const char *str;
  4. {
  5.   const char *char_ptr;
  6.   const unsigned long int *longword_ptr;
  7.   unsigned long int longword, magic_bits, himagic, lomagic;

  8.   for (char_ptr = str; ((unsigned long int) char_ptr
  9.                         & (sizeof (longword) - 1)) != 0;
  10.        ++char_ptr)
  11.     if (*char_ptr == '\0')
  12.       return char_ptr - str;

  13.   longword_ptr = (unsigned long int *) char_ptr;

  14.   magic_bits = 0x7efefeffL;
  15.   himagic = 0x80808080L;
  16.   lomagic = 0x01010101L;
  17.   if (sizeof (longword) > 4)
  18.     {
  19.       magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL;
  20.       himagic = ((himagic << 16) << 16) | himagic;
  21.       lomagic = ((lomagic << 16) << 16) | lomagic;
  22.     }
  23.   if (sizeof (longword) > 8)
  24.     abort ();

  25.   for (;;)
  26.     {

  27.       longword = *longword_ptr++;

  28.       if (
  29. #if 0
  30.           (((longword + magic_bits)
  31.             ^ ~longword)
  32.            & ~magic_bits)
  33. #else
  34.           ((longword - lomagic) & himagic)
  35. #endif
  36.           != 0)
  37.         {

  38.           const char *cp = (const char *) (longword_ptr - 1);

  39.           if (cp[0] == 0)
  40.             return cp - str;
  41.           if (cp[1] == 0)
  42.             return cp - str + 1;
  43.           if (cp[2] == 0)
  44.             return cp - str + 2;
  45.           if (cp[3] == 0)
  46.             return cp - str + 3;
  47.           if (sizeof (longword) > 4)
  48.             {
  49.               if (cp[4] == 0)
  50.                 return cp - str + 4;
  51.               if (cp[5] == 0)
  52.                 return cp - str + 5;
  53.               if (cp[6] == 0)
  54.                 return cp - str + 6;
  55.               if (cp[7] == 0)
  56.                 return cp - str + 7;
  57.             }
  58.         }
  59.     }
  60. }
复制代码
2) 查找后边一个空格的时候,可以根据字符串的长度,决定 tail 是从前往后找还是从后往前找。当然这个阈值需要统计大量样本找出经验值来,而且可能在不同的机器上存在差别。

论坛徽章:
0
10 [报告]
发表于 2011-11-07 08:37 |只看该作者
过早优化是万恶之源
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP