简体   繁体   English

从 C 中的字符串中删除子字符串

[英]Remove a substring from a string in C

I want to remove a particular substring from a string for example my main string is "ababccdabce" and I want to remove "abc" from it so it will become "abcde" .我想从字符串中删除一个特定的子字符串,例如我的主字符串是"ababccdabce"并且我想从中删除"abc"所以它会变成"abcde"

I just wanted to know if there is a predefined function in C to do that, and if not, how to do it?我只是想知道 C 中是否有一个预定义的函数可以做到这一点,如果没有,该怎么做?

There is no predefined function in C to remove a given substring from a C string, but you can write one using strstr and memmove . C 中没有预定义的函数可以从 C 字符串中删除给定的子字符串,但您可以使用strstrmemmove编写一个。 Note that if you remove the substring in place, you cannot use memcpy nor strcpy because these have undefined behavior if the source and destination arrays overlap.请注意,如果您原地删除子字符串,则不能使用memcpystrcpy因为如果源数组和目标数组重叠,它们将具有未定义的行为。

Here is the code:这是代码:

#include <string.h>

char *strremove(char *str, const char *sub) {
    size_t len = strlen(sub);
    if (len > 0) {
        char *p = str;
        while ((p = strstr(p, sub)) != NULL) {
            memmove(p, p + len, strlen(p + len) + 1);
        }
    }
    return str;
}

Note that the resulting string may contain the substring as is the case in your example.请注意,结果字符串可能包含子字符串,就像您的示例中的情况一样。

Netherwire suggested an optimisation: Netherwire建议进行优化:

char *strremove(char *str, const char *sub) {
    size_t len = strlen(sub);
    if (len > 0) {
        char *p = str;
        size_t size = 0;
        while ((p = strstr(p, sub)) != NULL) {
            size = (size == 0) ? (p - str) + strlen(p + len) + 1 : size - len;
            memmove(p, p + len, size - (p - str));
        }
    }
    return str;
}

Further honing the code, I came up with an even more efficient version using the 2 finger-method: only copying the fragments between matches starting after the first match:进一步磨练代码,我想出了一个使用 2 指法的更有效的版本:只在第一场比赛之后开始的比赛之间复制片段:

char *strremove(char *str, const char *sub) {
    char *p, *q, *r;
    if (*sub && (q = r = strstr(str, sub)) != NULL) {
        size_t len = strlen(sub);
        while ((r = strstr(p = r + len, sub)) != NULL) {
            memmove(q, p, r - p);
            q += r - p;
        }
        memmove(q, p, strlen(p) + 1);
    }
    return str;
}

Here is the same method without any calls to memmove :这是相同的方法,没有调用memmove

char *strremove(char *str, const char *sub) {
    char *p, *q, *r;
    if (*sub && (q = r = strstr(str, sub)) != NULL) {
        size_t len = strlen(sub);
        while ((r = strstr(p = r + len, sub)) != NULL) {
            while (p < r)
                *q++ = *p++;
        }
        while ((*q++ = *p++) != '\0')
            continue;
    }
    return str;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM