删除字符串中的数字并压缩字符串

题目:删除字符串中的数字并压缩字符串 。如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。

分析:可用两个索引指向字符串的开头,一个向后推进作为循环条件,另一个跨过数据向后推进。达到消除数据及压缩操作。
           一快一慢,可称为快慢消除法。
 
/***************************************************************************************
删除字符串中的数字并压缩字符串
题目:删除字符串中的数字并压缩字符串 。
如字符串”abc123de4fg56”处理后变为”abcdefg”。注意空间和效率。
分析:可用两个索引指向字符串的开头,
一个向后推进作为循环条件,另一个跨过数据向后推进。达到消除数据及压缩操作。
一快一慢,可称为快慢消除法。
*****************************************************************************************/
#include <stdio.h>
#define USE 1
#if USE
void ddc(char *s)
{
 int i = 0;
 int j = 0;
 while(s[i])
 {
  if(s[i]<'0' || s[i]>'9')
  {
   s[j++] = s[i];
  }
  i++;
 }
 s[j] = '';
}
#else
char *ddc(char *s)
{
 char *p = s;
 char *res = p;
 while(*s)
 {
  if(*s < '0' || *s > '9')
  {
   *p++ = *s;
  }
  s++;
 }
 *p = '';
 return res;
}

#endif

int main(void)
{
    //char *str = "abc123de4fg56"; segmentation fault。
    char str[] = "abc123de4fg56";
    #if USE
    ddc(str);
    printf("result is %s
",str);
    #else
    printf("result is %s
",ddc(str));
    #endif
    return 0;
}

当参数定义为char *str =  "abc123de4fg56" 时,会发生SEGMENTATION FAULT。

当参数定义为char str[] = "abc123de4fg56"  时,会正常运行。 
 
合理的解释是,参数定义char *str =  "abc123de4fg56" 时,表明str指向的是一个字符串常量,不能重写。
 而移动过程中会发生读写操作,所以会发生SEGMENTATION FAULT。 而参数定义为char str[] =  "abc123de4fg56" 
 时是定义的一个字符指针,初始化为 "abc123de4fg56" 。可以读写。所以会正常运行。
有一道类似的题目,也是快慢消除法:

对一个ab串进行排序

一个字符串只包含a和b,现在要求对这个字符串进行排序,要求将所有的a放在b的前面

  

 

char * Sort(char * str)
{
    char * p1 = str;
    
    while(*p1=='a')
    {
        ++p1;
    }
    char * p2 = p1;
    while(*p2!='')
    {
        if(*p2=='a')
        {
            *p1= 'a';
            *p2= 'b';
            ++p1;        
        }
        ++p2;
    }
    return str;
}

 我另外写的代码:

#include<iostream>
using namespace std;

void sortStr(char *s)
{
    int i,j;
    j=0;
    while(s[j]=='a')
    {
        j++;//j作为存储新数据的标志点
    }
    i=j;
    while(s[i]!='')
    {
        if(s[i]=='a')
        {
             swap(s[i],s[j]);
            //s[j]='a'; 和上面的swap作用等同
            //s[i]='b';

            j++;
        }
        i++;

    }
     
}
int main()
{
    char str[]="ababaaa";
    sortStr(str);
    cout<<str;
}

思路跟上面的一样,j指向b,首先必须:

while(s[j]=='a')
    {
        j++;//j作为存储新数据的标志点
    }

这里我们必须先把j指向第一个不是a,即b。
然后在第二个while里面我们每次把i向前推进,如果i是a。把s[i]和s[j]交换。
示例:
ababaaa
第一次while后j指向第一个b,j=1;
i=2时,s[2]=a;交换,变成了aabbaaa
i=3,
i=4; s[4]=a; 把s[2]和s[4]交换。变成了aaabbaa
i=5;把s[5]和s[3]交换,变成了aaaabba
i=6; aaaaabb
可以看到,j始终代表从字符串范围[0,j]个a

这种快慢消除法的思想可以用在很多方面:

如以前写的,在一个串中消除另一个串中的字符:www.cnblogs.com/youxin/p/3294150.html

面试题:删除字符串中多余的空格

给定字符串,删除开始和结尾处的空格,并将中间的多个连续的空格合并成一个。 
比如 “  I like     http://hi.baidu.com/mianshiti  ” 会变成 "I like http://hi.baidu.com/mianshiti"。

算法的文字描述如下:第一步:初始化:用i指针控制输出开始为0,j指针从0处开始扫描;
第二步:左边空格:当j遇见第一个不是空格的字符,赋给i处.i指向下一位;
第三步:中间以及后面空格:继续扫描,如果遇见空格则赋给i处,i指向下一位,后面空格就忽略直到下一个不是空格字符赋给i处,i指向下一位。
第四步:给字符串加一个''并且返回。算法结束。

#include<iostream>
using namespace std;

char *deleteSurplusSpace(char * str)
{
    char *p=str;
    int j=0;

    //delete left space 
    while(*p==' ')
    {
        p++;
    }
     
    while(*p)
    {
        if(*p!=' ')
        {
            str[j++]=*p;
        }
        else
        {
            while(*p==' ')
            {
                p++;
            }
            str[j++]=' ';

            p--;//这里很重要,因为后面p++;

        }
        
        p++;
    }
    
    str[j]='';

    return str;
}

int main()
{
    char str[]="    A  B    C   DE     ";
    char *p=deleteSurplusSpace(str);
    cout<<p;
}

输出:

A B C DE 请按任意键继续. . .

虽然我知道用快慢消除法,可是程序写起来不容易写对,很多细节值得注意。

相似题:

从第一字符串中删除第二个字符串中所有的字符

原文地址:https://www.cnblogs.com/youxin/p/3293460.html