代码之家  ›  专栏  ›  技术社区  ›  Bdfy

如何替换c中的子字符串?

c
  •  2
  • Bdfy  · 技术社区  · 14 年前

    这个例子有效,但我认为内存泄漏。简单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;
        }
    

    4 回复  |  直到 14 年前
        1
  •  11
  •   David Gelhar    14 年前

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

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

    另外,每次替换一个实例时执行另一个malloc/free是相当昂贵的。

    更好的方法是对输入字符串执行两次传递:

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

    • strlen(字符串)+匹配项*(strlen(替换)-strlen(substr))+1

    • 再次遍历源字符串,复制/替换

        2
  •  1
  •   EboMike    14 年前

    解释这部分:

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

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

        3
  •  1
  •   Sunny Shukla    9 年前

    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)));
    }
    
        4
  •  0
  •   user411313    14 年前
    • 标准不是C89/C99,因此您的代码=>没有ANSI C
    • 最好在malloc之后直接进行空测试

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