How to replace a substring in C when the substring is similar to the replacement string?

StackOverflow https://stackoverflow.com/questions/23257216

  •  08-07-2023
  •  | 
  •  

Question

I've created a program in C which uses the strstr, strncpy, and sprintf functions to replace all substrings with a replacement string. The only flaw with my program is that when you are looking to replace for e.g. searching for "The" and wanting to replace it with "There", this causes as infinite loop, as the program keeps finding what it just replaced. How could I fix this in C, or is there another way to implement such a function in C? Thanks.

Replacement function: (its called multiple times until there are no longer any matches found).

char *searchAndReplace(char *text, char *search, char *replace){
  char buffer[MAX_L];
    char *ptr;
    char *modText = malloc(4096);
    if(!(ptr = strstr(text, search))){
        return;
    }
    strncpy(buffer, text, ptr-text);
    sprintf(buffer+(ptr-text), "%s%s", replace, ptr + strlen(search));
    strcpy(text, buffer);
Was it helpful?

Solution

You can return a pointer to a place in the original string after the previous replacement, and then call your function the next time using that pointer instead of the original pointer.

Note that you should generally use strncpy instead of strcpy everywhere in the code below, but I am trying to preserve as much of your original code as possible, so I have made simplifying assumptions.

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#define MAX_L 4096
char *searchAndReplace(char *text, char *search, char *replace){
    char buffer[MAX_L];
    char *ptr;
    if(!(ptr = strstr(text, search))){
        return NULL;
    }
    strncpy(buffer, text, ptr-text);
    sprintf(buffer+(ptr-text), "%s%s", replace, ptr + strlen(search));
    strcpy(text, buffer);
    return ptr + strlen(search);
}

int main(){
    char* original = malloc(MAX_L);
    memset(original, 0, MAX_L);
    strcpy(original, "The The End Is Nigh");


    char* current = original;
    do {
        current = searchAndReplace(current, "The", "There");
    } while (current);

    printf("%s\n", original);
}

Output:

There There End Is Nigh

OTHER TIPS

You can look for the search string, copy up to that point to the buffer, append the replace string, advance your pointer to the point past the where you found the string. Do this in a loop until you don't find the search string.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_L 1000

char *searchAndReplace(char *text, char *search, char *replace)
{
   char buffer[MAX_L];
   char *ptr;
   char *modText = NULL;

   buffer[0] ='\0';
   while ( ptr = strstr(text, search) )
   {
      strncat(buffer, text, ptr-text);
      strcat(buffer, replace);

      // If you are looking for "xx" in "xxxx",
      // There are two ways of looking at this search.
      //                                 xxxx
      // You can either look at it as    ^^
      //                                   --
      // i.e. two matches, or
      //                                 xxxx
      //                                 ^^
      //                                  --
      //                                   ++
      // i.e. three matches

      // If the first interpretation is desired...
      // text = ptr + strlen(search);

      // If the second interpretation is desired...
      text = ptr + 1;

   }
   strcat(buffer, text);

   modText = malloc(strlen(buffer) + 1);
   strcpy(modText, buffer);
   return modText;
}

int main(int argc, char** argv)
{
   char* out = searchAndReplace(argv[1], argv[2], argv[3]);
   printf("%s\n", out);

   // Free the memory allocated and returned from searchAndReplace
   free(out);
}

When I run

./test "ab cc ccd" c xyz

I get the following output

ab xyzxyz xyzxyzd

Update

Just to test what would happen if I tried WhozCraig's suggestion.

>> ./test "xxxxxx" xx xxx
xxxxxxxxxxxxxxxx

I am not sure what the OP's expectations are about this.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top