【问题标题】:Set exact size of char array using dynamic memory allocation使用动态内存分配设置 char 数组的确切大小
【发布时间】:2015-01-27 12:36:02
【问题描述】:

我必须从标准输入中读取一些字符(我不知道其中有多少,但不超过 MAX)并且我想将它们存储在一个数组中。这段代码 sn-p 正确吗?

char *c1 = (char*) malloc(MAX * sizeof(char)); //may be too much
fgets(c, MAX, stdin);
int size = strlen(c1);
char *c2 = (char*) realloc(c1, size * sizeof(char));
free(c1);

当您不知道要存储多少元素时,是否有更优雅的方法来确定为数组分配的正确内存量?

【问题讨论】:

  • 那么为什么你会有一个 int * 来自 c1 和 c2,因为你正在为 char 分配数组。另一个想法是你可以声明一个静态数组 char c1[MAX+1];而不是调用 malloc。
  • char *c2 = (char*) realloc(c1, size * sizeof(char));free(c1); : 如果c1c2 不同,则c1 已经发布。 free(c1) 将被释放,因为它已被释放。也一样不发布。

标签: c arrays memory dynamic char


【解决方案1】:

fgets() 中,您可能指的是c1,而不是c

你可以这样做(如果你坚持使用 realloc()):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX 50

int main() {
  char *c1 = malloc(MAX * sizeof(char));
  if(!c1) {
    printf("malloc() failed\n");
    return -1;
  }
  fgets(c1, MAX, stdin);
  int size = strlen(c1);
  char* c2;
  if(c1[size - 1] == '\n') {
    c1[size - 1] = '\0';
    c2 = realloc(c1, (size) * sizeof(char));
  } else {
    c2 = realloc(c1, (size + 1) * sizeof(char));
  }
  if(!c2) {
    printf("realloc() failed\n");
    return -1;
  }
  c1 = NULL;
  printf("Input was: %s\n", c2);
  free(c2);
  return 0;
}

这里有一些cmets:

  1. 你希望读取一个字符串,因此你应该使用char*,而不是 int*.

  2. 通常,您不希望保留fgets() 读取的换行符, 因此我使用了c1[size - 1] = '\0';,它覆盖了它。但是,如果用户输入了允许的最大字符数,那么就没有空间了,因此我们检查换行符是否真的存储在我们的缓冲区中。

  3. Do not cast what malloc() returns.

  4. realloc() 中,您应该为 字符串,加上 NULL 终止符。这就是为什么它现在是size+1。但是,在我们覆盖换行符的情况下,没有必要这样做,因为我们已经将字符串的大小减少了 1,因此 size 就足够了。

  5. 永远不要忘记释放内存。


但是,如果我是你,我会打印一条消息,警告用户输入 MAX 字符并避免重新分配。

你看,正如ref of fgets() 所说,该函数将:

从流中读取字符并将它们作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件结尾,以先发生者为准。

所以,即使用户输入更多,程序也不会崩溃。


正如 Paul 正确评论的那样,使用第二个指针是一个非常好的主意,这样如果 realloc() 失败,我们就不会丢失数据。

还请注意,您不应释放c1,因为此指针已失效,应设置为NULLc1 可能会指向c2 指向的位置,因此如果我们释放c1,那么c2 将指向垃圾。或者可能是整个内存块被转移到其他地方,因此c1 指向垃圾,我们正在尝试释放。

【讨论】:

  • (1) 此处无需分配size + 1,因为您已经使用c1[size - 1] = '\0'; 减少了字符串的长度。 (2) 如果行大于缓冲区,fgets() 不会在其中放置换行符,因此您应该在尝试删除它之前检查它。 (3) “不需要第二个指针” - 有,因为realloc() 可能会失败,如果你没有第二个指针,你会丢失原来的指针。 (4) 这里真的应该有一些错误检查才能使它成为一个好的答案。
  • 我只考虑了第二点@PaulGriffiths,但你在所有四个方面都是对的。我更新了。你现在喜欢吗?不过感谢您的提醒!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-27
  • 1970-01-01
  • 2011-03-15
  • 1970-01-01
  • 1970-01-01
  • 2022-01-02
相关资源
最近更新 更多