【问题标题】:realloc homework helprealloc 作业帮助
【发布时间】:2011-08-01 22:25:15
【问题描述】:

对于一个作业,我必须做的一部分是使用malloc 和realloc。我首先创建一个二维字符数组,维度是行数和字符数。然后我使用malloc 分配足够的内存来存储来自某个文件的输入。使用fgets 我一次读入一行,并将其存储在数组中。这部分工作正常(或者我认为)。当我尝试为更多行重新分配内存时,问题就出现了。程序流程应该是这样的:

创建一个 50 行的字符数组,每行 80 个字符(工作)

使用fgets 一次读取一行并将其保存到数组中(工作)

读取 50 行后,重新分配数组以允许 100 行(不工作)

根据需要继续重新分配(不工作)

这是我目前所拥有的(至少是它的核心,我省略了不相关的代码):

#define NUMBER_OF_LINES 50
#define CHARACTERS_PER_LINE 80

FILE *inputFile = fopen("some.text", "r");

char **lines;
lines = malloc(NUMBER_OF_LINES * sizeof(*lines));
int i;
for (i = 0; i < NUMBER_OF_LINES; i++)
  *(lines+i) = malloc(CHARACTERS_PER_LINE * sizeof(char));

int linesRemaining = NUMBER_OF_LINES;
int reallocCount = 1;
i = 0;
while (!feof(inputFile)) {
  if (!linesRemaining) {
    reallocCount++;
    lines = realloc(lines, (NUM_OF_LINES * reallocCount) * sizeof(*lines));
    linesRemaining = NUM_OF_LINES;
  }
  fgets(*(lines+i), CHARS_PER_LINE, inputFile);
  i++;
  linesRemaining--;
}

我的直觉告诉我问题出在realloc,所以我将解释我认为它在做什么。

realloc(lines, (NUM_OF_LINES * reallocCount) * sizeof(*lines));

第一个参数lines 是我想重新分配一定数量内存的指针。 NUM_OF_LINES 是我想增加大小的数量。我将它乘以reallocLinesCount,这是一个计数器,用于跟踪我应该拥有多少组 50 行。 sizeof(*lines) 部分是指向char 的指针的大小。

感谢您的阅读,非常感谢您的帮助:)

编辑:谢谢大家的回复;我现在没有时间阅读所有答案,但是一旦这个迫在眉睫的截止日期过去,您的所有答案都会得到更彻底的阅读和理解:D

【问题讨论】:

  • 前/后增量/减量绊倒了许多新手 C 程序员;编写没有它们的代码,然后在获得经验时介绍它们。
  • 我永远无法理解这种奇怪的恋物癖老师必须教学生静态分配特定长度的数组。就像他们正在尝试培养下一代容易被黑客入侵的软件编写者..
  • 编辑为没有前/后增量/减量。

标签: c realloc


【解决方案1】:

我的座右铭是:“说出你的意思”。在您的情况下,您的意思是在数组不足以容纳您的数据时扩大数组。

FILE *in;      // you fill this in
int nlines=50; // initial value
char **buffer=malloc(nlines * sizeof *buffer);
int i=0;

for(int i=0; !feof(in); ++i)
{
  if(i>=nlines)
    buffer=realloc(buffer, (nlines+=50)*sizeof *buffer);

  buffer[i]=malloc(80);
  fgets(buffer[i], 80, in);
}

【讨论】:

  • 这工作谢谢!我做过很多 Java 编程,其中赋值评估为真或假,我喜欢如何将 (nlines+=50) 视为 int。巧妙地使用 !feof(in) 作为 for 循环中的条件。
  • 嗯,这种编码是许多有经验的程序员不能接受的(我经验不足;))。我个人喜欢!feof(in),但不喜欢(nlines+=50)*sizeof *buffer。
  • @Donotalo,一般来说,试着只为自己说话。
【解决方案2】:

realloc() 经常会发现没有足够的可用空间来就地扩展现有阵列;在这种情况下,它将创建一个指定大小的全新数组,将旧数组的内容复制到新数组,释放旧数组,并返回指向新数组的指针。所以你应该写

char **oldLines = lines;
lines = realloc(...);

(oldLines 的目的是保留原始指针,以防realloc() 内存不足并返回NULL,根据@Brian L 的提示)。

【讨论】:

  • 到底发生了什么(你怎么看它不起作用)?它会崩溃(在哪里,用什么消息),还是会产生乱码(什么结果)?
  • 您永远不应该将 realloc() 的结果直接分配给您正在重新分配的变量。如果对 realloc() 的调用失败,您将不再拥有指向先前分配的内存的指针。如果您只是要在 realloc 失败时中止程序,也许没关系。但是使用下面的 Donotalo 方法似乎是一个好习惯。
【解决方案3】:

这就是你应该重新分配的方式:

char **new_lines = realloc(lines, (NUM_OF_LINES * ++reallocLinesCount) * sizeof(*lines));
if (new_lines)
{
    lines = new_lines;
}
else
{
    // Memory allocation fails. Do some error handling.
}

阅读realloc reference了解详情。

编辑

您需要为每个新行分配更多。

【讨论】:

    【解决方案4】:

    您正在分配更多指向行的指针,而不是行本身。它在您的代码开头:

    for (i = 0; i < NUMBER_OF_LINES; i++)
       *(lines+i) = malloc(CHARACTERS_PER_LINE * sizeof(char));
    

    因此,在为每行分配行数后,您可以为行本身分配空间。重新分配时忘记为新行执行此操作。

    【讨论】:

      【解决方案5】:

      让我们先see how realloc() works。它返回一个指向 new 的指针 记忆成功,NULL 失败。在失败时,它不会 触摸旧记忆,成功后,它free()的它,复制后 你的数据到新的地方。

      所以,安全使用realloc()的方法是:

      /* allocate memory using malloc() */
      ptr = malloc(N * sizeof *ptr);
      /* make sure malloc succeeded */
      ...
      /* call realloc() */
      new_ptr = realloc(ptr, M * sizeof *new_ptr);
      /* see if it succeeded */
      if (new_ptr) {
          /* okay, we can set ptr */
          ptr = new_ptr;
      } else {
          /* realloc failed, old pointer still valid */
      }
      

      所以,第一件事是您错误地使用了realloc()。 你应该永远说x = realloc(x, ...);,因为如果realloc() 失败,你将x分配给NULL,旧的内存就丢失了。这是 内存泄漏。

      现在,谈谈你的问题。假设您已成功阅读 NUMBER_OF_LINES 行。现在你想为额外的空间腾出空间 NUMBER_OF_LINES 行。你会这样做:

      char **new_lines = realloc(lines, NUMBER_OF_LINES*reallocCount*sizeof *new_lines);
      if (new_lines) {
          lines = new_lines;
      } else {
          fprintf(stderr, "realloc failed!\n");
          return;
      }
      
      /* Now, lines[NUMBER_OF_LINES] to lines[2*NUMBER_OF_LINES-1] are
       * available to point someplace useful.  They don't point anywhere
       * useful yet.  We have to allocate memory for them, just like earlier */
      
      start = NUMBER_OF_LINES*reallocCount;
      for (i=0; i < NUMBER_OF_LINES; ++i) {
          /* You weren't allocating memory here, and were writing to
           * lines[0] through lines[NUMBER_OF_LINES-1], which is not what
           * you want. */
          lines[start+i] = malloc(CHARS_PER_LINE * sizeof *lines[start+i]);
          /* check the result of malloc here */
      }
      fgets(lines[start+i], CHARS_PER_LINE, inputFile);
      

      最后一点:almost always wrong 使用 while (!feof(fp)) 从文件中读取行。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-18
        • 1970-01-01
        • 1970-01-01
        • 2011-02-17
        • 1970-01-01
        相关资源
        最近更新 更多