【问题标题】:How to remove all occurrences of a given character from string in C?如何从C中的字符串中删除所有出现的给定字符?
【发布时间】:2012-03-27 18:17:03
【问题描述】:

我正在尝试从 C 中的字符串中删除一个字符。我的代码遇到的问题是它从字符串中删除了该字符的第一个实例,但也擦除了字符串中该字符之后的所有内容。例如,从 'hello' 中删除 'l' 会打印出 'he' 而不是 'heo'

int i;
char str1[30] = "Hello", *ptr1, c = 'l';
ptr1 = str1;
for (i=0; i<strlen(str1); i++)
{
    if (*ptr1 == c) *ptr1 = 0;
    printf("%c\n", *ptr1);
    ptr1++;
}

我需要为此使用指针,并希望尽可能简单,因为我是 C 的初学者。 谢谢

【问题讨论】:

  • 提示:在删除过程中,您希望将其他字母向上移动以覆盖您删除的字母。 *ptr1 = 0; 不是这样做的方法。
  • 您还使用了 for/loop 来处理每个字符的索引,但您从未使用实际索引(i 的值)
  • 另一件要记住的事情,在 CS 中,字符串是空终止的。
  • 意思是在 C 中是字符串.... 阅读障碍打字机.....

标签: c string


【解决方案1】:

你可以这样做:

void remove_all_chars(char* str, char c) {
    char *pr = str, *pw = str;
    while (*pr) {
        *pw = *pr++;
        pw += (*pw != c);
    }
    *pw = '\0';
}

int main() {
    char str[] = "llHello, world!ll";
    remove_all_chars(str, 'l');
    printf("'%s'\n", str);
    return 0;
}

这个想法是保留一个单独的读写指针(pr 用于读取,pw 用于写入),始终推进读取指针,仅在不指向给定字符时推进写入指针。

【讨论】:

  • 感谢您的简单回答和描述,解决了它。也感谢其他人的意见。
  • 为什么melpon.org/wandbox/permlink/qZPdItEH7hjg4sl3 会导致分段错误? *pw=*ptr++;*pw=(*ptr)++; 有什么区别
  • @Destructor *pw=*ptr++ 增加指针(正确),而(*ptr)++ 增加字符(错误)。
【解决方案2】:

如果您在原地删除字符,则每次删除字符时都必须将字符串的其余部分向左移动一位,这不是很有效。最好的方法是使用第二个数组来获取过滤后的字符串。例如,您可以像这样更改您的代码。

int i;
char str1[30] = "Hello", *ptr1, c = 'l';
char str2[30] = {0}, *ptr2;
ptr1 = str1;
ptr2 = str2;
for (i=0; i<strlen(str1); i++)
{
    if (*ptr1 != c) *ptr2++=*ptr1;
    ptr1++;
}
printf("%s\n", str2);

【讨论】:

  • 除非你真的不应该在这样的循环条件下调用strlen(),这是一个很好的答案。当然,这是从问题中的代码继承的错误,但是...
  • @Jonathan Leffler,这个答案犯了一些基本错误,使其无法成为一个好的答案。每次删除字符时,您不必将字符串的剩余部分向左移动。这意味着一个嵌套循环,答案表明它不是必需的。此外,是否将字符从一个字符串复制到另一个字符串也没有区别,因为它们都是同一个 RAM 块。实际上,使用第二个字符串可能效率更低,因为使用远处的内存块可能会导致缓存未命中。
【解决方案3】:

问题是当你遇到第一个匹配c 的字符时,你会在此处插入一个空字符。这意味着您实际上是在切断字符串的其余部分。

您需要做的是,当您找到匹配的字符时,将以下字符移回一个位置。然后,您需要根据删除的字符数在最后插入空字符。

【讨论】:

    【解决方案4】:
    char str1[30] = "Hello", *prt1, c = 'l';
    char str2[30], *prt2;
    prt1 = str1;
    prt2 = str2;
    while(*prt1 != 0)
    {
        if(*prt1 != c)
        {
             *prt2 = *prt1;
             prt2++;  
        }
        prt1++;
    }
    *prt2 = '\0';
    

    【讨论】:

      【解决方案5】:

      我知道这是一种重复的答案,但此代码是用于解决问题的函数版本。我想,由于提问者是初学者,他可能会从问题的分解版本中学到很多东西。

      int del_x_char(char *p, int x)
      {
          char *q;
          x=first_occurance(p, 'i')/*you can replace any character that you want delete with 'i'*/
          q=p+x;
          while(*q=*(q+1))
              q++;
          *q='\0';
          return 0;
      }
      int first_occurance(char *q, char phar)
      {
          int i=0;
          while(*q)
          {   
              if(*q++==phar)
                  return i;
              i++;
          }
          return -1;
      }
      

      【讨论】:

        【解决方案6】:

        改变一下

        if (*ptr1 == c) *ptr1 = 0;
        

        if (*ptr1 == c) continue;
        

        正如@ouah 所说,它在第一个 NULL 字符处中断..

        【讨论】:

        • 这还不够。
        【解决方案7】:

        C 将字符串定义为 “以第一个 null 字符 终止并包括在内的连续字符序列”

        【讨论】:

        • 是的,但很难解释这个问题。
        猜你喜欢
        • 2013-12-18
        • 2020-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-08-07
        • 2012-12-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多