一重循环实现删除子字符串(C++)

  从一个字符串里删除子串是非常常见的操作,如:

void deletestr(const char *str, const char* sub_str, char *result)

  str 指向的是主串,sub_str 是子串,rersult 是处理后的结果。当str 指向 “abcdabcd”、sub_str 指向 “ab" 时,处理完成后的结果是 result 指向 “cdcd”,result 已经分配了和 str 一样长的空间。

  通常我们的第一反应就是通过二重循环实现。当出现第一个与子串首字符相同的字符时,开始一个新循环来比较。

  显然这个方法是容易想到的,当字符串很长或者子串出现的次数很多时,效率也就不高了,那么可不可以用一重循环来实现呢?我们仔细想想,这个问题是很好解决的。

void deletestr(const char *str, const char* sub_str, char *result)
{
    //获得子串的长度
    int sublen = 0;
    const char *t = sub_str;
    while(*t++ != '\0')
    {
        sublen++;
    }

    int pos = 0;
    int pp = 0;
    int repos = 0; // 结果子串的索引
    while(*(str + pos) != '\0')
    {
        char t = *(str + pos);
        if(t == *(sub_str + pp)) // 重复子串起始位置
        {
            *(result + repos) = t;
            repos++;

            if(pp < sublen - 1) // 还未完全重复
            { 
                pp++;
            }
            else if(pp == sublen - 1) // 完全重复了
            {
                pp = 0;
                repos -= sublen; // 回溯下标位置
            }            
        }
        else{ // 不是一样的字符
            *(result + repos) = t;
            repos++;
        }
        pos++;
    }
    *(result + repos) = '\0';
}

  其实思想很容易理解,首先不管是不是重复,都复制到result指定的串中,当判断 if(pp == sublen - 1) 条件成立时,意味着出现了完全相同的子串,这时就需要将记录 result 字符长度变量 repos 减去子串长度,回到子串开始出现的位置,再开始复制,此时会覆盖掉之前记录在 result 里子串。

 

posted on 2013-08-11 22:40  AquWang  阅读(2633)  评论(0编辑  收藏  举报