This example works but I think that the memory leaks. Function used in the simple web server module and thus shared memory grows if you use this function.
Explain this part:
if ( substr == NULL || replacement == NULL ) return strdup (string);
Why do you return a copy of the existing string? This will leak memory, and it's unnecessary.
You also never free the duplicate if the while loop is skipped (i.e. the condition is never met).
One problem I can see is that if the replacement string contains the search string, you'll loop forever (until you run out of memory).
For example:
char *result = str_replace("abc", "a", "aa");
Also, doing another malloc/free every time you replace one instance is pretty expensive.
A better approach would be to do exactly 2 passes over the input string:
the first pass, count how many instances of the search string are present
now that you know how many matches, compute the length of your result & malloc once:
strlen(string) + matches*(strlen(replacement)-strlen(substr)) + 1
make a second pass through the source string, copying/replacing
here an example, only with one new memoryblock:
/* precondition: s!=0, old!=0, new!=0 */
char *str_replace(const char *s, const char *old, const char *new)
{
size_t slen = strlen(s)+1;
char *cout = malloc(slen), *p=cout;
if( !p )
return 0;
while( *s )
if( !strncmp(s, old, strlen(old)) )
{
p -= cout;
cout= realloc(cout, slen += strlen(new)-strlen(old) );
p += strlen( strcpy(p=cout+(int)p, new) );
s += strlen(old);
}
else
*p++=*s++;
*p=0;
return cout;
}
This will replace all occurrence of "str" with "rep" in "src"...
void strreplace(char *src, char *str, char *rep)
{
char *p = strstr(src, str);
do
{
if(p)
{
char buf[1024];
memset(buf,'\0',strlen(buf));
if(src == p)
{
strcpy(buf,rep);
strcat(buf,p+strlen(str));
}
else
{
strncpy(buf,src,strlen(src) - strlen(p));
strcat(buf,rep);
strcat(buf,p+strlen(str));
}
memset(src,'\0',strlen(src));
strcpy(src,buf);
}
}while(p && (p = strstr(src, str)));
}