蓝森林首页 | 返回主页 | 本站地图 | 站内搜索 | 联系信箱 |
 您目前的位置:首页 > 自由软件 > 技术交流 > 应用编程


    

蓝森林 http://www.lslnet.com 2006年6月6日 10:18


【转】超强版 Trim 横空出世!

昨天给一个同事讲 trim,一时豪情大发,一不小心编出了这段代码,后来仔细看看,确实是堪称精品,不过又怕有什么遗漏的地方,所以赶紧发到这里让大家帮我参详参详。

[code]void trim( char *str )
{
        char *copied, *tail = NULL;

        if ( str == NULL )
                return;

        for( copied = str; *str; str++ )
        {
                if ( *str != ' ' && *str != '\t' )
                {
                        *copied++ = *str;
                         tail = copied;
                }
                else
                {
                         if ( tail )
                                 *copied++ = *str;
                }
        }

        if ( tail )
             *tail = 0;
        else
             *copied = 0;

        return;
}[/code]

【转】超强版 Trim 横空出世!

if ( str == NULL )
                return NULL;
原型是返回void哦。

【转】超强版 Trim 横空出世!

-->
哦,粗心了,改过。

【转】超强版 Trim 横空出世!

还有else
             *copied = 0;
是否也可以去掉。
因为你for循环结束时的条件就是*copied == 0
还有应该是*str != 32 && *str != 9吧?

【转】超强版 Trim 横空出世!

-->
[color=red]真的是太不好意思了。[/color]
今天没有带电脑,刚才的这段代码是默写出来的,所以有很多错误。
刚才又改了一下,循环的条件改正确了。

另:TAB 的键值我可能的确是记错了。
但是程序中不建议直接写 ASCII 码,我是因为怕空格看不清楚才这么写的,现在改回去了。

【转】超强版 Trim 横空出世!

从那说起这个是超强的trim阿,它能去掉中间的空格,前面的空格,后面的空格,是全部还是部分阿。
还有,str!等于8或9有什么区别么?我看只要不等于32就算满足要求了!

【转】超强版 Trim 横空出世!

-->
它能去掉前面的和后面的空格,中间的不会去掉。网络通讯中经常用到。

9 是 TAB,TAB 一般和空格做同样的解释。所以也要去掉。

之所以说“超强”是因为只用了一个循环两个变量,估计也不能更简洁了。

【转】超强版 Trim 横空出世!

-->
它是去掉字符串两端的空格。
ascii码是TAB键。
这个算法已经很不错了。
要不你也写一个出来。

【转】超强版 Trim 横空出世!

斑竹的确很负责,码了很多字出来。这段代码也非常好。
W25兄表老激动哦。

【转】超强版 Trim 横空出世!

不错!

但我觉得应该把所有控制符都去掉,举个例子:BS也应该处理吧?而且处理起来还很复杂。STX,ACK等等有意义吗?
我都是判<=空格的,又干净效率还高。

【转】超强版 Trim 横空出世!

-->

呵呵,这个就不好说了,比如我们公司的接口中,都用 \1 来当做字段的分隔符,所以是不能去掉的。
通常情况下,<32 的字符由于大多是不可见字符,实际应用中用不着,所以恰恰被很多接口采用为转义字符、分隔符、类型符、控制符等等,所以绝对是不可以去掉的。


再说了,要是想去掉,改一下我这个代码就可以了。
反正又不影响算法的效率:“时间复杂度”和“空间复杂度”,
所以我不会在意的。

我在意的是:我的这个算法有没有漏洞?有没有人能写出比我这个更好的算法?

【转】超强版 Trim 横空出世!

不错不错,用了两个指针记录位置,tail只有在不是空格的情况下才写入,这样在tail不为空的时候就记录下了最后的空格出现的位置。

【转】超强版 Trim 横空出世!

不错,我觉得从算法而言,确实没有简化的余地了。

【转】超强版 Trim 横空出世!

算法不错!
但对用STX来做分隔符不赞同,控制码里也有专门的符号的,FS就是嘛!
这个算法在尾部空格较多时有损失。
我再给你简化一下,主要是从效率角度考虑:
[code]
void trim( char *str )
{
        char *copied;
        char *tail;
        char c;

        if ( str == NULL )
                return;

        for ( copied = str, tail = NULL; ( c = *str ) != 0; str ++ )
        {
                if ( c != ' ' && c != '\t' )
                {
                        *copied ++ = c;
                         tail = copied;
                }
                else
                {
                         if ( tail != NULL )
                                 *copied ++ = c;
                }
        }

        if ( tail != NULL )
             *tail = 0;
        else
             *str = 0;
}
[/code]

【转】超强版 Trim 横空出世!

不好意思刚才出去吃饭了,刚回来,我根本没激动,只不过我觉得tail的指针处理上有问题,手里没有编译器,这段代码考一下,回去调试调试。

【转】超强版 Trim 横空出世!

现在想找楼主研究一下,遗憾!晚了!!!555

【转】超强版 Trim 横空出世!

flw老兄的代码写得非常好,我是绝对写不出来的,在这个问题上,我只发表过一次代码,而且效率不高,剩下的帖子,倒像个批评家。
不过,这次我还是想做一次批评家,请大家不要介意。
1。如果该字符串前部没有空格(或空格串),只有尾部有,那么,if ( tail )这个条件判断就要进行O(n)次,这完全可以用分情况的办法解决,当然,大家会说,如果分情况的话,源代码就不会这么简洁了,那么*copied++ = *str出现过两次,也不简洁,但是效率比提到条件语句外稍高一点。
2。在《如何又简洁又安全地去掉字符串前面和后面的空符号?》中,大家降低时间复杂性的方法是在到达字符串结尾后又折回来。flw兄的是利用了tail变量来记住应该赋'\0'值的位置,但是这样一来,每次都要进行tail = copied; 赋值操作或者是if ( tail )比较+转跳操作,时间复杂性一下子加了一倍,在具有超流水线的机器中效率将会更低。
3。用strlen()或者memmove()的算法实际执行效率可能最高
大家可以试试用for循环来实现strlen()和memmove(),看看运行效率比它们低多少,稍微用心一点的strlen()等函数的实现都会用串处理指令,其运行效率,比用for循环高多了,但是高多少又无法像美国1787年宪法规定的“黑人人口按实际的四分之三折算”那样加以量化,因此是“可能”最高。
请大家多对我的看法提宝贵意见。

【转】超强版 Trim 横空出世!

tail 用的精妙

【转】超强版 Trim 横空出世!

【转】超强版 Trim 横空出世!



Copyright © 1999-2000 LSLNET.COM. All rights reserved. 蓝森林网站 版权所有。 E-mail : webmaster@lslnet.com