Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replace all occurrences of a substring in a string in C

I'm trying to make a function in C to replace all occurrences of a substring in a string. I made my function, but it only works on the first occurrence of the substring in the bigger string.

Here is the code so far:

void strreplace(char string*, char search*, char replace*) {
    char buffer[100];
    char *p = string;

    while ((p = strstr(p, search))) {
        strncpy(buffer, string, p-string);
        buffer[p-string] = '\0'; //EDIT: THIS WAS MISSING
        strcat(buffer, replace);
        strcat(buffer, p+strlen(search));
        strcpy(string, buffer);
        p++;
    }
} 

I'm not new to C programming, but I'm missing something here.

Example: for input string "marie has apples has", searching for "has" and replace with "blabla"

In the first "has" is replaced correctly, but the second one is not. The final output is "marie blabla apples hasblabla". Notice the second "has" is still there.

What am I doing wrong? :)

EDIT Is is working now. Adding the null terminating character fixed the problem. I know the resulting string can be bigger than 100. It's a school homework so I won't have strings longer than 20 or so.

like image 562
Erik Blenert Avatar asked Sep 05 '15 13:09

Erik Blenert


2 Answers

It doesn't seem clear to me what algorithm you are trying to follow, it all looks fishy to me. What's probably the simplest approach is:

  • search for first occurrence of the "needle" (searched-for substring)
  • copy the part before the first occurrence to the result buffer
  • append the replacement string to the result buffer
  • increment the p pointer so it points just after the needle
  • GOTO 10
void str_replace(char *target, const char *needle, const char *replacement)
{
    char buffer[1024] = { 0 };
    char *insert_point = &buffer[0];
    const char *tmp = target;
    size_t needle_len = strlen(needle);
    size_t repl_len = strlen(replacement);

    while (1) {
        const char *p = strstr(tmp, needle);

        // walked past last occurrence of needle; copy remaining part
        if (p == NULL) {
            strcpy(insert_point, tmp);
            break;
        }

        // copy part before needle
        memcpy(insert_point, tmp, p - tmp);
        insert_point += p - tmp;

        // copy replacement string
        memcpy(insert_point, replacement, repl_len);
        insert_point += repl_len;

        // adjust pointers, move on
        tmp = p + needle_len;
    }

    // write altered string back to target
    strcpy(target, buffer);
}

Warning: You also have to be careful about how you call your function. If the replacement string is larger than the needle, your modified string will be longer than the original one, so you have to make sure your original buffer is long enough to contain the modified string. E.g.:

char s[1024] = "marie has apples has";                         
str_replace(s, "has", "blabla");
like image 53
The Paramagnetic Croissant Avatar answered Oct 16 '22 00:10

The Paramagnetic Croissant


char *replace_str(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
int i=0;

while(str[i]){
    if (!(p=strstr(str+i,orig)))  return str;
    strncpy(buffer+strlen(buffer),str+i,(p-str)-i);
    buffer[p-str] = '\0';
    strcat(buffer,rep);
    printf("STR:%s\n",buffer);
    i=(p-str)+strlen(orig);
}

return buffer;
}

int main(void)
{
  char str[100],str1[50],str2[50];
  printf("Enter a one line string..\n");
  gets(str);
  printf("Enter the sub string to be replaced..\n");
  gets(str1);
  printf("Enter the replacing string....\n");
  gets(str2);
  puts(replace_str(str, str1, str2));

  return 0;
}

Input: marie has apples has

Output: marie blabla apples blabla

like image 44
StackUser Avatar answered Oct 15 '22 23:10

StackUser