【问题标题】:Remove spaces from char-array by using a function with a pointer argument使用带有指针参数的函数从字符数组中删除空格
【发布时间】:2015-02-26 21:26:45
【问题描述】:

所以我正在研究这本书,我遇到了一个练习,它(简要地)希望我使用以下函数删除 char 数组的所有空格:void removeSpaces(char* s)

[包含iostream、cstring并定义了SIZE]

这是 main():

int main() {
  char a[SIZE] = "a bb ccc d";
  cout << a << endl; // a bb ccc d
  removeSpaces(a);
  cout << a << endl; // a bb ccc d instead of abbcccd
}

这是 removeSpaces():

void removeSpace(char* s) {
  int size = strlen(s);

  char* cpy = s;  // an alias to iterate through s without moving s
  char* temp = new char[size]; // this one produces the desired string
  s = temp; // s points to the beginning of the desired string

  while(*cpy) {
      if(*cpy == ' ')
          cpy++;
      else
          *temp++ = *cpy++;
  }

  cout << s << endl; // This prints out the desired result: abbcccd
}

(我选择的名称并不理想,但现在没关系。)所以我的函数基本上做了我想要它做的事情,除了结果在函数范围之外没有任何影响。我怎样才能做到这一点?我错过了什么,我做错了什么?

【问题讨论】:

  • 因为这只是 C 代码。您可能应该添加 C 标签,以便让一些 C 专家给您建议。如果您正在编写 C++ 代码,则不应传递指针。
  • 嗯,这是一本 C++ 书籍(章节:指针)中的练习,所以是的。但我会记住这一点。谢谢。

标签: c++ arrays char spaces


【解决方案1】:

由于您按值传递指针,因此您肯定会更改数组。显然,你会像这样删除空格:

void removeSpaces(char* s) {
    *std::remove(s, s + strlen(s), ' ') = 0;
}

【讨论】:

  • 供参考:en.cppreference.com/w/cpp/algorithm/remove -- 不过看起来有点不舒服。
  • 谢谢,但如果可能的话,我想尽可能避免使用库函数。
  • @moooeeeeep:这段代码有什么不舒服的地方......?
  • 查看文档后,非常清楚这段代码的作用。我觉得不舒服的是在我通常不希望它们出现的地方出现星号和分配。当然,这是一个(主观)背景和个人偏好问题。 (+1 用于促进标准库函数的使用。毕竟它们是用来使用的。)
【解决方案2】:

您的函数甚至不应该进行任何字符串复制。它应该只进行就地替换:

void removeSpace(char* s)
{
    for (char* s2 = s; *s2; ++s2) {
        if (*s2 != ' ')
            *s++ = *s2;
    }
    *s = 0;
}

更简洁:

void removeSpace(char* s)
{
    char* s2 = s;
    do {
        if (*s2 != ' ')
            *s++ = *s2;
    } while (*s2++);
}

【讨论】:

  • 谢谢,这行得通。所以基本上 s 复制自己,除了所有空间出现。 *s = 0 有什么作用?
  • C 字符串必须以空值结尾。所以该行添加了终止符。
【解决方案3】:

您更改了s 的值,但这是一个局部变量,因此在函数之外没有影响:

void removeSpace(char* s)

您可以将其更改为:

void removeSpace(char*& s)

这会引用传递的值。因此更改s 将更改原来的。不幸的是,这对您不起作用,因为您调用 removeSpace() 的方式(当您传递一个数组时)。

char a[SIZE] = "a bb ccc d";
removeSpaces(a);

您也可以更改您的代码:

char buffer[SIZE] = "a bb ccc d";
char* a = buffer;
removeSpaces(a);

现在上面建议的修改可以正常工作了。但是您正在泄漏内存(您在 removeSpace() 中动态分配从未释放的内存。解决此问题的最佳方法是使用现代 C++ 技术,而不是编写 C 并使用 C++ 编译器对其进行编译。

几个解决方案:

  1. 就地修改数组(无动态分配)
  2. 使用适当的容器(std::string 或 std::vector)
  3. 使用标准算法。

【讨论】:

  • 谢谢。很多有用的见解。
【解决方案4】:

removeSpaces 的调用没有任何影响,因为您在函数中创建了一个临时缓冲区,并在应用转换时将字符串复制到该缓冲区中。您可以通过删除临时缓冲区并仅修改字符串来解决此问题。

void removeSpaces(char* s)
{
    char* cpy = s;  // an alias to iterate through s without moving s
    char* temp = s;

    while (*cpy)
    {
        if (*cpy != ' ')
            *temp++ = *cpy;
        cpy++;
    }
    *temp = 0;

    cout << s << endl; // This prints out the desired result: abbcccd
}

【讨论】:

  • 已修复。 *src = 0; 应该是 *temp = 0;
  • 谢谢。 *temp = 0 到底是什么?做什么?
  • 它在修改后的字符串末尾放置一个空终止符,这样可以防止输出字符串缓冲区中现在未使用的部分。
  • 好的。最后一个问题,希望我能说清楚。如果您查看“Chris Jester-Young”的建议,他会移动输入参数 s。所以到函数的末尾 s 基本上已经移到数组的末尾了,对吧?这是否意味着 main() 的输入参数 a 也移动了?
  • 如果我只想删除两次出现的空格会有什么变化?
【解决方案5】:

只需在函数中添加最后一行:-

strcpy(s, temp);

并删除不必要的:-

s = temp;

【讨论】:

    【解决方案6】:

    您的函数接收指针 a 的副本。更改函数内的副本不会更改调用者的原始指针。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-16
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多