【问题标题】:Is there a good way to remove a character from a string without copying all the characters following it?有没有一种很好的方法可以从字符串中删除一个字符而不复制它后面的所有字符?
【发布时间】:2010-05-21 18:17:17
【问题描述】:
// The first example:
char text[] = "henri";
char *p;
p = text;
*(p + 1) = 'E'; // Output = hEnri
// Now If we want to remove the "e" ie hnri, we would go for?????
     *(p + 1)=????? 

显而易见的答案是将数组的其余部分“向后”复制一个位置。但这似乎……不愉快。肯定有更好的方法吗?

【问题讨论】:

  • 我认为单次赋值操作不可能做到这一点。
  • @Codism 更好地使用你的脑袋:-)
  • 不幸的是,“开始复制”(或至少移动)就是答案。
  • @Frust: *(int32_t*)(p+1) = *(int32_t*)(p+2);不要在家里这样做。
  • @Codism - 完全错误。当您拥有的唯一工具是火箭筒时,一切都开始看起来像一个指针:) 因此,在这种情况下,火箭筒比锤子更合适。

标签: c arrays string


【解决方案1】:

复制最好的解决方案,当您从数组中删除元素时,它确实是唯一的解决方案。 (你可以对数组末尾的元素进行特殊处理,但仅此而已。)我不明白为什么它如此糟糕。

你需要做两件事之一。两者都涉及一些复制。

1) 将'n'复制到'E'所在的位置,'r'复制到'n'所在的位置,'i'复制到'r'所在的位置,然后null终止它。

2) 将“h”复制到“E”所在的位置,然后始终使用指向“h”新位置的指针。这可能并不总是一种选择。

【讨论】:

  • 如果字符串很长并且分配在堆上,您也可以复制指针并节省一些循环。移动指针更有效(例如链表)
【解决方案2】:
*++p = 'h';
puts(p);

【讨论】:

  • 因为我很确定这不是面试官正在寻找的过于聪明的答案。 -耸耸肩-
【解决方案3】:

您必须将所有剩余的字符上移一位。没有办法说“跳过这个字符”。

while (*p)
{
    *p = *p++;
}

编辑:呃,我是怎么犯这个错误的?现在修好了。 p 在字符串的末尾仍然是非空的,但 *p 不会。

【讨论】:

  • 这里有两个错误:1. while(p) 将继续循环直到 p 为 NULL,你想要 while(*p) 2. 即使这样,你也需要复制结尾 '\0'
  • @BlueRaja:*p 完全是个脑残,谢谢。但是你不需要复制终止的 0,这将在循环的最后一次迭代中完成。
  • *p=*p++ 不会导致未定义的行为,因为您修改 p 并在没有中间序列点的情况下读取它(不仅仅是确定要存储的值)?此外,我看不到一种订购修改的方式来做正确的事情(它绝对不适用于gcc)。不过,如果您将其更改为 *p=*(p+1);++p;,它确实可以工作。
  • @Mike Dinsdale:我认为分配是一个序列点,所以它会读取、修改、递增。如果它在 gcc 中不起作用,那我一定是错的 - 我实际上并没有尝试过。
  • @Vicky:根据this question 的答案,分配不是非用户定义类型的序列点。不过,我不确定它是否会有所帮助,因为即使增量会保证在分配之前发生,它是否发生在*p= 的第一个参数)被评估之前是不确定的(如果我们能相信Wikipedia ;))
【解决方案4】:

将其后的字符向下移动 1(包括末尾的 null)

顺便说一句,你最后会得到两个空值。

【讨论】:

    【解决方案5】:

    这不是复制数组。我在同一个数组中移动数据。

    for (p = text + 1; *p != '\0'; ++p) {
      *p = *p + 1;
    }
    

    一个更老套的解决方案是将“h”放在“e”所在的位置,并返回一个指向新起点的指针。

    *p + 1 = *p;
    p = p + 1;
    

    【讨论】:

      【解决方案6】:

      应该这样做:

      memmove(p+1, p+2, 4);

      我们移动四个字符是因为我们还想复制空终止符。

      【讨论】:

        【解决方案7】:

        如果不复制以下字符来填补空洞,就无法从 C 字符串中删除任何内容

        但是你可以改变你的数据结构并使用字符串以外的东西。例如,您可以使用字符串片段的数组或链表。这有时被称为“绳索”。

        当然,当您需要将数据传递给其他需要 C 字符串的函数时,您必须复制整个内容。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-06
          • 2016-01-02
          • 2021-11-17
          • 2014-09-15
          相关资源
          最近更新 更多