我有一个程序,我想从字符串中删除空格。我想找到一种优雅的方法,所以我找到了以下内容(我已经改变了一点,因此它可以更好阅读)代码in a forum:
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
字符串的末尾没有放置“null-character”。并且不知何故,编译器知道它以“non_spaced”字符串改变的最后一个字符结束。怎么知道?
答案 0 :(得分:9)
魔法不会发生这种情况。你的代码中有:
for (i = 0; i <= strlen(line); i++)
^^
循环索引i
一直运行到strlen(line)
,并且在此索引处,字符数组中有一个空字符,这也会被复制。因此,您的最终结果在所需索引处具有零字符。
如果你有
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;
答案 1 :(得分:5)
其他人已经回答了你的问题,但这是相同代码的更快,更清晰的版本:
void line_remove_spaces (char* line)
{
char* non_spaced = line;
while(*line != '\0')
{
if(*line != ' ')
{
*non_spaced = *line;
non_spaced++;
}
line++;
}
*non_spaced = '\0';
}
答案 2 :(得分:2)
循环使用<= strlen
,因此您也将复制空终止符(位于i == strlen(line)
)。
答案 3 :(得分:0)
你可以尝试一下。在处理只包含一个空格的字符串时调试它:''。仔细观察索引i会发生什么。
答案 4 :(得分:0)
你怎么知道它“知道”?最可能的情况是,您只是运气未定义的行为,并且在'\0'
的有效字节结束后有一个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;
}
请注意,此 终止字符串的无空间版本,因此返回的指针保证指向有效的字符串。
答案 5 :(得分:0)
你的函数的字符串参数是以null结尾的,对吗? 在循环中,原始字符串的空字符也会复制到非间隔返回的字符串中。所以非间隔字符串实际上也是以空值终止的!
对于你的编译器,空字符只是另一个没有得到任何特殊处理的二进制数据,但字符串API使用它作为一个方便的字符来轻松检测字符串的结尾。
答案 6 :(得分:0)
如果你使用&#34;&lt; = strlen(line),strlen(line)的长度包括&#39; \ 0&#39; 所以你的程序可以工作。你可以使用调试和运行分析。