如何在c中替换substring?

这个例子有效,但我认为内存泄漏。 如果使用此function,则在简单Web服务器模块中使用的函数以及共享内存会增加。

char *str_replace ( const char *string, const char *substr, const char *replacement ){ char *tok = NULL; char *newstr = NULL; char *oldstr = NULL; if ( substr == NULL || replacement == NULL ) return strdup (string); newstr = strdup (string); while ( (tok = strstr ( newstr, substr ))){ oldstr = newstr; newstr = malloc ( strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1 ); memset(newstr,0,strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) + 1); if ( newstr == NULL ){ free (oldstr); return NULL; } memcpy ( newstr, oldstr, tok - oldstr ); memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) ); memcpy ( newstr + (tok - oldstr) + strlen( replacement ), tok + strlen ( substr ), strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) ); memset ( newstr + strlen ( oldstr ) - strlen ( substr ) + strlen ( replacement ) , 0, 1 ); free (oldstr); } return newstr; } 

我可以看到的一个问题是,如果替换字符串包含搜索字符串,您将永远循环(直到内存不足)。

例如:

 char *result = str_replace("abc", "a", "aa"); 

另外,每次更换一个实例时再做一次malloc / free是非常昂贵的。

更好的方法是在输入字符串上完成2次传递:

  • 第一遍,计算搜索字符串的实例数

  • 现在您知道了多少匹配,计算结果和malloc的长度一次:

    strlen(string)+ matches *(strlen(replacement)-strlen(substr))+ 1

  • 通过源字符串进行第二次传递,复制/替换

解释这一部分:

if ( substr == NULL || replacement == NULL ) return strdup (string);

为什么要返回现有字符串的副本? 这会泄漏内存,这是不必要的。

如果跳过while循环(即从未满足条件),也永远不会释放副本。

这将用“src”中的“rep”替换所有出现的“str”……

 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))); } 
  • strdup不是C89 / C99,因此你的代码=>没有ANSI C
  • 最好在malloc之后直接进行NULL测试

这里有一个例子,只有一个新的内存块:

 /* 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; }