C 通过只遍历字符串一次来删除字符串中的特定字符

C 通过只遍历字符串一次来删除字符串中的特定字符,c,string,C,String,我在一次采访中被问到这个问题,但我无法回答。 问题是:通过只遍历字符串一次来从给定字符串中删除特定字符。 e、 g.给定字符串为:“aaabbcdabe” 删除所有“b” 输出:“aaacdae” 我创建了这个逻辑,但它不止一次遍历字符串: for(int i=0; str[i]!='\0'; i++) { if(str[i] == 'b') { for(j=i; str[j]!='\0'; j++) { str[j] = str[j+1]

我在一次采访中被问到这个问题,但我无法回答。 问题是:通过只遍历字符串一次来从给定字符串中删除特定字符。 e、 g.给定字符串为:“aaabbcdabe” 删除所有“b” 输出:“aaacdae”

我创建了这个逻辑,但它不止一次遍历字符串:

for(int i=0; str[i]!='\0'; i++)
{
    if(str[i] == 'b')
    {
      for(j=i; str[j]!='\0'; j++)
      {
        str[j] = str[j+1];
      }
    }
}
使用这种逻辑,字符串被遍历不止一次,在外部for循环中遍历一次,在移位操作中遍历多次。
还有其他方法吗?

保留一个指向读取位置的指针和一个指向写入位置的指针。每次读取指针前进时,只有在未删除字符的情况下才通过写入指针进行写入。只有在写入字符时才前进写入指针:

#include <stdio.h>

void remove_chars(char *str, const char c);

int main(void)
{
    char test_str[] = "aaabbcdabe";

    puts(test_str);
    remove_chars(test_str, 'b');

    puts(test_str);

    return 0;
}

void remove_chars(char *str, const char c)
{
    char *write_ptr = str;

    while (*str) {
        if (*str != c) {
            *write_ptr = *str;
            ++write_ptr;
        }
        ++str;
    }
    *write_ptr = '\0';
}

保留一个指向读取位置的指针和一个指向写入位置的指针。每次读取指针前进时,只有在未删除字符的情况下才通过写入指针进行写入。只有在写入字符时才前进写入指针:

#include <stdio.h>

void remove_chars(char *str, const char c);

int main(void)
{
    char test_str[] = "aaabbcdabe";

    puts(test_str);
    remove_chars(test_str, 'b');

    puts(test_str);

    return 0;
}

void remove_chars(char *str, const char c)
{
    char *write_ptr = str;

    while (*str) {
        if (*str != c) {
            *write_ptr = *str;
            ++write_ptr;
        }
        ++str;
    }
    *write_ptr = '\0';
}

这个应该有用。它很短很甜

int newLen = 0;
int oldLen = strlen(str);
for(int i=0; i<oldLen; i++){
    if(str[i] != 'b'){
        str[newLen] = str[i];
        newLen++;
    }
}
str[newLen] = '\0';
int newLen=0;
int oldLen=strlen(str);

对于(inti=0;i这应该行得通。它很短很甜

int newLen = 0;
int oldLen = strlen(str);
for(int i=0; i<oldLen; i++){
    if(str[i] != 'b'){
        str[newLen] = str[i];
        newLen++;
    }
}
str[newLen] = '\0';
int newLen=0;
int oldLen=strlen(str);

对于(int i=0;我在猜测递归…?保留一个指向读取位置的指针和一个指向写入位置的指针。每次读取指针处于高级状态时,只有在未删除字符的情况下才通过写入指针写入,然后再进行写入指针。@DavidBowling听起来不错,(任何东西都比递归好:).OP应该确保写入了终止NUL。我猜是递归。保留一个指向读取位置的指针和一个指向写入位置的指针。每次读取指针前进时,只有在未删除字符的情况下才通过写入指针进行写入,然后前进写入指针。@DavidBowling听起来不错,(任何东西都比递归好:)。OP应确保已写入终止NUL。如果仅针对结尾处的显式NUL写入,请创建一个upboat;)这是最好、最简单的方法。虽然在这种情况下,您甚至不需要
write_ptr
。指向原始字符串的指针是通过副本传递的,因此您可以将其提前到位。如果找到要删除的字符,则将指针提前2,否则只需提前1。@iguanaut如果您编码,这将非常令人印象深刻。”甚至不需要“write_ptr”或至少另一个计数器。使用“如果找到要删除的字符,则将指针前进2,否则只需前进1”看起来非常困难。“因为它没有任何文字。我期待着你发布的解决方案。不,你是对的,它仍然需要至少有一个计数器来记录删除了多少项。请向上看,如果只是为了最后明确的NUL write;)这是最好、最简单的方法。虽然在这种情况下,您甚至不需要
write\u ptr
。指向原始字符串的指针是通过副本传递的,因此您可以将其提前到位。如果找到要删除的字符,则将指针提前2,否则只需提前1。@iguanaut如果您编码,这将非常令人印象深刻“甚至不需要write_ptr”或至少另一个计数器。使用“如果找到要删除的字符,则将指针前进2,否则只前进1”看起来很难做到这一点。"因为它没有任何文字。我期待着你发布的解决方案。不,你是对的,它仍然需要至少有一个计数器的多少项目被删除。这基本上是相同的方法,我在我的解决方案中使用,但数组索引,而不是指针算术。我想我更喜欢在这种情况下的指针符号,但它是好的要查看这两种变体,请注意:您可以通过更改为(int i=0;str[i]!='\0';i++){}的
for来删除对
strlen()
的调用
;此外,最好对数组索引使用
size\t
,因为这是一种保证能够保存任何数组索引的
无符号
整数类型,并且是数组索引的正确类型。+1这与我在解决方案中使用的方法基本相同,但使用数组索引而不是指针算法。我认为我优先考虑r在本例中使用指针表示法,但最好同时看到这两种变体。注意:您可以通过更改为(int i=0;str[i]!='\0';i++){}的
来删除对
strlen()的调用
;此外,最好对数组索引使用
size\t
,因为这是一种保证能够保存任何数组索引的
无符号
整数类型,并且是数组索引的正确类型。+1