动态内存分配 +截断字符串问题

发布于 2024-08-17 10:57:27 字数 878 浏览 7 评论 0原文

为了编写一些基本函数来操作 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 中完成这项工作。如果有人帮助我找到并纠正我的问题,我将不胜感激。这里有错误。提前致谢。

I've been fooling around with malloc, realloc and free in order to write some basic functions to operate on C strings (char*). I've encountered this weird issue when erasing the last character from a string. I wrote a function with such a prototype:

int string_erase_end (char ** dst, size_t size);

It's supposed to shorten the "dst" string by one character. So far I have come up with this code:

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;
}

In main(), when I truncate strings (yes, I called malloc on them previously), I get strange results. Depending on the number of characters I want to truncate, it either works OK, truncates a wrong number of characters or throws a segmentation fault.

I have no experience with dynamic memory allocation and have always used C++ and its std::string to do all such dirty work, but this time I need to make this work in C. I'd appreciate if someone helped me locate and correct my mistake(s) here. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

你与清晨阳光 2024-08-24 10:57:27

第一个 strncpy() 不会在 tmp 末尾放置 '\0'。

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

The first strncpy() doesn't put a '\0' at the end of tmp.

Also, you could avoid a double copy: *dst = tmp;

妄司 2024-08-24 10:57:27

根据您的描述,您的函数应该删除字符串中的最后 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';
} 

According to your description your function is supposed to erase the last n characters in a string:

/* 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';
} 
唠甜嗑 2024-08-24 10:57:27

我不明白 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() 的返回值;它没有任何作用并且可以隐藏错误,所以不要这样做。

I don't understand the purpose of the size parameter.

If your strings are initially allocated using malloc(), you should just use realloc() to change their size. That will retain the content automatically, and require fewer operations:

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;
}

In the "real world", you would generally not change the allocated size for a 1-char truncation; it's too inefficient. You would instead keep track of the string's length and its allocated size separately. That makes it easy for strings to grow; as long as there is allocated space already, it's very fast to append a character.

Also, in C you never need to cast the return value of malloc(); it serves no purpose and can hide bugs so don't do it.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文