我正在编写一种算法来从动态大小的数组中删除所有引号,并在删除后减少它的长度。到目前为止,这是我的代码:
void remove_quotations(char *str)
{
int len = strlen(str);
for (int i = 0; i < len; i++) {
if (str[i] == '\'') {
for (int j = i; j < len - 1; j++) {
str[j] = str[j + 1];
}
len--;
str = realloc(str, len);
}
}
}
示例输入:'1357'、'name'、'topic'、'2'
预期输出:1357,名称,主题,2
我得到的是:“1357,名称,主题,2''''''''”
如您所见,引号按预期移到了末尾,但字符串并没有像它应该的那样被缩短。
注意:我不是故意做任何错误检查。
最佳答案
So as you can see the quotation marks get moved to the end as expected, but the string doesn't get shortened like it should.
好吧,得到 缩短的是分配给您的字符串的区域,这就是realloc()
所做的。您忘记缩短实际的字符串:字符串 的末尾总是有一个 \0
字节。
因此,您的程序会导致未定义的行为,例如使用 printf()
或 puts()
输出此字符串——这些函数将读取直到找到 \0
终止符,并且它不在其中您在 realloc()
之后可以合法访问的区域。
这似乎有效的事实纯属偶然:realloc()
没有给你一个新地址,旧内容仍然存在。
您的代码中还有另一个错误:如果 realloc()
给您一个不同的地址,它将不起作用,因为调用代码无法取回指针。
旁注:
在使用
realloc()
时,将结果分配给一个临时变量。如果返回 NULL,则必须free()
原始变量。您只需要在循环后一次调用
realloc()
。
供引用,固定和注释版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *remove_quotations(char *str)
{
// always use the correct type, strlen returns size_t:
// (int would only be a problem here for **huge** strings, still it's better
// getting used to ALWAYS use size_t for sizes.)
size_t len = strlen(str);
for (size_t i = 0; i < len; ++i)
{
if (str[i] == '\'')
{
// move following bytes *including* the final 0 terminator:
memmove(str+i, str+i+1, len-i);
--len;
}
}
// include space for 0 terminator when shortening:
char *tmp = realloc(str, len+1);
if (!tmp)
{
free(str);
return 0;
}
return tmp;
}
int main(void)
{
char test[] = "'1357', 'name', 'topic', '2'";
char *foo = malloc(strlen(test)+1);
strcpy(foo, test);
foo = remove_quotations(foo);
if (foo)
{
puts(foo);
free(foo);
}
return 0;
}
这个版本仍然使用您原来的结构,即在遇到的每个 '
上移动字符串的其余部分。这并不过分有效,请参阅 mch's answer以获得更好的方法。
为了完整起见,您可以只返回原始字符串的副本,如下所示:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *remove_quotations(const char *str)
{
size_t len = strlen(str);
char *dst = malloc(len+1);
const char *r = str;
char *w = dst;
while (*r)
{
if (*r == '\'') --len;
else *w++ = *r;
++r;
}
*w = 0;
char *tmp = realloc(dst, len+1);
if (!tmp)
{
free(dst);
return 0;
}
return tmp;
}
int main(void)
{
const char *test = "'1357', 'name', 'topic', '2'";
char *foo = remove_quotations(test);
if (foo)
{
puts(foo);
free(foo);
}
return 0;
}
关于c - 从字符串中删除字符并在删除时动态调整其大小的算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44823539/