【问题标题】:Recursive C String replace递归 C 字符串替换
【发布时间】:2011-09-27 07:12:15
【问题描述】:

我是 C 编程的新手,以前只使用 C++ 和 String 类,但我想知道如何用另一个字符串递归替换一个字符串。

我的代码是这样的,但它似乎无法正常工作,我无法确定它失败的地方。它可以在一个替换上正常工作,但不止一个,它会失败。

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

char *replace_str(char *str, char *orig, char *rep)
{
    int current_index = 0;
    static char buffer[10000];

    if (!strstr(str, orig))  // Is 'orig' even in 'str'?
    {
        return str;
    }

    while (1)
    {        
        char *p;

        if (!(p = strstr(str + current_index, orig)))  // Is 'orig' even in 'str'?
        {
            return buffer;
        }

        strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
        buffer[p-str] = '\0';

        sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));


        printf("%d -> %s\n", current_index, buffer);

        current_index = (p - str) + strlen(rep);

        str = buffer;
    }

    return buffer;
}

int main(void)
{
    puts(replace_str("hello world world", "world", "world2"));

    return 0;
}

在这个例子中,它会打印:

 0 -> hello world2 world
12 -> hello world2 world22
hello world2 world22

【问题讨论】:

  • “失败”是什么意思?是停止替换还是出现错误?
  • 我说的不是“递归”而是“迭代”。循环直到你找不到搜索字符串。
  • 它失败了,因为它不再正确替换。这是示例输出:0 -> hello world2 world 12 -> hello world2 world22 hello world2 world22
  • 递归函数中的静态缓冲区向我发出警告标志。您可以管理的字符串长度有一个未经检查的上限,这意味着该函数的所有嵌套调用都使用相同的存储。这也意味着没有线程安全。这不一定是错的。但这对我来说是一个危险信号。

标签: c string recursion replace


【解决方案1】:

问题是 str = buffer; 。您正在有效地更改源指针,并且搞砸了您的代码。

在while循环开始之前使用下面的代码

 char bk[100]
 strcpy(bk,str);

并用 bk 替换 while 循环中的所有 str 出现。它将起作用。

【讨论】:

    【解决方案2】:

    这可能不是最好的实现,但是here 你会找到一个 stringReplace 函数来完成这项任务。

    关于您的代码。首先,调用者最好提供它的 dest 缓冲区,而不是在函数中使用静态缓冲区。然后,您不检查缓冲区溢出。

    你的

        strncpy(buffer, str, p-str); // Copy characters from 'str' start to 'orig' st$
    

    会从 A 复制到 A,但第一次迭代除外。这不好,缓冲区不应该重叠。请改用memmove

    但整个想法并不干净,因为您更新了用作源的同一缓冲区以捕获其他事件。

    在某些时候,您会覆盖输入(当 str 和 buffer 指向同一事物时)丢失信息,因为您的替换单词比要替换的原始单词长,因此您不会保留“原始下一个字符”。 (如果您尝试使用“work”而不是“world2”,它应该可以工作)...

    所以你的 current_index 应该索引原始字符串 str (你永远不会做 str = buffer ),你将附加到你的内部缓冲区你需要的部分(直到出现“世界”,如果找到然后附加“ world2",将 current_index 更新为 "world" 的长度并继续)。

    我愿意(或多或少尽量保持你的原创想法)

    #include <stdio.h>
    #include <string.h>
    
    char *replace_str(char *str, const char *orig, const char *rep)
    {
        size_t buf_index = 0;
        static char buffer[10000];
    
        if (!strstr(str, orig))  // Is 'orig' even in 'str'?
        {
            return str;
        }
    
        buffer[0] = 0;
        for(;;)
        {        
            char *p;
    
            if (!(p = strstr(str, orig)))  
            {
               strcpy(buffer + buf_index, str);
               return buffer;
            }
            strncpy(buffer + buf_index, str, p - str);
            strcpy(buffer + buf_index + (p - str), rep);
            buf_index += (p-str) + strlen(rep);
            str = p + strlen(orig);
        }
        return buffer;
    }
    
    int main(void)
    {
        puts(replace_str("hello world world world", "wor", "world2"));
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      使用这个递归函数rplcStr(),它被编码为简单的replace c++。

      string rplcStr(string x, string y, string z){
      // Done by Raafat Maurice in 29 Feb 2012
      // this function will replace all string (y) found in string (x) by the string (z).
              if (x.find(y.c_str(),0) != -1 ) {
                  return (rplcStr (x.substr(0,  x.find(y.c_str(),0) ) + z + x.substr( x.find(y.c_str(),0) + y.size()  ) ,y,z));
              }
              else {
                  return (x);
              }
      }
      

      【讨论】:

      • 问题标记为 C,而不是 C++
      猜你喜欢
      • 2017-04-24
      • 2011-05-09
      • 1970-01-01
      • 2013-08-21
      • 2017-10-28
      • 2023-03-04
      • 1970-01-01
      • 2012-04-19
      • 1970-01-01
      相关资源
      最近更新 更多