2

为了编写一些基本函数来操作 C 字符串 (char*),我一直在玩弄 malloc、realloc 和 free。从字符串中删除最后一个字符时,我遇到了这个奇怪的问题。我用这样的原型写了一个函数:

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 来完成这项工作。如果有人帮助我找到并纠正我的问题,我将不胜感激这里有错误。提前致谢。

4

3 回答 3

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';
} 
于 2010-01-06T13:43:12.093 回答
2

第一个 strncpy() 没有在 tmp 的末尾放置一个 '\0'。

此外,您可以避免双重复制: *dst = tmp;

于 2010-01-06T13:44:52.823 回答
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 字符截断的分配大小;这太低效了。您将改为单独跟踪字符串的长度及其分配的大小。这使得字符串很容易增长;只要已经分配了空间,追加一个字符就非常快。

此外,在 C 中,您永远不需要转换 ; 的返回值malloc()。它没有任何用途,并且可以隐藏错误,所以不要这样做。

于 2010-01-06T13:44:22.390 回答