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


题目:删除字符串中的数字并压缩字符串 。如字符串”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]
= '\0';
}
#else
char *ddc(char *s)
{
char *p = s;
char *res = p;
while(*s)
{
if(*s < '0' || *s > '9')
{
*p++ = *s;
}
s
++;
}
*p = '\0';
return res;
}

#endif

int main(void)
{
//char *str = "abc123de4fg56"; segmentation fault。
char str[] = "abc123de4fg56";
#if USE
ddc(str);
printf(
"result is %s\n",str);
#else
printf(
"result is %s\n",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!='\0')
{
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]!='\0')
{
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指向下一位。
第四步:给字符串加一个'\0'并且返回。算法结束。

#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]
='\0';

return str;
}

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

输出:

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

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

相似题:

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

智能推荐

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
© 2014-2019 ITdaan.com 粤ICP备14056181号  

赞助商广告