我在Codewars上尝试一个初学者的C问题:我应该写一个函数,从给定的字符串中删除空格,然后返回一个新的(动态分配的)字符串。
范例:str_in
中的输入字符串HELLO WORLD
需要输出HELLOWORLD
,但我的代码在noSpace_str
中返回的是HELLO
。WORLD
无处可寻,我试图理解为什么。
(提前感谢您的回答)
我的代码:
char *no_space(const char *str_in)
{
int len = strlen(str_in);
char *noSpace_str = (char *)malloc(len * sizeof(char));
for (int i = 0; i < len; i++) {
if (str_in[i] != ' ')
noSpace_str[i] = str_in[i];
}
return noSpace_str;
}
字符串
6条答案
按热度按时间nfg76nw01#
当你的代码遇到一个空格时,它不会复制任何东西。这会在缓冲区中留下一个空白,其中包含之前存在的任何东西,在这种情况下,是一个空字节(0x00)。10个字节用于终止字符串,因此字符串在单词“HELLO”之后结束。在不立即给出答案的情况下,你需要开始复制 * 在 * 空格之后,而不是忽略它。
r1wp621o2#
除了其他好的答案,如果你只想分配所需的大小,而不是额外的,做2遍,计算你需要的第一遍。
第一个循环替换了
strlen()
,strlen()
本身就是一个遍历字符串的过程。只要代码遍历字符串,就可以计算非空格。字符串
xsuvu9jc3#
代码中存在一些主要问题:
len + 1
字节。' '
),而不初始化分配的字符串中的其他条目。分配块中的第六个字节可能是空字节,这可以解释为什么你得到HELLO
作为输出,但其他任何事情都可能发生。len
和i
应该具有size_t
类型,以与strlen
的返回类型保持一致。要实现此目标,您应该为源数组和目标数组使用不同的索引,并确保追加了空终止符。
以下是修改后的版本:
字符串
tvokkenx4#
其他(当前)答案指出,代码需要两个不同的索引计数器;一个用于源数组,一个用于目标数组。
其他的答案表明,分配的缓冲区需要容纳一个终止NUL(不按源字符串的
strlen()
计数)。其他的答案已经证明了从
malloc()
返回的指针可以是NULL。不要使用NULL指针。总是测试来自系统函数的返回代码(如malloc()
或fopen()
),如果需要的话减少处理。这里有一个紧凑的替代方案。“* 更少的(工作!)代码是更好的代码 *”
字符串
更强大的版本将采用第二个
char
参数,允许此函数过滤掉调用者想要的任何字符(不仅仅是SP)的所有出现。一个功能更强大的版本将采用第二个
char*
参数,允许此函数过滤掉调用者希望排除的任何字符(以char *excl
作为参数传递给函数)。简单的测试
cp += *cp != ch;
个可能成为
cp += !strchr( excl, *cp );
个最后一种可能性留给OP去探索和理解。
lpwwtiir5#
每个数组需要一个变量来遍历它们。只有当有字符副本时,目标数组的变量才必须递增。
字符串
8qgya5xd6#
字符串
strlen()
返回字符串的长度,但是这个长度不包括最后一个'\0'
的空间,strlen()
需要正确地找到字符串的结尾并计算字符数,直到到。你需要在结尾处为null多分配一个字节,所以使用len = strlen(str_in) + 1;
。这确实是一个错误,如果输入字符串根本没有空格,在这种情况下,它将溢出分配的缓冲区,使您将'\0'
放置在分配的缓冲区末尾之外的一个空间,这是错误的。如果你打算复制到一个新分配的字符串,那么你必须只复制字符,但跳过空格。这意味着你将不得不使用两个索引,而不是一个,因为它们之间的差异将说明跳过的字符数,所以你可以做得更好:
型
(注意,如果源索引处的源字符串显示空格,则不会复制空格,并且
dst_index
也不会递增)或者,如果你更喜欢使用指针:
型