1

我有以下代码:

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替换字符串单词中所有出现的测试?

4

1 回答 1

1

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

如果您事先不知道字符串和替换的长度,那么您有几个选择:

  1. 首先计算匹配的数量并使用它来计算所需的空间
  2. 在循环中使用realloc以更改分配的内存量
  3. 从对大小的智能猜测开始,然后根据需要使用 realloc
  4. 使用固定大小的缓冲区,如果我们用完就会出错

第一种是最简单的方法,您要使用的方法取决于您的性能要求(如果您很好地掌握了最大字符串大小,则四个最快,但会消耗更多内存,如果您掌握了最大字符串大小,则三个可能是下一个最快的对平均匹配次数有一个很好的了解)。

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

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
于 2013-09-22T05:25:09.490 回答