输入2个字符串S1和S2,要求删除字符串S1中出现的所有子串S2,即结果字符串中不能包含S2。
提示:输入数据的设计使得不可能出现输出为空的情况。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*
* 输入2个字符串S1和S2,要求删除字符串S1中出现的所有子串S2,
* 即结果字符串中不能包含S2。
* 提示:输入数据的设计使得不可能出现输出为空的情况。
*/
char* str_remove_key(const char* src,const char* key);
int main(void)
{
char *src = "ccaabbccddcckkccmmccppccqqccxx";
//char *src = "xxww";
char* p =str_remove_key(src,"cc");
printf("%s\n",p);
free(p);
return 0;
}
char* str_remove_key(const char* src,const char* key)
{
int keyLen = strlen(key);
// cc aabb ccddcckkccmmccppccqqccxx
char *xx = (char*)malloc(strlen(src)+1);
char *dest = (char*)malloc(strlen(src)+1);
char *xtemp = xx;
int lastIndex = 0;
int i=0;
while((xx = strstr(src,key))!=NULL)
{
int len = xx - src;
if(len){
for(i=0;i<len;i++){
dest[lastIndex+i] = *(src+i);
}
lastIndex += i;
// printf("lastIndex = %d\n",lastIndex);
// dest[lastIndex] = '\0';
}else{
// do nothing !
}
// printf("src = %s , dest = %s\n",src,dest);
xx +=keyLen;
src = xx;
}
dest[lastIndex] = '\0';
strcat(dest,src);
// printf("-------------- src = %s , dest = %s\n",src,dest);
free(xtemp);
return dest;
}
整体思路如下:
- 用
strstr()
函数来不断查找子串的位置;然后保存子串前面的字符集;然后让子串丢弃前面的关键子串。并改变src
为返回的子串;不断查找,直到src
中没有子串了为止。
strstr(“abcd”,”ab”) –> “abcd”
strstr(“abcd”,”bc”) –> “bcd”
上面这两个栗子足以说明,为什么要让strstr()得到的返回值去丢弃前面的关键子串了。
步骤如下:
首先定义返回值
char* dest
,因为不知道会是多大,但是最大就是和src
大小相同。于是char *dest = (char*)malloc(strlen(src)+1);
定义查找返回的子串
char *xx
。因为也不知道多大,但最大也就和src
相同。于是char *xx = (char*)malloc(strlen(src)+1);
。同时定义一个临时指针xtemp
,指向当前的定义的xx
(为了后续的free(xtemp)
)。最关键的一步:定义
dest
的当前需要移动到哪。这里使用了两个变量来共同定义的。分别是lastIndex
与i
。- 这里为什么要定义两个变量呢?不显得多余吗?
- 答: 注意:这里的
i
是要给后续的前字符串用的。因为前字符串是一个一个字符放入到dest
中的。i
是每次查找之后,被strstr
函数丢弃的子串需要的索引。而lastIndex
呢,是要记录dest
现在的可用空间索引。所以,每次增加一个字符到dest
,实际上是应该存放到lastIndex + i
所指的位置的空间里面的。
- 然后就是循环查找关键子串是否存在于
src
中,使用的就是库函数strstr(src,key)
。该函数的特点是,找到了,就返回当前key
的位置(指针)。找不到就返回NULL
。
- 循环给
xx
赋值,只要xx
不为NULL
就获取被丢弃的长度int len = xx-src
。判断len
,如果len>0
,说明前面有被丢弃的字符串。那么,就通过一个for
循环取src
所指的内容*(src+i)
并存放到dest
对应的位置*dest[lastIndex+i]
。for
结束,就给lastIndex
再次赋值:lastIndex = i
;因为这时候的i
的位置刚好是下次dest
应该存放内容的位置。比如:dest
现在是“abcd”,那么,这时候就该把lastIndex
设置为4
。因为下次就应该存放新的内容到(dest+4)
的位置上。 - 这时候,里面的事情并没有结束。这时候,也有一件重要的事情,就是移动指针
xx
到strlen(key)
的后面。也就是丢弃本次查询到的关键子串。也就要xx += strlen(key);
,然后src = xx;
。这一步是改变循环状态。否则就会死循环,并且不能顺利获取下次查询丢弃的内容了。 - 在循环结束之后,(即使是从来没有进入过循环)。给
dest[lastIndex]
赋值为\0
。并执行strcat(dest,src)
的操作。
- 为什么要执行这一步呢?
- 因为,如果没有查询到,那么返回值应该和
src
相同;如果查询到了,但是,末尾的字符比如是zz
,不是关键子串key(假设关键子串为cc
),那么也应该包括末尾的zz
。
- 循环给
- 到这里,就得到去除关键子串之后的字符串了。但是记得
free(xtemp);
,最后return dest;
返回结果。
OK,看看输出吧:
char *key = "cc";
// 如果char *src = "ccaabbccddcckkccmmccppccqqccxx";
输出如下:aabbddkkmmppqqxx
// 如果char *src = "xxww";
输出如下:xxww