【问题标题】:Replacing character in a string [duplicate]替换字符串中的字符[重复]
【发布时间】:2012-10-05 02:17:29
【问题描述】:

可能重复:
What is the function to replace string in C?

我正在尝试用多个字符替换字符串中的某个字符。这是我正在尝试做的一个示例。

假设我有字符串“aaabaa”

我想将所有出现的字符“b”替换为 5 个“c”。

所以当我完成时,“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()
  • 让我们暂时假设字符串中的 每个 char 都是一个 'b'...您的目标缓冲区最好比占用它的字符串长 5 倍调用时间。至少,如果您希望 就地 完成此操作,您需要 对算法进行编码以考虑 缓冲区 的大小(不仅仅是string) 被替换的内容占用。不这样做最终会导致灾难。

标签: c string character


【解决方案1】:

如果您想在一般情况下执行此操作,而不必担心尝试调整缓冲区大小,您应该 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;
}

【讨论】:

  • 如果没有const char *s 而不是char *s,是否可以?
【解决方案2】:

您的问题是您将“ccccc”替换为原始字符串,从而在您希望替换的内容之后覆盖剩余的字符...您应该复制到一个新字符串并跟踪两个索引 - 每个索引一个。

很高兴您声明 char s[20] 大于原始字符串的大小加上替换值,否则您会在关键登录系统中创建缓冲区溢出漏洞 :-)

干杯,

【讨论】:

    【解决方案3】:

    需要声明第二个字符数组。在下面的代码中,它只是在条件失败时将数组 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);
    }
    

    【讨论】:

      【解决方案4】:

      你可以使用不同的变量

      #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);
      }
      

      【讨论】:

        【解决方案5】:
        #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"

        【讨论】:

          【解决方案6】:

          好吧,如果您要动态分配数组,您可能必须分配第二个数组。这是必要的,因为您的字符串 s 只分配了固定数量的内存。

          因此,我建议不要尝试覆盖 for 循环中的字符,而是增加一个计数器,告诉您新数组的大小。您的计数器应该从原始字符串的大小开始,每次找到 'b' 的实例时递增 4。然后,您应该能够编写一个函数,将修改后的字符串适当地复制到大小为 [counter] 的新字符缓冲区,每次找到“b”时插入 5 个 c。

          【讨论】:

            【解决方案7】:

            使用这个功能:

            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"));

            【讨论】:

            • 不过,这并不是对所有实例都适用......而且这真的很脆弱,因为您使用的是静态缓冲区。
            • ... 并祈祷 *st 不引用 4097 个字符或更长的字符串,并以 'b' 结尾。
            猜你喜欢
            • 2011-10-10
            • 2021-06-17
            • 1970-01-01
            • 2014-11-05
            • 2022-01-07
            • 2020-12-19
            • 2014-08-23
            相关资源
            最近更新 更多