Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

How to replace a specified number of occurrences of a cstring in C?

Languages such as Python have the replace(s, old, new [,maxreplace]) method which not only replaces a substring but also allows one to limit the number of replacements made. How can I implement this in C without use of Regex? It is preferred that the cstring is not modified and can be of any length including 0. This was what I tried. I would like this function to have a parameter max_replacements such that if and only if it equates to 0, all occurrences are replaced.

char *strnrep(char *haystack, char needle, char replacement, int max_replacements) {
    char buf[strlen(haystack) + 1];
    int count = 0;
    strcpy(buf, haystack);
    for (unsigned j = 0; j < strlen(buf); ++j) {
        if (buf[j] == needle) count++;
    }
    int j = 0;
    if (max_replacements == 0) {
        max_replacements = count;
    }
    while (j < max_replacements) {
        for (int i = 0; buf[i] != '\0'; i++) {
            if (buf[i] == needle) {
                buf[i] = replacement;
                break;
            }
        }
        j++;
    }
    return strdup(buf);
}

But only works for char rather than char* or char[]

NOTE This question is NOT duplicate to what one of the commenters is suggesting. I am asking for a specified number of occurrences rather than all.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

Updating previous replace solution

Don’t look for all occurence, stop if you reach the limit with something like:

        if (count >= max)
            break;
// You must free the result if result is non-NULL.
char *str_replace(const char *orig, char *rep, char *with, int max) {
    char *result; // the return string
    const char *ins;    // the next insert point
    char *tmp;    // varies
    int len_rep;  // length of rep (the string to remove)
    int len_with; // length of with (the string to replace rep with)
    int len_front; // distance between rep and end of last rep
    int count;    // number of replacements

    // sanity checks and initialization
    if (!orig || !rep)
        return NULL;
    len_rep = strlen(rep);
    if (len_rep == 0)
        return NULL; // empty rep causes infinite loop during count
    if (!with)
        with = "";
    len_with = strlen(with);

    // count the number of replacements needed
    ins = orig;
    for (count = 0; tmp = strstr(ins, rep); ++count) {
        ins = tmp + len_rep;
        if (count >= max)
            break;
    }

    tmp = result = malloc(strlen(orig) + (len_with - len_rep) * count + 1);

    if (!result)
        return NULL;

    // first time through the loop, all the variable are set correctly
    // from here on,
    //    tmp points to the end of the result string
    //    ins points to the next occurrence of rep in orig
    //    orig points to the remainder of orig after "end of rep"
    while (count--) {
        ins = strstr(orig, rep);
        len_front = ins - orig;
        tmp = strncpy(tmp, orig, len_front) + len_front;
        tmp = strcpy(tmp, with) + len_with;
        orig += len_front + len_rep; // move to next "end of rep"
    }
    strcpy(tmp, orig);
    return result;
}
int main(void)
{
    const char* input = "foo bar one bar two bar three bar";
    char *replace = str_replace(input, "bar", "john", 2);
    printf("before: %s\nafter: %s\n", input, replace);
    free(replace);
    return 0;
}

will output

before: foo bar one bar two bar three bar
after: foo john one john two bar three bar
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading