如何在C语言中从字符串中删除给定索引处的字符?

58

如何从字符串中删除一个字符?

如果我有字符串"abcdef",我想要删除"b",我该怎么做呢?

使用以下代码可以轻松删除第一个字符:

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

int main()
{
    char word[] = "abcdef";
    char word2[10];

    strcpy(word2, &word[1]);

    printf("%s\n", word2);
 
    return 0;
}

并且

strncpy(word2, word, strlen(word) - 1);

使用 slice 方法可以让我得到一个去掉最后一个字符的字符串,但是我仍然不知道如何删除中间的字符。


给定字符的所有出现次数:https://dev59.com/VVHTa4cB1Zd3GeqPU9SX - Ciro Santilli OurBigBook.com
22个回答

75

memmove函数可以处理重叠区域,建议尝试使用该函数(未经测试,可能会有+-1的问题)。

char word[] = "abcdef";  
int idxToDel = 2; 
memmove(&word[idxToDel], &word[idxToDel + 1], strlen(word) - idxToDel);

之前:"abcdef"

之后:"abdef"


47

试试这个:

void removeChar(char *str, char garbage) {

    char *src, *dst;
    for (src = dst = str; *src != '\0'; src++) {
        *dst = *src;
        if (*dst != garbage) dst++;
    }
    *dst = '\0';
}

测试程序:

int main(void) {
    char* str = malloc(strlen("abcdef")+1);
    strcpy(str, "abcdef");
    removeChar(str, 'b');
    printf("%s", str);
    free(str);
    return 0;
}

结果:

>>acdef

1
当你不知道要删除的字符的位置时,这样做会更好! - gsamaras
既然这段代码已经假定字符存在,为什么不直接使用 for(dst = str; *dst != garbage; dst++){} *dst = '\0'; 呢? - JayB

17

我删除所有指定字符的方法:

void RemoveChars(char *s, char c)
{
    int writer = 0, reader = 0;

    while (s[reader])
    {
        if (s[reader]!=c) 
        {   
            s[writer++] = s[reader];
        }

        reader++;       
    }

    s[writer]=0;
}

5
点赞支持好的结构和变量名,相比上面简洁的版本,我更容易理解这段代码。谢谢。 - Ace.C
很棒的解决方案!我只会投票给函数名称,例如 removeAllCharOccurrences - Sany

4
int chartoremove = 1;

strncpy(word2, word, chartoremove);
strncpy(((char*)word2)+chartoremove, ((char*)word)+chartoremove+1,
    strlen(word)-1-chartoremove);

丑得要命


这个不起作用:空终止符未设置。 - chqrlie

4

真的很惊讶这个之前没有被发布过。

strcpy(&str[idx_to_delete], &str[idx_to_delete + 1]);

相当高效简单。大多数实现中,strcpy 使用 memmove

4
根据C99第7.21.2.3节(“strcpy函数”)所述,“如果在重叠的对象之间进行复制,则行为未定义。” 至于在“大多数实现”中使用memmove- [需要引用]。因此,“THIS IS UNDEFINED BEHAVIOR.” - Maya
strcpy并不总是使用memmove,不要依赖它,事实上它几乎从不使用。 - chqrlie

3
char a[]="string";
int toBeRemoved=2;
memmove(&a[toBeRemoved],&a[toBeRemoved+1],strlen(a)-toBeRemoved);
puts(a);

试试这个。 memmove 会覆盖它。已测试。


1
这与6年前stacker发布的被接受答案没有任何区别。 - chqrlie

3

这是一个从字符串中移除元音字母的示例

 #include <stdio.h>
    #include <string.h>
    
    void lower_str_and_remove_vowel(int sz, char str[])
    {   
        for(int i = 0; i < sz; i++)
        {
            str[i] = tolower(str[i]);
            if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' || str[i] == 'o' || str[i] == 'u')
            {
                for(int j = i; j < sz; j++)
                {
                    str[j] = str[j + 1];
                }
                sz--;
                i--;
            }
        }
    }
    
    int main(void)
    {
        char str[101];
        gets(str);
        int sz = strlen(str);// size of string
        lower_str_and_remove_vowel(sz, str);
        puts(str);       
    }

输入:

tour

输出:

tr

2
gets(str)会让你的点赞数下降。 - chqrlie

1

以下将通过从第一个字符串参数中删除出现在第二个字符串参数中的任何字符来扩展问题。

/*
 * delete one character from a string
 */
static void
_strdelchr( char *s, size_t i, size_t *a, size_t *b)
{
  size_t        j;

  if( *a == *b)
    *a = i - 1;
  else
    for( j = *b + 1; j < i; j++)
      s[++(*a)] = s[j];
  *b = i;
}

/*
 * delete all occurrences of characters in search from s
 * returns nr. of deleted characters
 */
size_t
strdelstr( char *s, const char *search)
{ 
  size_t        l               = strlen(s);
  size_t        n               = strlen(search);
  size_t        i;
  size_t        a               = 0;
  size_t        b               = 0;

  for( i = 0; i < l; i++)
    if( memchr( search, s[i], n))
      _strdelchr( s, i, &a, &b);
  _strdelchr( s, l, &a, &b);
  s[++a] = '\0';
  return l - a;
}

0

以下代码应该可以解决问题:

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

int main (int argc, char const* argv[])
{
    char word[] = "abcde";
    int i;
    int len = strlen(word);
    int rem = 1;

    /* remove rem'th char from word */
    for (i = rem; i < len - 1; i++) word[i] = word[i + 1];
    if (i < len) word[i] = '\0';

    printf("%s\n", word);
    return 0;
}

更简单的写法:for (i = rem; i < len; i++) word[i] = word[i + 1];,并移除 if (i < len) word[i] = '\0'; - chqrlie

0

编辑: 根据最新版本的库,更新了代码zstring_remove_chr()

来自一个名为zString的C语言BSD许可的字符串处理库。

https://github.com/fnoyanisi/zString

去除一个字符的函数

int zstring_search_chr(char *token,char s){
    if (!token || s=='\0')
        return 0;

    for (;*token; token++)
        if (*token == s)
            return 1;

    return 0;
}

char *zstring_remove_chr(char *str,const char *bad) {
    char *src = str , *dst = str;

    /* validate input */
    if (!(str && bad))
        return NULL;

    while(*src)
        if(zstring_search_chr(bad,*src))
            src++;
        else
            *dst++ = *src++;  /* assign first, then incement */

    *dst='\0';
    return str;
}

使用示例

   char s[]="this is a trial string to test the function.";
   char *d=" .";
   printf("%s\n",zstring_remove_chr(s,d));

示例输出

  thisisatrialstringtotestthefunction

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