如何从C中的字符串中删除所有出现的给定字符?

问题描述:

我试图从C中的一个字符串中删除一个字符。我的代码中存在的问题是它从字符串中删除了字符的第一个实例,同时也删除了该字符串中的所有字符之后的所有内容。例如,去除“你好”打印“他”“L”而不是“HEO”如何从C中的字符串中删除所有出现的给定字符?

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. 由于

+1

提示:在删除过程中,您希望将其他字母向上移动以覆盖您删除的字母。 '* ptr1 = 0;'不是这样做的。 – 2012-03-27 18:18:49

+0

您还正在使用for/loop来解决每个char的索引,但是您从不使用实际索引(i的值) – 2012-03-27 18:20:33

+0

另一件需要记住的事情是,在CS中,字符串以null结尾。 – 2012-03-27 18:21:25

你可以这样说:

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写作),总是提前读出指针,推进写指针只有当它不指向给定的字符时。

+0

谢谢你简单的回答和描述,解决了它。也感谢所有人的意见。 – boutrosc 2012-03-27 18:42:16

+0

为什么http://melpon.org/wandbox/permlink/qZPdItEH7hjg4sl3导致分段错误? '* pw = * ptr ++;'和'* pw =(* ptr)++;' – Destructor 2016-04-27 15:10:06

+0

@Destructor'* pw = * ptr ++'增加指针(正确),'(* ptr)++'增加字符(不正确)。 – dasblinkenlight 2016-04-27 15:21:15

C定义一个字符串作为“字符的连续序列通过终止并且包括第一空字符

+1

是的,但几乎不能解释问题的答案。 – 2014-01-22 02:00:56

只是改变

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

if (*ptr1 == c) continue; 

为@ouah说,它打破了在第一个NULL字符..

+0

这不是一个足够的解决办法。 – 2014-01-22 02:02:36

的问题是,当你遇到一个匹配c的第一个字符,你插入一个空字符在那里。这意味着你基本上切断了字符串的其余部分。

您需要做的是在找到匹配的字符时,将下列字符移回到一个位置。然后,您需要在最后插入空字符,具体取决于您删除了多少个字符。

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'; 

如果您删除的地方,你将不得不串一个地方休息,每次左移你删除一个角色的人物,这是不是很有效。最好的方法是让第二个数组采用过滤后的字符串。例如,你可以像这样改变你的代码。

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); 
+1

除了你真的不应该在这样的循环条件下调用'strlen()',这是一个很好的答案。当然,这是一个从问题中的代码继承的错误,但... – 2014-01-22 01:59:13

+0

@Jonathan Leffler,这个答案使一些基本的错误,防止它成为一个很好的答案。每次删除角色时,不必将字符串的剩余部分移到左侧。这意味着一个嵌套的循环,答案证明不是必需的。此外,无论是将字符从一个字符串复制到另一个字符串都没有区别,因为它们都是同一块RAM。事实上,使用第二个字符串可能效率更低,因为使用远距离内存块会导致缓存未命中。 – 2014-10-28 15:35:35

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

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