如何在c中动态分配结构数组?

时间:2012-12-12 22:09:25

标签: c file memory-management struct linked-list

我想实现一个简单的单词计数程序,它将打开一个 文本文件,作为命令行参数提供,然后计算单词数, 该文本中的非字母单词(例如:1998,2-3等)句子和段落的数量 文件。假设两个空格之间的字符数组计为单词,非字母单词由数字,连字符等组成。每个句子都以'。'(点)字符结束,而段落则为 用换行符分隔。我将使用一个保持字数,非字母的结构 每个段落的字数,句子数和起始行如下:

    struct {
      int word;
      int sentence;
      int nonAlpha;
      int startingLine;
      struct Paragraph*next;       
    }Paragraph; 

我决定使用链接列表。那么我应该知道并学习将使用多少段并初始化链表,链接它们,或者只是在从文件读取新段落并且需要存储在结构中时继续分配?

    Paragraph->next=(struct Paragraph*) calloc(1,sizeof(struct Paragraph));

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

  

如何在不给出SIZE的情况下动态分配它?

在不知道大小的情况下,无法分配连续的数组。

我会给你一些选择:

  1. 使用malloc在大型块中预分配并复制到其中。如果您在阅读文件realloc较大的块时耗尽了大小。

  2. 首先计算文件中的单词数量malloc,然后再次读取该文件。

  3. 使用链接列表结构。每个单词malloc,并指向下一个单词。

答案 1 :(得分:1)

struct Paragraph *dynamicParagraph = malloc(SIZE * sizeof(Paragraph));

因为在C / C ++中,数组和指针基本相同,所以可以将它用作数组:

Paragraph specificParagraph = dynamicParagraph[index]; //Assuming index < SIZE and > 0

答案 2 :(得分:0)

根据您的说明,您希望每个段落有一个struct个实例。因此,每次遇到换行符时,都要开始新的段落计数。

首先动态分配初始数量的Paragraph个对象(足以覆盖大多数情况),然后根据需要扩展该块:

#define INITIAL_SIZE ... // some initial value, say 5 or 10
...
size_t numParas = 0;     // keep track of the array size
size_t parasRead = 0;    // keep track of the paragraphs read
...
struct Paragraph *paras = malloc(sizeof *paras * INITIAL_SIZE);
if (paras)
{
  numParas = INITIAL_SIZE;
}
else
{
   perror("Could not allocate initial memory...exiting");
   exit(-1);
}

... // open the file and read input

while (more_data)
{
  int c = fgetc(input);

  // update the various fields of paras[parasRead]
  // based on the value of current_character

  if (c == '\n')
  {
    // ready to start a new paragraph.  If we've reached the end
    // of the paras array and don't have a new slot available,
    // extend the array by doubling its size
    if (parasRead + 1 == numParas)
    {
      struct Paragraph *tmp = realloc(paras, sizeof *paras * (numParas * 2));
      if (tmp)
      {
        paras = tmp;
        numParas *= 2;
      }
      else
      {
        perror("Could not extend the paras array...exiting");
        free(paras);
        exit(-1);
      }
    }
    parasRead++;
    moreData = (c != EOF);
  }
}

// display results
...
free(paras);

至少应该让你开始。如果realloc无法扩展缓冲区,则必须决定该怎么做。在上面的示例代码中,我将其视为致命错误并立即退出,但您可以尝试将缓冲区扩展较小的量(而不是加倍,将其增加1.5倍,如果失败则增加1.25倍等) 。您可以决定退出循环并显示您的结果。或者完全不同的东西。

也可能有更好的方法来组织这个;最好将阵列管理代码分离到一个单独的函数中。但这应该会让你了解所需要的东西。

答案 3 :(得分:0)

使用链接列表而不是数组。在这种情况下,您只需要在需要时分配新成员。