2012-04-27 94 views
2

我有一个程序,我想从一个字符串中删除空格。我想找到一个优雅的方式来做到这一点,所以我发现下面的(我已经改变了它一点,所以它可能是更好的可读)代码in a forumC如何知道我的字符串的结尾?

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的字符串是“Null-terminated string”。我一直认为这样,一切都很好。但问题是:我们把没有“空字符”在non_spaced字符串的结尾。并以某种方式编译器知道它的最后一个字符用“non_spaced”串改结束。它如何知道?

+0

你是什么意思“编译器知道它”?你在运行时改变它,编译过程是long已过 – Fred 2012-04-27 11:34:46

+0

@Fred - 好点! – 2012-04-27 11:36:14

+2

对于它的价值,'strlen(line)'会重新计算字符串的长度时间。这是一个非平凡的计算,不应该在每个循环迭代中完成。你会更好地计算一次并存储它:'size_t len = strlen(line); for(i = 0; i <= len; i ++)'。 (另外,你所有作为int的变量在技术上应该是'size_t'类型。) – 2012-04-27 11:38:38

回答

9

这不会发生魔法。你在你的代码:

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

循环索引i运行,直到strlen(line)这个指数有字符数组的NULL字符,这被复制为好。结果你的最终结果在所需的索引处有nul字符。

如果你有

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

,那么你不得不手动将空字符为:

for (i = 0; i < strlen(line); i++) 
{ 
    if (line[i] != ' ') 
    { 
     non_spaced[j] = line[i]; 
     j++; 
    } 
} 
// put nul character 
line[j] = 0; 
+0

空字符将是'\ 0'而不是'' – KBN 2012-04-27 11:42:43

+0

@xFortyFourx:http: //stackoverflow.com/questions/4705968/what-is-value-of-eof-and-0-in-c – codaddict 2012-04-27 11:45:07

+0

哇!我永远不会明白。谢谢! (严重的是,我没有注意到“<=”那里) – vaulttech 2012-04-27 11:46:33

0

你可以试试。在处理仅包含一个空格的字符串时对其进行调试:''。仔细观察指数i发生了什么。

0

你怎么知道它“知道”?最有可能的情况是,你只是在运行时遇到了未定义的行为,并且在line的有效字节结束后有一个'\0'-字符。

这很可能是因为你没有在最后看到空格,可能会在打到流浪的“幸运'\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; 
} 

注意,这确实终止字符串的空间较少的版本,所以返回的指针一定是在点有效的字符串。

+1

不,代码不是未定义的。它会工作 - 检查比较运算符。 – 2012-04-27 11:39:02

+0

如果'line'是一个以空字符结尾的字符串,那么'non_spaced'确保为空终止,因此它不是'lucky'\ 0'“ – Anthales 2012-04-27 11:39:39

2

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

0

你的函数的字符串参数为空值终止的,对不对? 而在循环中,原始字符串的空字符也会被复制到非间隔返回的字符串中。所以非间隔字符串实际上也是空终止的!

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

3

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

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

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

    line++; 
    } 

    *non_spaced = '\0'; 
} 
0

如果使用“< = strlen的(线),strlen的长度(行)包括'\ 0' 所以你的程序可以工作。你可以使用调试和运行分析。

相关问题