简体   繁体   中英

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.

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

char s[1024] = "marie has apples has";                         
str_replace(s, "has", "blabla");

For starters:

This line

strncpy(buffer, string, p-string);

not necessarily appends a 0 -terminator to what had been copied to buffer .

The following line

strcat(buffer, replace);

however relies on buffer being 0 -terminated.

As buffer had not been initialised and though the 0 -terminator most likely misses the latter line may very well read beyond buffer 's memory and with this invoke the infamous Undefined Behaviour.

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

int replace_str(char* i_str, char* i_orig, char* i_rep)
{
   char l_before[2024];
   char l_after[2024];
   char* l_p;
   int l_origLen;

   l_origLen = strlen(i_orig);
   while (l_p = strstr(i_str, i_orig)) {
      sprintf(l_before ,"%.*s" ,l_p - i_str ,i_str);
      sprintf(l_after ,"%s" ,l_p + l_origLen);
      sprintf(i_str ,"%s%s%s" ,l_before ,i_rep ,l_after);
   }
   return(strlen(i_str));
}

i find some needful corrections to be made in function.. here is new function

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

    if (!(p = strstr(str + i, orig)))
    {
        return str;
    }

    while (str[i])
    {
        if (!(p = strstr(str + i, orig)))
        {
            strcat(buffer, str + i);
            break; //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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM