Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove a substring from a string in C

Tags:

c

string

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".

I just wanted to know if there is a predefined function in C to do that, and if not, how to do it?

like image 579
Mohit Singh Avatar asked Nov 05 '17 00:11

Mohit Singh


1 Answers

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. 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.

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:

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:

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:

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;
}
like image 150
chqrlie Avatar answered Oct 11 '22 17:10

chqrlie