替换字符串中的字符

6

可能是重复的问题:
C语言中替换字符串的函数是什么?

我想要将字符串中的某个字符替换为多个字符。以下是一个示例:

假设我有一个字符串 "aaabaa"

我想要用5个字符 "c" 替换所有出现的字符 "b".

所以当我完成时,"aaabaa" 变成了 "aaacccccaa"

我已经写好了下面的代码:

#include <stdio.h>
#include <string.h>
int main(void)
{
    char s[20] = "aaabaa";
    int i, j;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            for (j=0; j<5; j++)
            {
                s[i+j] = 'c';
            }
        }
    }
    printf("%s\n", s);
}

这个函数的输出结果是"aaaccccc"。看起来它只是用c覆盖了最后两个a。有没有办法让最后几个a不被覆盖?


你需要使用memmove()函数。 - Agnius Vasiliauskas
1
假设字符串中的每个字符都是“b”...你的目标缓冲区最好比当前占用它的字符串长5倍。如果你想要原地完成这个操作,那么你必须编写算法来考虑正在进行替换的内容所占用的缓冲区(而不仅仅是字符串)的大小。不这样做最终会导致灾难。 - WhozCraig
7个回答

11

如果您想一般地完成此操作,而不必担心尝试调整缓冲区大小,您应该malloc一个足够大的新字符串来容纳结果:

/* return a new string with every instance of ch replaced by repl */
char *replace(const char *s, char ch, const char *repl) {
    int count = 0;
    const char *t;
    for(t=s; *t; t++)
        count += (*t == ch);

    size_t rlen = strlen(repl);
    char *res = malloc(strlen(s) + (rlen-1)*count + 1);
    char *ptr = res;
    for(t=s; *t; t++) {
        if(*t == ch) {
            memcpy(ptr, repl, rlen);
            ptr += rlen;
        } else {
            *ptr++ = *t;
        }
    }
    *ptr = 0;
    return res;
}

使用方法:

int main() {
    char *s = replace("aaabaa", 'b', "ccccc");
    printf("%s\n", s);
    free(s);
    return 0;
}

可以使用char *s而不是const char *s吗? - dforce

5
您的问题在于您将“ccccc”替换为原始字符串,从而覆盖了您希望替换的其余字符... 您应该将其复制到一个新字符串中,并跟踪两个索引 - 每个字符串一个。
并且很高兴您声明char s [20]大于原始字符串加上替换值的大小,否则您将在关键登录系统中创建缓冲区溢出漏洞 :-)
干杯,

1
需要声明一个第二个字符数组。在下面的代码中,当条件失败时,它只是将数组s的内容复制到s1中。
#include <stdio.h>
#include <string.h>
int main(void)
{
  char s[20] = "aaabaa";
  char s1[1024];
  int i, j, n;
  for (i=0, n = 0; s[i]!= '\0'; i++)
  {
    if (s[i] == 'b')
    {
        for (j=0; j<5; j++)
        {
            s1[n] = 'c';
            n++;
        }
    }
    else
    {
        s1[n] = s[i];
        n++;
    }
}
s1[n] = '\0';
printf("%s\n", s1);
}

1

您可以使用不同的变量

#include <stdio.h>
#include <string.h>
int main(void)
{
    char s[20] = "aaabaa";
    char temp[20]="";
    int i, j,k;
    k=0;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            for (j=0; j<5; j++)
            {
                temp[k] = 'c';
                k++;
            }
        }
        else
        {
            temp[k]=s[i];
            k++
        }
    }
    printf("%s\n", temp);
}

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

int main(void)
{
    char temp[20];
    char s[20] = "aaabaa";
    int i, j;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            strcpy(temp,s[i+1]); //copy rest of the string in this case 'aa'
            for (j=0; j<5; j++)
            {
                s[i+j] = 'c';
            }
            s[i+j] = '\0';   // here we get s = "aaaccccc"
            strcat(s,temp); // concat rest of the string (temp = "aa") after job is done. 
                           //  to this point s becomes s = "aaacccccaa"
        }
    }
    printf("%s\n", s); //s = "aaacccccaa". 
}

在这里,我们使用一个缓冲区(temp)来存储待替换字符后面的字符串。 当替换完成后,我们将其附加到末尾。

因此,我们得到 s = "aaacccccaa"


0

如果你要动态分配数组,那么你可能需要再分配一个数组。这是必要的,因为你的字符串s只有固定的内存分配。

所以,不要试图在for循环中覆盖字符,我建议你增加一个计数器,告诉你新数组的大小。你的计数器应该从原始字符串的大小开始,每次找到'b'的实例时增加4。然后,你应该能够编写一个适当的函数,将修改后的字符串复制到一个新的char缓冲区中,插入5个c,每次发现一个'b'。


-1
请使用此函数:
char *replace(char *st, char *orig, char *repl) {
  static char buffer[4096];
  char *ch;
  if (!(ch = strstr(st, orig)))
   return st;
  strncpy(buffer, st, ch-st);  
  buffer[ch-st] = 0;
  sprintf(buffer+(ch-st), "%s%s", repl, ch+strlen(orig));
  return buffer;
  }

针对您的情况:printf("%s\n", replace(s,"b","ccccc"));


这并不适用于每个实例,而且由于使用了静态缓冲区,所以非常脆弱。 - nneonneo
祈祷 *st 不引用一个长度为4097个字符或更长,并以'b'结尾的字符串。 - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接