PTN
PTN

Reputation: 1692

Find a replace a substring C

I am trying to do a find a replace but not just for strings but for substrings also. So the program I am working on looks for the word "bar" and append "foo" in front of any instance of "bar". So my approach is that instead of actually appending the string, I replace the whole string "bar" with "foobar". The code I have right now (not fully tested), should find and replace all occurrences of "bar" with "foobar". However, if there is a string that looks like "bar123abc", it does not replace it with "foobar123abc".

This is the code I have:

static void replaceAllString(char *buf, const char *orig, const char *replace)
{
    int olen, rlen;
    char *s, *d;
    char *tmpbuf;

    if (!buf || !*buf || !orig || !*orig || !replace)
        return;

    tmpbuf = malloc(strlen(buf) + 1);
    if (tmpbuf == NULL)
        return;


    olen = strlen(orig);
    rlen = strlen(replace);

    s = buf;
    d = tmpbuf;

    while (*s) {
        if (strncmp(s, orig, olen) == 0) {
            strcpy(d, replace);
            s += olen;
            d += rlen;
        }
        else
            *d++ = *s++;
    }

    *d = '\0';

    strcpy(buf, tmpbuf);
    free(tmpbuf);
}

Upvotes: 0

Views: 329

Answers (1)

Lee Daniel Crocker
Lee Daniel Crocker

Reputation: 13171

Here's how I might do it:

static char *replaceAll(char *buf, int buflen, const char *orig, const char *replace) {
    if (!buf || !*buf || !orig || !*orig || !replace) return buf;

    int olen = strlen(orig), rlen = strlen(replace);

    int max = strlen(buf) + 1;
    if (olen < rlen) {
        max = rlen * ((max / olen) + 1) + 1;
    }
    char *tmpbuf = malloc(max);
    char *bp = buf, *tp = tmpbuf, *sp;

    while (NULL != (sp = strstr(bp, orig))) {
        int f = sp - bp;
        memmove(tp, bp, f);
        memmove(tp + f, replace, rlen);
        tp += f + rlen;
        bp += f + olen;  // no recursive replacement
    }
    strcpy(tp, bp);
    strncpy(buf, tmpbuf, buflen);
    free(tmpbuf);
    return buf;
}

char haystack[128] = "123bar456bar7ba8ar9bar0";

int main(int ac, char *av[]) {
    printf("%s\n", replaceAll(haystack, sizeof haystack, "bar", "foobar"));
}

Note: passing buflen is NOT optional! You DO NOT write to memory buffers you don't know the length of. If I'm interviewing C programmers, this would be an instant "no hire". tmpbuf is allocated the length max, crudely calculated for the worst case (something like "barbarbar"). The heavy lifting here is done by strstr().

Upvotes: 1

Related Questions