替换字符串中的标记

时间:2013-09-22 01:03:08

标签: c string

我有以下代码:

char *repl_word(char *word, char *repl)
{
    const char *p1 = strstr(word,"<")+1;
    const char *p2 = strstr(p1,">");
    size_t len = p2-p1;
    char *src = (char*)malloc(len+1);
    if (src == NULL)
        return word;
    strncpy(src,p1,len);
    src[len] = '\0';
    char *find = "test";
    char *found;
    char *res = malloc(strlen(src) + strlen(repl) - strlen(find) + 1);
    if (res == NULL)
        return src;
    found = strstr(src, find);

    if (found == NULL){
        free(res);
        return src;
    }
    res[0] = '\0';
    strncpy(res, src, (size_t)(found - src));
    strcat(res, repl);
    strcat(res, found + strlen(find));
    return res;
}

工作正常但仅适用于"test"的第一次出现。 如果单词是"<testtesttest1234>",则它不会替换所有内容。

如何使用repl?

替换字符串中所有出现的test

1 个答案:

答案 0 :(得分:1)

我将忽略删除<>的代码,只关注问题的核心。

如果你事先不知道琴弦和替换的长度,那么你有几个选择:

  1. 首先计算匹配数并使用它来计算所需的空间
  2. 在循环中使用realloc来更改分配的内存量
  3. 从大小的智能猜测开始,然后根据需要使用realloc
  4. 使用固定大小的缓冲区,如果我们用完了就错误输出
  5. 第一种是最简单的方法,你想要使用的方法取决于你的性能要求(如果你对最大字符串大小有很好的把握,那么四个是以更多内存为代价最快的,三个可能是下一个如果您对平均匹配数有所了解,最快。

    实现最简单的方法只需要两个循环,一个用于查找匹配,另一个用于替换:

    char *strreplace(char *src, char* find, char *repl)
    {
      char *target;    // Will store our new string
      char *final;     // Will use to store the pointer of the final string
      char *str = src; // Will use for searching
      int matches = 0; 
    
      // First count the matches (if strlen(repl) <= strlen(word) 
      // you could skip this and just allocate strlen(src)
    
      while (str = strstr(str, find)) { 
        matches ++;
        str++;
      }
    
      target = malloc(1 + strlen(src) + 
                  (sizeof(char) * (matches * 
                           (strlen(repl) - strlen(find))
                       )));
      if (target == NULL) { 
        return src; // Or NULL, or whatever to indicate an error
      }
    
      final = target;
    
      // Now copy everything 
      str = src;
      while (str = strstr(str, find)) { 
    
        // Copy string before the match
        if (str > src) { 
          strncpy(target, src, (str - src)); 
          target += (str - src);
      src += (str - src);
        }
    
        // Copy replacement 
        strncpy(target, repl, strlen(repl));
    
        // Move pointers 
        str++;                  // Move past the match in our searching pointer
        src += strlen(find);    // Move past the string in our src
        target += strlen(repl); // Move past the replacement in our target
    
      }
      // Finally copy the rest of the string, if there's some left
      if (*src) {
        strncpy(target, src, strlen(src));
      }
    
      return final;
    }
    

    我想我可能会在那里使用太多指针,我觉得可以对替换代码进行简化,但目前我看不到它。

    你可以采取这种做法并使其适应你想要的,一些测试(尝试覆盖角落的情况):

    printf("%s\n", strreplace("testtesttest1234", "test", "foo"));
    printf("%s\n", strreplace("testtesttest1234", "test", "foobar"));
    printf("%s\n", strreplace("somethingtestsomethingteasesttest", "test", "foobar"));
    

    输出:

    foofoofoo1234
    foobarfoobarfoobar1234
    somethingfoobarsomethingteasestfoobar