【问题标题】:Replace all occurrences of a substring in a string in C替换C中字符串中所有出现的子字符串
【发布时间】:2015-09-05 13:35:31
【问题描述】:

我正在尝试在 C 中创建一个函数来替换字符串中所有出现的子字符串。我做了我的函数,但它只适用于较大字符串中子字符串的第一次出现。

这是目前为止的代码:

void strreplace(char string*, char search*, char replace*) {
    char buffer[100];
    char *p = string;

    while ((p = strstr(p, search))) {
        strncpy(buffer, string, p-string);
        buffer[p-string] = '\0'; //EDIT: THIS WAS MISSING
        strcat(buffer, replace);
        strcat(buffer, p+strlen(search));
        strcpy(string, buffer);
        p++;
    }
} 

我对 C 编程并不陌生,但我在这里遗漏了一些东西。

示例:对于输入字符串“marie has apples has”,搜索“has”并替换为“blabla”

第一个“有”被正确替换,但第二个不是。 最终输出是“marie blabla apples hasblabla”。注意第二个“has”仍然存在。

我做错了什么? :)

编辑 现在正在工作。添加空终止字符解决了这个问题。 我知道生成的字符串可能大于 100。这是学校作业,所以我的字符串不会超过 20 左右。

【问题讨论】:

  • @GerardvanHelden 可能是因为它们不在 C 标准库中? (你在考虑 PHP 吗?)
  • 您如何看待结果?使用调试器?
  • @ace 公平点,评论已删除。认为 PHP 函数在内部映射到 C stdlib(他们经常这样做),但不是这种情况。
  • 这个函数有点冒险,因为你不确定输入的字符串是否能容纳100字节。但除此之外,您的 while 循环每次通过循环时只会将 p 增加 1。我认为它需要增加替换字符串的长度。
  • 另外,strcat(buffer, p+strlen(search));strcpy(string, buffer); 是干什么用的?你真的不需要第一行,你可以把第二行移出循环......

标签: c string str-replace


【解决方案1】:

我似乎不清楚您要遵循什么算法,我觉得这一切都很可疑。最简单的方法可能是:

  • 搜索第一次出现的“needle”(搜索的子字符串)
  • 将第一次出现之前的部分复制到结果缓冲区
  • 将替换字符串附加到结果缓冲区
  • 增加p 指针,使其正好指向指针之后
  • 转到 10
void str_replace(char *target, const char *needle, const char *replacement)
{
    char buffer[1024] = { 0 };
    char *insert_point = &buffer[0];
    const char *tmp = target;
    size_t needle_len = strlen(needle);
    size_t repl_len = strlen(replacement);

    while (1) {
        const char *p = strstr(tmp, needle);

        // walked past last occurrence of needle; copy remaining part
        if (p == NULL) {
            strcpy(insert_point, tmp);
            break;
        }

        // copy part before needle
        memcpy(insert_point, tmp, p - tmp);
        insert_point += p - tmp;

        // copy replacement string
        memcpy(insert_point, replacement, repl_len);
        insert_point += repl_len;

        // adjust pointers, move on
        tmp = p + needle_len;
    }

    // write altered string back to target
    strcpy(target, buffer);
}

警告:您还必须小心调用函数的方式。如果替换字符串比针大,你修改的字符串会比原来的长,所以你必须确保你的原始缓冲区足够长,可以容纳修改后的字符串。例如:

char s[1024] = "marie has apples has";                         
str_replace(s, "has", "blabla");

【讨论】:

  • 你用文字描述的算法是我想要实现的。我知道我可以做得更好,但这只是学校的作业。感谢您的输入:)
【解决方案2】:

对于初学者:

这一行

strncpy(buffer, string, p-string);

不一定将0-terminator 附加到已复制到buffer 的内容中。

下面一行

strcat(buffer, replace);

但是依赖于 buffer0-终止。

由于buffer 尚未初始化,尽管0-terminator 很可能错过了后一行,但很可能会超出buffer 的内存,从而调用臭名昭著的未定义行为。

【讨论】:

  • 忘记了 strncpy 之后的 0 终止符。谢谢:)
【解决方案3】:
char *replace_str(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
int i=0;

while(str[i]){
    if (!(p=strstr(str+i,orig)))  return str;
    strncpy(buffer+strlen(buffer),str+i,(p-str)-i);
    buffer[p-str] = '\0';
    strcat(buffer,rep);
    printf("STR:%s\n",buffer);
    i=(p-str)+strlen(orig);
}

return buffer;
}

int main(void)
{
  char str[100],str1[50],str2[50];
  printf("Enter a one line string..\n");
  gets(str);
  printf("Enter the sub string to be replaced..\n");
  gets(str1);
  printf("Enter the replacing string....\n");
  gets(str2);
  puts(replace_str(str, str1, str2));

  return 0;
}

输入:玛丽有苹果有

输出: marie blabla apples blabla

【讨论】:

    【解决方案4】:
    int replace_str(char* i_str, char* i_orig, char* i_rep)
    {
       char l_before[2024];
       char l_after[2024];
       char* l_p;
       int l_origLen;
    
       l_origLen = strlen(i_orig);
       while (l_p = strstr(i_str, i_orig)) {
          sprintf(l_before ,"%.*s" ,l_p - i_str ,i_str);
          sprintf(l_after ,"%s" ,l_p + l_origLen);
          sprintf(i_str ,"%s%s%s" ,l_before ,i_rep ,l_after);
       }
       return(strlen(i_str));
    }
    

    【讨论】:

    • 你能解释一下为什么这比其他 4 个答案更好吗?
    【解决方案5】:

    我发现需要在功能上进行一些必要的更正。 这是新功能

    char *replace_str(char *str, char *orig, char *rep)
    {
        static char buffer[1024];
        char *p;
        int i = 0;
    
        if (!(p = strstr(str + i, orig)))
        {
            return str;
        }
    
        while (str[i])
        {
            if (!(p = strstr(str + i, orig)))
            {
                strcat(buffer, str + i);
                break; //return str;
            }
            strncpy(buffer + strlen(buffer), str + i, (p - str) - i);
            buffer[p - str] = '\0';
            strcat(buffer, rep);
            //printf("STR:%s\n", buffer);
            i = (p - str) + strlen(orig);
        }
    
        return buffer;
    }
    

    【讨论】:

    • 请不要只给出一段代码,而是解释这些变化以及它们为何重要。还;这能解决问题吗?
    猜你喜欢
    • 1970-01-01
    • 2013-07-10
    • 2012-08-01
    • 2013-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-23
    相关资源
    最近更新 更多