7

我有一个程序,我想从字符串中删除空格。我想找到一种优雅的方式来做到这一点,所以我在一个论坛中找到了以下代码(我对其进行了一些更改,以便更好地阅读):

char* line_remove_spaces (char* line)
{
    char *non_spaced = line;
    int i;
    int j = 0;
    for (i = 0; i <= strlen(line); i++)
    {
        if ( line[i] != ' ' )
        {
            non_spaced[j] = line[i];
            j++;
        }
    }
    return non_spaced;
}

如您所见,该函数接受一个字符串,并使用相同的分配内存空间,仅选择非空格字符。有用!

无论如何,根据维基百科,C 中的字符串是“空终止字符串”。我一直这么想,一切都很好。但问题是:我们没有在字符串末尾放置“空字符” non_spaced。不知何故,编译器知道它以“non_spaced”字符串更改的最后一个字符结束。它是怎么知道的?

4

7 回答 7

12

这不是魔术发生的。您的代码中有:

for (i = 0; i <= strlen(line); i++)
              ^^

循环索引i一直运行到strlen(line)该索引处,字符数组中有一个 nul 字符,并且它也会被复制。结果,您的最终结果在所需索引处具有 nul 字符。

如果你有

for (i = 0; i < strlen(line); i++)
              ^^

那么您必须手动将 nul 字符设置为:

for (i = 0; i < strlen(line); i++)
{
    if ( line[i] != ' ' )
    {
        non_spaced[j] = line[i];
        j++;
    }
}
// put nul character
line[j] = 0;
于 2012-04-27T11:39:34.290 回答
7

其他人已经回答了你的问题,但这里是相同代码的更快,也许更清晰的版本:

void line_remove_spaces (char* line)
{
  char* non_spaced = line;

  while(*line != '\0')
  {
    if(*line != ' ')
    {
      *non_spaced = *line;
      non_spaced++;
    }

    line++;
  }

  *non_spaced = '\0';
}
于 2012-04-27T12:02:11.787 回答
2

循环使用<= strlen,因此您也将复制空终止符(位于i == strlen(line))。

于 2012-04-27T11:38:36.440 回答
1

你可以试试。在处理只包含一个空格的字符串时对其进行调试:" ". 仔细观察索引会发生什么i

于 2012-04-27T11:35:47.207 回答
0

你怎么知道它“知道”?最可能的情况是您只是对未定义的行为感到幸运,并且在 end'\0'的有效字节之后有一个 -character line

您也很有可能在最后没有看到空格,这些空格可能会在碰到流浪“幸运'\0'”之前打印出来。

其他几点:

  • 无需使用索引编写此内容。
  • strlen()调用每个循环迭代并不是很有效。
  • 您可能想使用isspace()删除更多的空白字符。

这是我将如何编写它,使用isspace()和指针:

char * remove_spaces(char *str)
{
  char *ret = str, *put = str;

  for(; *str != '\0'; str++)
  {
    if(!isspace((unsigned char) *str)
      *put++ = *str;
  }
  *put = '\0';

  return ret;
}

请注意,这确实终止了字符串的无空格版本,因此返回的指针保证指向一个有效的字符串。

于 2012-04-27T11:37:00.643 回答
0

你的函数的字符串参数是空终止的,对吧?并且在循环中,原始字符串的空字符也被复制到不带空格的返回字符串中。所以非空格字符串实际上也是空终止的!

对于您的编译器,空字符只是另一个没有得到任何特殊处理的二进制数据,但它被字符串 API 用作方便的字符来轻松检测字符串的结尾。

于 2012-04-27T11:42:46.803 回答
0

如果您使用,则包含<= strlen(line)的长度使您的程序可以工作。您可以使用调试和运行分析。strlen(line)'\0'

于 2012-04-27T13:38:10.200 回答