我一直在使用malloc,realloc和free来编写一些基本函数来操作C字符串(char *)。当从字符串中删除最后一个字符时,我遇到了这个奇怪的问题。我用这样的原型编写了一个函数:
int string_erase_end (char ** dst, size_t size);
它应该将“dst”字符串缩短一个字符。到目前为止,我已经提出了这个代码:
int string_erase_end (char ** dst, size_t size)
{
size_t s = strlen(*dst) - size;
char * tmp = NULL;
if (s < 0) return (-1);
if (size == 0) return 0;
tmp = (char*)malloc(s);
if (tmp == NULL) return (-1);
strncpy(tmp,*dst,s);
free(*dst);
*dst = (char*)malloc(s+1);
if (*dst == NULL) return (-1);
strncpy(*dst,tmp,s);
*dst[s] = '\0';
free(tmp);
return 0;
}
在main()中,当我截断字符串时(是的,我先前在它们上面调用了malloc),我得到了奇怪的结果。根据我要截断的字符数,它可以正常工作,截断错误的字符数或引发分段错误。
我没有动态内存分配的经验,并且一直使用C ++及其std :: string来完成所有这些肮脏的工作,但这次我需要在C中完成这项工作。如果有人帮助我找到我会很感激并纠正我的错误。提前谢谢。
答案 0 :(得分:2)
根据你的描述,你的函数应该删除字符串中的最后n个字符:
/* Assumes passed string is zero terminated... */
void string_erase_last_char(char * src, int num_chars_to_erase)
{
size_t len = strlen(src);
if (num_chars_to_erase > len)
{
num_chars_to_erase = len;
}
src[len - num_chars_to_erase] = '\0';
}
答案 1 :(得分:2)
第一个strncpy()没有在tmp的末尾添加'\ 0'。
此外,您可以避免双重复制:* dst = tmp;
答案 2 :(得分:1)
我不明白size
参数的目的。
如果您的字符串最初是使用malloc()
分配的,则应使用realloc()
更改其大小。这将自动保留内容,并且需要更少的操作:
int string_erase_end (char ** dst)
{
size_t len;
char *ns;
if (dst == NULL || *dst == NULL)
return -1;
len = strlen(*dst);
if (len == 0)
return -1;
ns = realloc(*dst, len - 1);
if (ns == NULL)
return -1;
ns[len - 1] = '\0';
*dst = ns;
return 0;
}
在“真实世界”中,通常不会更改1-char截断的分配大小;这太低效了。您可以分别跟踪字符串的长度和分配的大小。这使字符串变得容易;只要已经分配了空间,就可以非常快速地追加一个角色。
此外,在C中你永远不需要转换malloc()
的返回值;它没有任何意义,可以隐藏错误,所以不要这样做。