删除C中字符串的所有子字符串

removing all sub strings of a string in C

我一直在尝试从给定字符串中删除所有出现的子字符串,但我的代码有一个我不知道如何解决的错误。当两个子字符串背靠背时,我的代码只能删除其中一个。

这是我的代码:

void removeSub(char *str, char *sub, char *new) {
    int len = strlen(sub);
    char *subp = strstr(str, sub);
    int position = subp - str;
    for (int i = 0; i <= strlen(str); i++) {
        if (i >= position && i < position + len) {
            continue;
        }

        if (i == position + len - 1) {
            // update position
            subp = strstr(str + i - 1, sub);
            position = subp - str;
        }
        
        char ch = str[i];
        strncat(new, &ch, 1);
    }
}

代码的快速解释:我将字符串一个字符一个字符地复制到另一个字符串(新)中,每当我沿途看到子字符串时,我的代码就会继续循环,什么也不做。传递子字符串时,我重新定位下一个子字符串。 (我知道这不是很有效,但我是新手,不知道很多方法和功能)

问题是循环不断前进。当你删除一个子字符串时,你需要从循环索引中减去一个 i 所以你再次搜索相同的位置。

您的代码有多个问题:

  • 循环 for (int i = 0; i <= strlen(str); i++) 的效率非常低,因为 str 的长度在循环的每次迭代中都会重新计算。你应该简单地写:

    for (int i = 0; str[i] != '[=10=]'; i++)
    
  • 当您跳过匹配的子字符串时,它后面的字符被复制并且 i 在循环中递增,因此无法正确测试下一个匹配项。

  • 附加单个字符的代码效率低下:您应该有一个指向目标字符串末尾的指针,而不是 strncat(new, &ch, 1); 并写入 *p++ = str[i]; 并设置 null循环结束后的终止符。

这是修改后的版本:

#include <string.h>
// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
    char *p = new;
    size_t len = strlen(sub);
    if (len > 0) {
        const char *subp;
        while ((subp = strstr(str, sub)) != NULL) {
            memcpy(p, str, sub - str);
            p += sub - str;
            str = sub + len;
        }
    }
    strcpy(p, str);
    return new;
}

还有一个没有库调用的替代方案:

// remove all occurrences of sub in str into destination buffer new
// return a pointer to the destination string
char *removeSub(cont char *str, const char *sub, char *new) {
    char *p = new;
    while (*str) {
        if (*str == *sub) {  /* potential substring match */
            for (size_t i = 1;; i++) {
                if (sub[i] == '[=12=]') {  /* substring match */
                    str += i;
                    break;
                }
                if (str[i] != sub[i]) {
                    *p++ = *str++;
                    break;
                }
            }
        } else {
            *p++ = *str++;
        }
    }
    *p = '[=12=]';
    return new;
}