【问题标题】:How to replace a substring in C when the substring is similar to the replacement string?当子字符串与替换字符串相似时,如何替换C中的子字符串?
【发布时间】:2014-06-09 01:10:09
【问题描述】:

我用 C 语言创建了一个程序,它使用 strstrstrncpysprintf 函数将所有子字符串替换为替换字符串。我的程序的唯一缺陷是,当您要替换例如搜索“The”并想用“There”替换它,这会导致无限循环,因为程序一直在寻找它刚刚替换的内容。我怎样才能在 C 中解决这个问题,或者是否有另一种方法可以在 C 中实现这样的功能?谢谢。

替换函数:(多次调用,直到找不到任何匹配项)。

char *searchAndReplace(char *text, char *search, char *replace){
  char buffer[MAX_L];
    char *ptr;
    char *modText = malloc(4096);
    if(!(ptr = strstr(text, search))){
        return;
    }
    strncpy(buffer, text, ptr-text);
    sprintf(buffer+(ptr-text), "%s%s", replace, ptr + strlen(search));
    strcpy(text, buffer);

【问题讨论】:

  • 请发布您的代码的代表性示例。
  • last 替换文本的尾部开始搜索 next 替换。即“TheQuestion”将“The”替换为“There”,然后开始在“ThereQuestion”的“Q”处搜索下一个“The”。
  • @WhozCraig 我究竟如何让它从那里开始,这就是我卡住的地方我无法弄清楚如何确定那个位置。
  • @Nassim,你在重复调用你的函数吗?
  • @merlin2011,是的,它反复调用,直到没有更多匹配项。

标签: c string substring


【解决方案1】:

您可以返回一个指向原始字符串中上一次替换后位置的指针,然后在下次使用该指针而不是原始指针调用您的函数。

请注意,您通常应该在下面的代码中使用strncpy 而不是strcpy,但我试图尽可能多地保留您的原始代码,所以我做了简化假设。

#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#define MAX_L 4096
char *searchAndReplace(char *text, char *search, char *replace){
    char buffer[MAX_L];
    char *ptr;
    if(!(ptr = strstr(text, search))){
        return NULL;
    }
    strncpy(buffer, text, ptr-text);
    sprintf(buffer+(ptr-text), "%s%s", replace, ptr + strlen(search));
    strcpy(text, buffer);
    return ptr + strlen(search);
}

int main(){
    char* original = malloc(MAX_L);
    memset(original, 0, MAX_L);
    strcpy(original, "The The End Is Nigh");


    char* current = original;
    do {
        current = searchAndReplace(current, "The", "There");
    } while (current);

    printf("%s\n", original);
}

输出:

There There End Is Nigh

【讨论】:

  • 不错的解决方案!我会尝试让它适用于我的程序。谢谢老兄。
  • 下一个练习,制作一个就地执行并防止缓冲区溢出的版本..:)
【解决方案2】:

您可以查找搜索字符串,将其复制到缓冲区,附加替换字符串,将指针移到找到字符串的位置。循环执行此操作,直到找不到搜索字符串。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_L 1000

char *searchAndReplace(char *text, char *search, char *replace)
{
   char buffer[MAX_L];
   char *ptr;
   char *modText = NULL;

   buffer[0] ='\0';
   while ( ptr = strstr(text, search) )
   {
      strncat(buffer, text, ptr-text);
      strcat(buffer, replace);

      // If you are looking for "xx" in "xxxx",
      // There are two ways of looking at this search.
      //                                 xxxx
      // You can either look at it as    ^^
      //                                   --
      // i.e. two matches, or
      //                                 xxxx
      //                                 ^^
      //                                  --
      //                                   ++
      // i.e. three matches

      // If the first interpretation is desired...
      // text = ptr + strlen(search);

      // If the second interpretation is desired...
      text = ptr + 1;

   }
   strcat(buffer, text);

   modText = malloc(strlen(buffer) + 1);
   strcpy(modText, buffer);
   return modText;
}

int main(int argc, char** argv)
{
   char* out = searchAndReplace(argv[1], argv[2], argv[3]);
   printf("%s\n", out);

   // Free the memory allocated and returned from searchAndReplace
   free(out);
}

当我跑步时

./test "ab cc ccd" c xyz

我得到以下输出

ab xyzxyz xyzxyzd

更新

只是为了测试如果我尝试 WhozCraig 的建议会发生什么。

>> ./test "xxxxxx" xx xxx xxxxxxxxxxxxxxxx

我不确定 OP 对此有何期望。

【讨论】:

  • 以“xxxxxx”作为源文本、“xx”作为搜索文本、“xxx”作为替换文本运行它应该证明......很有趣。结果应该是九个x。 (提示:text = ptr + 1 并非完全符合预期)。
  • @WhozCraig 我刚刚添加了运行该案例的输出。
  • 有趣。通常,您预计会发生崩溃,但是随着参数 1 的增长,您开始破坏搜索和替换字符串(即参数 2 和 3),因此实际上您停止了。让您在调用searchAndReplace() 之前和之后添加:printf("[%s] =&gt; [%s]\n", argv[2], argv[3]); 会很有趣。
  • @JonathanLeffler 我得到了预期的结果,[xx] =&gt; [xxx] 进行了更改。我不知道你为什么认为这会有所作为。
  • 好的;我的错。我没有注意到您的代码中存在内存泄漏,因为您分配了放置修改后的字符串的空间并且没有释放它。 WhozCraig 测试的一个更极端的变体是./test xxxxxxxxxxxxz x xxxxxxxxxxxxxxxxxxxxxxxy,它对我来说崩溃了——堆栈溢出。这并不完全公平。另一个答案可以触发相同的问题,但是缓冲区大小要大得多,因此需要更多的努力才能打破它。这就是向外界发布的程序被滥用的方式。作为程序员,你的职责是确保滥用不会破坏任何东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-03
  • 2013-07-23
  • 1970-01-01
相关资源
最近更新 更多