中国IT动力,最新最全的IT技术教程
最新100篇 | 推荐100篇 | 专题100篇 | 排行榜 | 搜索 | 在线API文档 | 网通镜像
首 页 | 程序开发 | 操作系统 | 软件应用 | 图形图象 | 网络应用 | 精文荟萃 | 教育认证 | 硬件维护 | 未整理篇 | 站长教程
ASP JS PHP工程 ASP.NET 网站建设 UML J2EESUN .NET VC VB VFP 网络维护 数据库 DB2 SQL2000 Oracle Mysql
服务器 Win2000 Office C DreamWeaver FireWorks Flash PhotoShop 上网宝典 CorelDraw 协议大全 网络安全 微软认证
硬件维护  CPU  主板  硬盘  内存  显卡  显示器  键盘鼠标  声卡音箱  打印机  机箱电源  BIOS  网卡  C#  Java  Delphi  vs.net2005
  当前位置:> 程序开发 > 编程语言 > C/C++
如何又简洁又安全地去掉字符串前面和后面的空符号?
作者:未知 时间:2005-09-13 19:27 出处:ChinaUnix.net 责编:chinaitpower
              摘要:如何又简洁又安全地去掉字符串前面和后面的空符号?

要求:代码尽量简洁,内存访问安全,符合接口规范。例如,把"  123 aa d   "变成"123 aa d",空符号指空格符和制表符。
函数原型:void kill_space( char *ptr );

 wangshim_ 回复于:2003-12-25 10:30:42
数组调用

顺序来,先从前往后,记住非空的位置
再从后往前,记住非空的位置。

两位置之间的字符就是你要的。

 cacaty 回复于:2003-12-25 10:31:27
我给你改改,函数这样声明好了char *trim(char *ptr)
其实很好写

 wangshim_ 回复于:2003-12-25 10:32:36
pb 中的trim 也很好用,呵呵

 lylzp 回复于:2003-12-25 10:35:52
[quote:1d563acbb8="bjf"]要求:代码尽量简洁,内存访问安全,符合接口规范。例如,把"  123 aa d   "变成"123 aa d",空符号指空格符和制表符。
函数原型:void kill_space( char *ptr );[/quote:1d563acbb8]

[code:1:1d563acbb8]
void TrimAllStr(char *ibuf)
{
int nlen,i;
/*判断字符指针是否为空及字符长度是否为0*/
if (ibuf == NULL) 
return;
nlen = strlen(ibuf);
if (nlen == 0)
return;
/*去前空格*/
i = 0;
while (1)
{
if (ibuf[i]!=' ')
break;
i ++;
}
if (i == nlen)
{
ibuf[0] = 0;
return;
}
if (i != 0)
{
nlen = nlen - i + 1;
memcpy(ibuf,&ibuf[i],nlen);
}
/*去后空格*/
nlen = strlen(ibuf) - 1;
while (nlen>=0)
{
if (ibuf[nlen] != ' ')
{
ibuf[nlen + 1] = 0;
break;
}
nlen --;
}
}
[/code:1:1d563acbb8]

 flw 回复于:2003-12-25 10:38:01
[quote:77befd92ac="lylzp"][/quote:77befd92ac]
呵呵,还不行。

 只爱一点点 回复于:2003-12-25 10:47:21
看了 wangshim_ 和 cacaty 的帖子应该效率更高。
我好多年没用了,全忘了。就当从头学起,望指正。
可能会有逻辑和语法错误,看看我到什么水平了,虚啊~~
[code:1:3fedc0eb38]
 void kill_space( char *ptr )
{
char *search ;

if( *ptr!='\0' )
{
search=ptr ;
while( *search!='\32' || *search!='\t' )
{
  seach++ ;   
}
while( *search!='\0' )
{
*ptr=*search ;
ptr++ ;
search++ ;
}
search-- ;
while( *search=='\32' || *search=='\t' )
{
search-- ;   
}
search++ ;
*search='\0' ;
}
}

[/code:1:3fedc0eb38]

不行了,一帮人虎视着我要我去给打印机加纸,去起动个电脑,去印个材料~~~
刚才大叫了一顿~~

 lylzp 回复于:2003-12-25 10:49:55
哈!不好意思,我没看到还有制表符:
把if (ibuf[i]!=' ')改为 if ((ibuf[i]!=0x20)&&(ibuf[i]!='\t'))
把if (ibuf[nlen] != ' ')改为 if ((ibuf[nlen]!=0x20)&&(ibuf[nlen]!='\t'))

 flw 回复于:2003-12-25 10:51:52
[quote:38a0450cfd="只爱一点点"][/quote:38a0450cfd]
你这个也不行的。

 只爱一点点 回复于:2003-12-25 10:52:51
[quote:6250e4e4fd="flw"]
你这个也不行的。[/quote:6250e4e4fd]

快告诉我哪错了!

 wangshim_ 回复于:2003-12-25 10:53:29
楼上兄弟,第2个while 应该这样写:
while( *seach!='\0' || *seach!='\32' || *seach!='\t')
这样才能把后面的空给屏蔽掉。

 flw 回复于:2003-12-25 10:54:44
[quote:16f39e735a="wangshim_"]楼上兄弟,第2个while 应该这样写:
while( *seach!='\0' || *seach!='\32' || *seach!='\t')
这样才能把后面的空给屏蔽掉。[/quote:16f39e735a]
这样还是不行的。
呵呵。

 只爱一点点 回复于:2003-12-25 10:58:24
[quote:07088a035d="wangshim_"]楼上兄弟,第2个while 应该这样写:
while( *seach!='\0' || *seach!='\32' || *seach!='\t')
这样才能把后面的空给屏蔽掉。[/quote:07088a035d]

我是尾巴没处理好。

但这样中间有空格就会截断了。

 wangshim_ 回复于:2003-12-25 10:59:15
有意见可以提嘛,我们可以讨论,
不过不需要硬邦邦的定论。:)

 lylzp 回复于:2003-12-25 11:01:45
[quote:ad284c278c="flw"]
这样还是不行的。
呵呵。[/quote:ad284c278c]
你真逗,不过我的那段代码确实不怎么简洁
我也没去调试,我想功能应该是做到了。

 只爱一点点 回复于:2003-12-25 11:10:21
不行了,忘了给会计打表了,找来的。
flw,把我的改了或者删了吧,拜托

删了吧,这样做没什么效率了。
原型就不满意,呵呵

 BingbingNorth 回复于:2003-12-25 11:15:29
void kill_space(char * ptr)
{
int start,end,i;

for(start=0; ((ptr[start]==' ')||(ptr[start]=='\t'))&&(ptr[start]!='\0'); start++);
for(end=strlen(ptr)-1; (ptr[end]==' ')||(ptr[end]=='\t'); end--);
for(i=start; i<=end; i++)
ptr[i-start]=ptr[i];
ptr[end-start+1]='\0';
}
我的这段代码效率并不是最高的(最高的应该不用strlen),但是比较简单。

 flw 回复于:2003-12-25 11:15:46
[code:1:bffef3d6a9]void AllTrim( char *str )
{
    char *head, *tail;

    if ( str == NULL )
        return;

    for( head = str; *head == ' ' || *head == '\t'; head ++ );

    for( tail = str + strlen(str) - 1; (*tail == ' ' || *tail == '\t' ) && tail >= head; tail -- );

    while( head <= tail )
         *str ++ = *head ++;

    *str = 0;
}
[/code:1:bffef3d6a9]

 只爱一点点 回复于:2003-12-25 12:25:51
到底地对不对呀?
[code:1:a7e1b22f99]
void kill_space( char *ptr )
{
char *search ;

if( *ptr!='\0' )
{
for( search=ptr; *search==' ' || *search=='\t'; search++ ) ;
for( ; *search!='\0'; *ptr++=*search++  ) ;
 /* 多了一些无用的内存移动 */
for( search-- ; *search==' ' || *search=='\t' ; search-- ) ;
search++ ;
*search='\0' ;
}
}
[/code:1:a7e1b22f99]
楼下的老大,我改了,看看行不行

 flw 回复于:2003-12-25 12:28:22
[quote:0ab997ffeb="只爱一点点"][/quote:0ab997ffeb]
优点:没有用 strlen。
缺点:不能在 C 中编译,而且,有语法错误! :?  :oops:  :oops:  :oops:  :oops:

 蓝色键盘 回复于:2003-12-25 14:08:00
trim的问题写了这么多代码,好啊!

老夫也写个
去左边
[code:1:41ff858844]
char *lefttrim( char *str )
{
 char *pstart, *ptr;

    if ( str == NULL )
        return NULL;

    pstart = ptr = str;

    while ( *( ( unsigned char * )ptr ) == 0x20 || *ptr == '\t' || \
            *ptr == '\r' || *ptr == '\n' )
        ptr ++;

    while ( *ptr != 0x0 )
        *str ++ = *ptr ++;

    *str = 0x0;

    return pstart;
}

[/code:1:41ff858844]
去右别
[code:1:41ff858844]
char *righttrim( char *str )
{
    char        *ptr;

    if ( str == NULL )
        return NULL;

    ptr = str + strlen( str ) - 1;

    while ( ptr >= str && ( *( ( unsigned char * )ptr ) == 0x20 || \
            *ptr ==&nbs''''' ||  *ptr ==&nbs''''' || *ptr ==&nbs''''' ))
        *ptr -- = 0x0;

    return str;
}

[/code:1:41ff858844]

如法炮制,去左右以及去所有空格、制表符等,谁来写写?

 只爱一点点 回复于:2003-12-25 14:17:12
测试了一下,我的用&nbs''''' 判断制表符好像不行???

 BingbingNorth 回复于:2003-12-25 14:47:45
不可能吧,一直都行的!

 只爱一点点 回复于:2003-12-25 15:06:40
[quote:ac8fe57ac8="BingbingNorth"]不可能吧,一直都行的![/quote:ac8fe57ac8]

我说的是在 flw 写的代码下的面的那个代码?它可以吗?

 youngf 回复于:2003-12-25 16:09:00
修改了一下。source量应该是比较小了。
性能应该还可以吧。

[code:1:5d76327fc7]void kill_space(char *ptr){

        char *pHead=ptr, *pFoot=ptr+strlen(ptr)-1;

        if (ptr==NULL) return;

        while(*pFoot==32 || *pFoot''''') *pFoot--;
        while(*pHead==32 || *pHead''''') *pHead++;
        *(++pFoot)=0;

        if (pHead==ptr) return;

        while(pHead<=pFoot) *ptr++=*pHead++;
        *ptr=0;

        return;
}
[/code:1:5d76327fc7]

 eboymcy 回复于:2003-12-25 16:09:59
1

 eboymcy 回复于:2003-12-25 16:10:26
[code:1:251627421a]
char *KillSpeace(char *pStr)//去掉pStr前后空格和制表符
{
        char *pHead,*pTail;
        char *pAddr;
        if(pStr == NULL)
                 return NULL;
        pAddr = pStr;
        for(pHead = pStr;((*pHead ==&nbs'''&nbs''') || (*pHead ==&nbs''''')&&(*pHead !=&nbs'''''));pHead ++);
        for(pTail = pStr + strlen(pStr) -1;((*pTail ==&nbs'''&nbs''')||(*pTail ==&nbs''''')&&(pTail <= pHead));pTail --);
        while(pHead <= pTail)
                *pStr++ = *pHead ++;
        *pStr =&nbs''''';
        return pAddr;
}
[/code:1:251627421a]

 youngf 回复于:2003-12-25 16:19:09
注意,他的要求是:返回值是 void, 不是char*。

 BingbingNorth 回复于:2003-12-25 16:32:14
[quote="只爱一点点"]

我说的是在 flw 写的代码下的面的那个代码?它可以吗?[/quote]
能运行啊,而且跟最佳状态已经不远了(只要解决多余的内存移动,但是如果要解决多余的内存移动,代码就变长了)。

 只爱一点点 回复于:2003-12-25 16:44:10
[quote:022844b84b="BingbingNorth"]
能运行啊,而且跟最佳状态已经不远了(只要解决多余的内存移动,但是如果要解决多余的内存移动,代码就变长了)。[/quote:022844b84b]

???你是怎么测试的,把主程序贴出来看看可以吗?

我都忘了,想从控制台读一行字符串都想不起来了。

 tangsuilx 回复于:2003-12-25 17:03:15
UNIX C 下:
void sch_ltrim( char* str )
{
    int    len;
    int    i;

    len = strlen( str );
    for ( i = 0; i < len, str[i] ==&nbs'''&nbs'''; i++ )
    if( i )
        strcpy( str, &str[++i] );
}
void sch_rtrim( char* str )
{
    int     i;
    int     len;
    char    *ptr;

    if( len = strlen( str ) ){
        ptr = malloc( strlen( str ) + 1 );
        memcpy( ptr, str, len );
        i = len;
        for( ; i > 0, ptr[i-1] ==&nbs'''&nbs'''; i-- );
        ptr[i] =&nbs''''';
        memcpy( str, ptr, len );
        free( ptr );
    }
    return;
}

 lylzp 回复于:2003-12-25 17:17:12
哈!我就再献一次丑:
[code:1:162ff366ba]
void TrimAllStr(char *str)
{
char *phead,*pmove;
if (str == NULL) 
return;
phead = pmove = str;
while ((*pmove == 0x20)||(*pmove ==&nbs'''''))
pmove ++;
do
{
*str ++ = *pmove ++;
}
while (*pmove != 0);

*str = 0;
if ((str - phead) == 1) return;

pmove = str - 1;
while (1)
{
if ((*pmove != 0x20)&&(*pmove !=&nbs'''''))
{
pmove ++;
*pmove =&nbs''''';
break;
}
pmove --;
}
}
[/code:1:162ff366ba]

 BingbingNorth 回复于:2003-12-25 20:46:09
回答只爱一点点:
没有读标准输入,而是这样:
#include <stdio.h>


void kill_space( char *ptr ) 

   char *search ; 

   if( *ptr''''' ) 
   { 
      for( search=ptr; *search'''&nbs''' || *search'''''; search++ ) ; 
      for( ; *search'''''; *ptr++=*search++  ) ; 
             /* &àÁËÒ&Ð&ÎÞÓÃ&ÄÄÚ&&ÒÆ&& */ 
      for( search-- ; *search'''&nbs''' || *search''''' ; search-- ) ; 
      search++ ; 
      *searc''''' ; 
   } 



int main()
{
char a[]="  \t bc   efg\t";

kill_space(a);
printf("[%s]\n",a);
}

 老K 回复于:2003-12-25 22:10:46
flw的我收了。比我的写的好。

 youngf 回复于:2003-12-26 12:29:10
能不能借这个机会,讲讲C是怎么实现strlen函数的?

 win_hate 回复于:2003-12-26 12:36:49
[quote:6cbbbf3a47="youngf"]能不能借这个机会,讲讲C是怎么实现strlen函数的?[/quote:6cbbbf3a47]

不同的c库实现方式肯定不一样,在x86上,一个很好的选择是用汇编中的串扫描指令。

 bjf 回复于:2003-12-26 20:33:28
我自己也来一个:

void
trim( ptr )
    char *ptr;
{
    char *p1, *p2;

    p1 = p2 = ptr;
    while( *p2'''&nbs''' || *p2''''' || *p2''''' ) p2++;
    for( ; *p1=*p2; p1++,p2++ );
    while( p1>ptr && (*(p1-1)'''&nbs''' || *(p1-1)''''' || *(p1-1)''''') ) p1--;
    *p1 =&nbs''''';
}

 蓝色键盘 回复于:2003-12-27 09:56:57
楼上各位兄弟讲得非常好

去空格的函数,我倒是没有仔细追究性能。看了标题,偶便把left/right贴上来,凑热闹。呵呵

 只爱一点点 回复于:2003-12-27 12:02:00
[quote:21a77270f6="forest077"]返回值是char *和void有很大的区别,后者需要把新的字符串的每个字符覆盖掉旧字符串的每个字符,所以一些内存移动必不可少....[/quote:21a77270f6]

这种情况下内存移动是不可必免的。我主要指在字符串末尾有空格时程序也会对它进行移动。要避免就要先找到末尾,所以没有那样做。

另外做成这样纯属偶然,因为写到一半忘了处理末尾的空格了,经大家提醒才临时打了个补丁,呵呵 。其实它的效率取决于字符串的长度和末尾空格数的多少了。

不过效率在这意思好像不是很大,主要能让我们理解一些更深的东西,如:strlen的效率如何等等。

 bjf 回复于:2003-12-27 14:38:37
一个小小的问题引出那么多的见解,真没想到啊!希望能有谁总结一下,对于这个常用的小函数,从安全、高效的角度来考虑,哪一种方法最好,以后就不用再去写了。

 converse 回复于:2004-02-15 20:06:53
我的算法,应该是比较简洁的吧,大家给点意见

void kill_space( char *str)
{
      int i, j;

      assert( str != NULL);

      /*find the first non-space ch'''s position */
      for (i = 0; (str[i] ==&nbs'''&nbs''' || str[i] ==&nbs''''') && str[i] !=&nbs'''''; i++)
          ;
      /*find the last non-space ch'''s position */
      for (j = strlen(str) - 1; (str[j] ==&nbs'''&nbs''' || str[j] ==&nbs''''') && j; j--)
          ;
      memmove(str, str + i, j - i);
      str[j + 1] =&nbs''''';
}

 BingbingNorth 回复于:2004-02-15 20:52:16
这个帖子又被顶上来了,我发表一下关于“效率最高”的拙见,不足之处请大家补充。
1。如果前面没有空白符,那么str[i]=str[i]这样的操作不应该被执行,否则,对于一个很大的字符串,你的算法的时间复杂性比最佳的就低很多。大家可以看看前面的帖子,这一点有谁考虑到了。
2。用了strlen()的算法一定不是最佳的,因为这个程序的算法可以降到strlen(str)+1,而strlen()本身的时间复杂性就是strlen(str)+1。
3。只爱一点点兄发表于: 2003-12-25 12:12 的算法,bjf兄 发表于: 2003-12-26 20:12    的时间复杂性是最小的,(只比strlen(str)+1大了一点点)但还没有达到最佳,在到达字符串结尾后又折回来了。
另外我还要感谢converse兄,教给了我memmove()的用法。

 converse 回复于:2004-02-15 22:33:05
在写上面的代码前,没有看过前面的留言,原来可以不用strlen呀,所以我又进行了一个改进,大家再看一看吧

[code:1:1d563acbb8] 
void kill_space(char *str)
{
      char *p, *q;

      assert(str != NULL);

      for (p = str; (*p ==&nbs'''&nbs''' || *p ==&nbs''''') && *p !=&nbs'''''; p++)
          ;
      for (q = p; *q !=&nbs'''&nbs''' && *q !=&nbs''''' && *q !=&nbs'''''; q++)
          ;
      *q =&nbs''''';
      memmove(str, p, q - p);
}[/code:1:1d563acbb8]

BingbingNorth:
我现在写程序的时候,首先考虑的是标准库里有没有相应功能的函数,这样可以保证移植性,我也是最近开始仔细研究C库的,过一段时间(大概一个月吧),我会把自己实现的部分C库(主要是string.h,input/output,stdlib.h)的代码放在这里和大家讨论。
另外,谁能告诉我哪里能找到C库的实现,我听说好像LINUX里有,不知道是不是呢

 converse 回复于:2004-02-15 22:44:41
在写上面的代码前,没有看过前面的留言,原来可以不用strlen呀,所以我又进行了一个改进,大家再看一看吧 

[code:1:8f2359ca7a] 
void kill_space(char *str) 

char *p, *q; 

assert(str != NULL); 

for (p = str; (*p ==&nbs'''&nbs''' || *p ==&nbs''''') && *p !=&nbs'''''; p++) 

for (q = p; *q !=&nbs'''&nbs''' && *q !=&nbs''''' && *q !=&nbs'''''; q++) 

*q =&nbs'''''; 
memmove(str, p, q - p); 
}[/code:1:8f2359ca7a] 

BingbingNorth: 
我现在写程序的时候,首先考虑的是标准库里有没有相应功能的函数,这样可以保证移植性,我也是最近开始仔细研究C库的,过一段时间(大概一个月吧),我会把自己实现的部分C库(主要是string.h,input/output,stdlib.h)的代码放在这里和大家讨论。 
另外,谁能告诉我哪里能找到C库的实现,我听说好像LINUX里有,不知道是不是呢

 BingbingNorth 回复于:2004-02-16 15:00:16
converse兄:
你的算法不太符合原来的要求,字符串中间的空白符是不能删的。

 foryijian 回复于:2004-02-16 15:41:49
个人认为,由于中间空格的存在,strlen 一下是无法避免的

 converse 回复于:2004-02-16 17:49:17<7
BingbingNorth:
我昨晚回去睡觉的时候也反应过来了,不过今天上班,不太有时间想,我暂时也想不到一个比较好的小于(或接近)strlen(s)-1的方法找到后面空格的位置,待我想一想。

 gm_jwl 回复于:2004-02-17 01:11:57
char *
kill_space(char *ptr)
{
int i=0,j;
char *str;

j=strlen(ptr)-1;
while(ptr[i]'''''||ptr[i]'''&nbs'''||ptr[i]''''') i++;
while(ptr[j]'''''||ptr[j]'''&nbs'''||ptr[j]''''') j--;

if((str=(char *)malloc(j-i+2))==NULL)
{
perror("kill_space:malloc");
exit(1);
}
strncpy(str,ptr+i,j-i+1);
str[j-i+1''''';
return str;
}

楼主应当把函数接口改掉,如双指针,否则不可能成功。

 BingbingNorth 回复于:2004-02-17 10:53:18
关注这个帖子的同仁,也可以看一看wangrujun兄发的一个有关算法的帖子,主题为“[原创] 从字符串中,删除指定字符串中的任意字符”,有一定的相似之处。

 bulluta 回复于:2004-02-21 13:22:12
不考虑memmove的复杂度后复杂度为strlen(s),大家看看算法有没有问题
void KillSpace(char*ptr)
{
    int begin=-1, end=0, curpos=0;

    while(0 != ptr[curpos])
    {
        if'''&nbs''' == ptr[curpos]) || ''''' == ptr[curpos]))
        {
            //do nothing 
        }
        else
        {
            //find out the first byte not space
     &nb;      if(-1 == begin)
                begin = curpos;

            //current the last byte not space
            end = curpos;
        }
        curpos++;
    }
     ptr[end+1] = 0;

    if(-1 == begin)
        //only space and tab in ptr
        ptr[0] = 0;
    else if(0 != begin)
        memmove(ptr, &ptr[begin], end-begin+1);
}

这是借鉴了楼上各位兄台的思路后得出的算法,尤其是BingbingNorth的“如果前面没有空白符”的提醒。
不过我还有个疑问,这样去空格会不会造成内存泄漏?去掉的空格的内存空间并没有真正的释放掉,但直接用free似乎不妥。

 improgrammer 回复于:2004-02-24 22:14:57
void kill_space(char *ptr)
{
char *p,*q;
if(ptr==NULL)
return;
for(p=ptr;*p'''&nbs''' || *p''''';++p);
if(*p''''')
{
*pt''''';
return;
}
for(q=ptr;*p;++p,++q)
{
*q=*p;
}
for(p=q-1;*p'''&nbs'''||*p''''';--p);
*(++p''''';
}

这样简单,而且即使用memmove()代替逐字符拷贝提高一点效率,也少不了逐字符计算长度,效率的提高毕竟有限。至于没有前置空字符时可以省却第一、二循环,则要看使用时那种情况出现的概率大小。如果大多数情况下有前置空字符,则加一个if判断反而降低理论上的效率。总之,多一事不如少一事,就这样,采用最简单的代码。

有一点,就是如果传入NULL指针,则算是调用者违规,用个assert(ptr);强调一下协议是规范的做法,而不用这里的if(ptr==NULL)判断。 :em11:

 mindit 回复于:2004-02-25 09:32:43
我也来凑凑热闹

// 用处:1、删除前导空白符
//       2、将中间连续的空白符替换为一个空格
//   p;    3、删除后面的空白符
void kill_space(char *s)
{
char *p=s, *q=s;

for(; isspace(*s); s++); /* 掠过前导空白符 */
for(; *s; )
{ /* 顺序访问字符串s中的每个字符 */
*q++ = isspace(*s) ?&nbs'''&nbs''' : *s ;
if(!isspace(*s))
{
s++;
}
else /* 掠过中间连续的多余空白符 */
{
while(isspace(*s))
{
s++;
}
}
}

if(q>p && *(q-1) ==&nbs'''&nbs''') /* 如q>p,则已经复制过非空白字符 */
{
*(q-1) =&nbs'''''; /* 如果后复制的是空白字符,将其改为字符串结束符 */
}
else
{
*q =&nbs'''''; /* 否则添加字符串结束符 */
}
}

// 判断是否空字符
int isspace(char chr)
{
if(chr'''&nbs''' || chr''''' || chr''''' || chr==0x0a)
{
return(1);
}
return(0);
}

 zxhred 回复于:2004-02-25 11:02:59
聆听教诲,不敢多走一步,只不过代码又多了一个变量.

[code:1:d44b116498]void trim ( char* ptr)
{
    char *p,*q,*pos;
    if ( ptr == NULL)
        return ;
    p = q = pos = ptr;
    for ( ;*p'''&nbs'''||*p''''';p++);
    
    q = pos = p;
    for ( ; *p !=&nbs'''''; p++)
    {
        if ( *p'''&nbs'''&&*p''''')
          &np; q = p;  
    }
    *(++q) =&nbs'''''; 
    memmove ( ptr,pos,q-pos+1);
    return ;
}[/code:1:d44b116498]

 flw 回复于:2004-03-02 15:55:49
http://bbs.chinaunix.net/forum/viewtopic.php?p=1813892

这个是我刚写的,比这个帖子所有的代码都好用。

 鸿弧凌风 回复于:2004-03-02 16:48:10
#include "stdio.h"
#include "string.h"
void kill_space(char * str) 

        char * head,* end,* temp; 
if(str==NULL ) 
               printf("The String is NULL.\n"); 
head=str;
end=str+strlen(str);
while((*head''''')||(*head''''')||(*head''''')||(*head==32))
head++;
while((*end''''')||(*end''''')||(*end''''')||(*end==32))
end--;
temp=head;
temp[end-head''''';
*str=*temp;
printf("%s\n",str);
}

 我不懂C++ 回复于:2004-06-29 12:01:46
[code:1:53b0fd94a2]char* trim(char* s)
{
ASSERT ( s != NULL );
char* begin = s;
char* end = s + strlen( s );
if( begin != end )
{
--end;
while( isspace( *end ) && begin != end )
--end;
*end = 0;
}
if( isspace( *begin ) )
{
++begin;
while( isspace( *begin ) )// will stop at trailing zero
++begin;
memmove(s, begin, end - begin + 1 );
}
return s;
}
[/code:1:53b0fd94a2]

 xstart 回复于:2004-09-10 02:33:26
#include <stdio.h>
#include <string.h>
#include <ctype.h>


char * trim(char * ptr) 
{
int start,end,i;
for(start=0; isspace(ptr[start]); start++); 
for(end=strlen(ptr)-1;isspace(ptr[end]);end--);
for (i=start;i<=end;i++)
ptr[i-start]=ptr[i];
ptr[end-start+1''''';
return (ptr);
}

正好需要这样一个函数所以找到这里,试用了很多人的成果,发现大家的注意力主要在程序的效率上,结果往往不是很精确。我使用isspace函数改了一下,经测试能保证结果的正确性。

 zxf_tdm 回复于:2004-10-10 13:55:47
该写法应该是比较简洁的
int trim(char *str)
{
char *src, *dst;
   int i;
   i=strlen(str)-1;
   dst=src=str;
   while(*(src+i) && *(src+i)==0x20)
    {
      *(dst+i''''';
       i--;
    }
  
   dst=src=str;
   while(*src && *src==0x20) src++;
   do
   {
      *dst++=*src;
     }while (*src++); 
}

 yuxh 回复于:2004-10-11 12:18:33
这样子是不是有点烦?但效率应该还可以。

[code:1:11518c9fc8]#include "stdio.h"
void kill_space(char * str)
{
    char *pSource, *pDest;
    int  nLen, nNum, iFlag;

    pSource = pDest = str;
  &n  while(*pSource ==&nbs'''&nbs'''||*pSource ==&nbs''''' || *pSource ==&nbs''''' || *pSource ==&nbs''''') pSource++;
    if(pSource == pDest) {
        nLen = 0;
        iFlag = 1;
        while(*pSource != 0) {
            if(*pSource ==&nbs'''&nbs'''||*pSource ==&nbs''''' || *pSource ==&nbs''''' || *pSource ==&nbs''''') {
                if( iFlag == 0)
                    nNum++;
                else {
                    iFlag = 0;
                    nNum = 1;
                }
            }
            else {
                if( iFlag == 0 ) {
                    iFlag = 1;
     &nbs              nLen += nNum;
                }
                nLen++;
            }
            pSource++;
        }
        str[nLen] = 0;
    }
    else {
        nLen = 0;
        iFlag = 1;
        while(*pSource != 0) {
            if(*pSource ==&nbs'''&nbs'''||*pSource ==&nbs''''' || *pSource ==&nbs''''' || *pSource ==&nbs''''') {
                if( iFlag == 0)
                    nNum++;
                else {
                    iFlag = 0;
                    nNum = 1;
                }
            }
            else {
                if( iFlag == 0 ) {
                    iFlag = 1;
                    nLen += nNum;
                }
                nLen++;
             }
            *pDest++ = *pSource++;
        }
        str[nLen] = 0;
    }
}
[/code:1:11518c9fc8]

 mengwg 回复于:2004-10-11 17:05:55
好热闹,偶一个类里的实现,摘了一部分代码。

[code:1:cd4ed32717]
#ifndef str_h
#define str_h

class TStr
{
private:
  char * mBuf;
  int mSize;
  int mInfo_Size;
  
public:
  TStr();
  TStr(char *str);
  ~TStr();

  int Size();
  char * Str();
  char * Ret();

  char * operator~();
  char * operator=(char * str);
  char * operator+(char * str);
  char * operator+(char   str);
  char * operator()(char * str,int size);
  char * AR();
  char * AL();
};
#endif


char * TStr::AR()
{
char * pblank=NULL,*pos;

  if(mBuf==NULL) return NULL;
  pos=mBuf;
  while(*pos!=0)
  {
    if(*pos'''&nbs'''||*pos==0x09)
      pblank=pos;
    else pblank=NULL;
    pos++;
  };
  if(pblank!=NULL)
    *pblank=0;
  mInfo_Size=strlen(mBuf);
  return mBuf;
};

char * TStr::AL()
{
char * src,*tag;

  if(mBuf==NULL) return NULL;
  tag=src=mBuf;
  while(*src'''&nbs'''||*src==0x09) src++;
  while(*src!=0) *tag++=*src++;
  *tag=0;
  mInfo_Size=strlen(mBuf);
  return mBuf;
};

[/code:1:cd4ed32717]

 Ares42 回复于:2004-10-11 18:51:24
[quote:95e686d76d="bjf"]要求:代码尽量简洁,内存访问安全,符合接口规范。例如,把"  123 aa d   "变成"123 aa d",空符号指空格符和制表符。
函数原型:void kill_space( char *ptr );[/quote:95e686d76d]

我也凑一贴,请高手指正.

#include <stdio.h>
#include <string.h>

void Trim(char *Old)
{
  int i=0;
  char *New;

  if(!strlen(Old) || !(New=strdup(Old))) return;

  while(strchr(" \t",*(New+i)) && ++i);
  while(strchr(" \t",New[strlen(New)-1]) && !(New[strlen(New)-1'''''));

  sprintf(Old,New+i);

  return;
}

 xjfirst 回复于:2004-10-12 15:05:48
[code:1:623db5675f]
void trim(char *scr)
{
int i, startpos, endpos;

startpos = 0;
if(scr == NULL) return NULL;
for(i = 0; *(scr + i) ==&nbs'''&nbs''' || *(scr + i) ==&nbs'''''; i++);
startpos = i;
endpos = i;
for(; *(scr + i) !=&nbs''''';) 
{
for(; *(scr + i) !=&nbs'''&nbs''' && *(scr + i) !=&nbs''''' && *(scr + i) !=&nbs'''''; i++);
endpos = i - 1;
for(; *(scr + i) ==&nbs'''&nbs''' || *(scr + i) ==&nbs'''''; i++);
}

if(startpos == endpos) { /* 说明字符串是由空格与制表符组成的 */
return NULL;
}

memmove(scr, scr + startpos, endpos - startpos + 1);
memset(scr + endpos - startpos + 1, 0, i - endpos + startpos);
}[/code:1:623db5675f]

 zerglot 回复于:2004-10-15 15:40:48
upup

 shiyiming 回复于:2004-10-15 19:05:05
我给你改改,函数这样声明好了char *trim(char *ptr) 
其实很好写

 zzgwz 回复于:2004-11-21 21:05:25
void kill_space( char *ptr )
{
      int i, j, k;
     
      for( i = j = 0, k = -1; *(ptr + i ) !=&nbs''''' ; ++ i )
              if( *( ptr + i ) !=&nbs'''&nbs''' && *( ptr + i ) !=&nbs''''' )
              {
                     k = i;
                     *( ptr + j ) = *( ptr + i )
                     ++j;
               }
       *( ptr + k + 1 ) =&nbs''''';
       return ;
}

 christine6280 回复于:2004-11-29 09:54:16
void TrimStr( char *s )
{
   int  len = 0;
   char *p;

   p = s;
   len = strlen( p );

   if( p == NULL )
      return;
   if( strlen( p ) == 0 )
      return; 

   while( 1 )
   {
      if(( p[ len - 1 ] != 0x20 ) && 
         ( p[ len - 1 ] !=&nbs''''' ))
      {
         p[ len ] = 0x00;
         break;
      }
      len--;
   }

   while( 1 ) 
   {
      if(( *p != 0x20 ) && ( *p !=&nbs''''' ))
         break;
      p++; 
      len--;  
   }
   
   sprintf( s, p );
}

已经在sco上调试通过

 wangxg2 回复于:2004-12-28 17:16:15
[code:1:ea8a39d367]
void erase_char(char *str, char a)
{
    if (*str ==&nbs''''') return;
    
    for (char *p = str; *p !=&nbs'''''; )
    {
        if (*p == a)
        {
            char *pos1 = p;
            char *pos2 = p;
            while(*pos1++ = *(++pos2)){}
        }
        else
            p++;
    }
}[/code:1:ea8a39d367]

这样呢?可以删除任何字符

 javacool 回复于:2005-07-25 14:53:11
void trim(char *str)
{
int bpos;
assert(str != NULL);
/* trim blank character in front of str */
for(int i = 0; str[i]''''' && (str[i]'''&nbs''' || str[i]'''''); i++)
NULL;

/* test where str is full of blank characters*/
if(str[i] ==&nbs'''''){
str[0] =&nbs''''';
return;
}

/* trim blank character at the end of str */
bpos = 0;
for(int j = i; str[j]'''''; j++)
/* record pos start of last blank characters */
if(str[j] ==&nbs'''&nbs''' || str[j] ==&nbs'''''){
bpos = j;
for(; str[j]'''&nbs''' || str[j] ==&nbs'''''; j++)
NULL;
/* make j point to end pos of last blank characters*/
j--;
}

/* test whether last blank characters at the end of str */
if(str[j-1] '''&nbs''' || str[j-1] ''''') 
j = bpos;

memmove(str, str+i, j-i);
str[j-i] =&nbs''''';
}
通过bpos记录最后一个空字符串的起始位置,移动字符串时比较bpo'''''的位置来决定后面空字符串的trim 程序只需遍历字符串一次且不需使用strlen

关闭本页
 
首页 | 投资与合作 | 服务条款 | 隐私政策 | 收藏本站 | 设为首页 | 新用户注册 | 免责声明 | 使用帮助
Copyright ©2005-2008 chinaitpower.com All rights reserved. www.chinaitpower.com 版权所有