C 超级难搞定的 删除字符串中的子串

输入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()得到的返回值去丢弃前面的关键子串了。

步骤如下:
  1. 首先定义返回值char* dest,因为不知道会是多大,但是最大就是和src大小相同。于是char *dest = (char*)malloc(strlen(src)+1);

  2. 定义查找返回的子串char *xx。因为也不知道多大,但最大也就和src相同。于是char *xx = (char*)malloc(strlen(src)+1);。同时定义一个临时指针xtemp,指向当前的定义的xx(为了后续的free(xtemp))。

  3. 最关键的一步:定义dest的当前需要移动到哪。这里使用了两个变量来共同定义的。分别是lastIndexi

    • 这里为什么要定义两个变量呢?不显得多余吗?
    • 答: 注意:这里的i是要给后续的前字符串用的。因为前字符串是一个一个字符放入到dest中的。i是每次查找之后,被strstr函数丢弃的子串需要的索引。而lastIndex呢,是要记录dest现在的可用空间索引。所以,每次增加一个字符到dest,实际上是应该存放到lastIndex + i所指的位置的空间里面的。
  4. 然后就是循环查找关键子串是否存在于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)的位置上。
    • 这时候,里面的事情并没有结束。这时候,也有一件重要的事情,就是移动指针xxstrlen(key)的后面。也就是丢弃本次查询到的关键子串。也就要xx += strlen(key);,然后src = xx;。这一步是改变循环状态。否则就会死循环,并且不能顺利获取下次查询丢弃的内容了。
    • 在循环结束之后,(即使是从来没有进入过循环)。给dest[lastIndex]赋值为\0。并执行strcat(dest,src)的操作。
      • 为什么要执行这一步呢?
      • 因为,如果没有查询到,那么返回值应该和src相同;如果查询到了,但是,末尾的字符比如是zz,不是关键子串key(假设关键子串为cc),那么也应该包括末尾的zz
  5. 到这里,就得到去除关键子串之后的字符串了。但是记得free(xtemp);,最后return dest;返回结果。

OK,看看输出吧:

char *key = "cc";
// 如果char *src = "ccaabbccddcckkccmmccppccqqccxx";
输出如下:aabbddkkmmppqqxx
// 如果char *src = "xxww";
输出如下:xxww
  • 2
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值