1

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

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

我决定为此使用链表。那么我应该迭代并了解将使用多少段落并初始化链接列表,链接它们,或者如果从文件中读取新段落并且需要存储在结构中,则继续分配?

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

谢谢您的帮助。

4

4 回答 4

2

如何在不提供 SIZE 的情况下动态分配它?

你不能在不知道大小的情况下分配一个连续的数组。

我会给你几个选择:

  1. malloc使用并复制到大块中预分配。如果您在读取文件时用完大小,请realloc使用更大的块。

  2. 先数文件的字数,malloc就这么多,然后再读文件。

  3. 使用链表结构。malloc每个单词都有一个指向下一个单词的指针。

于 2012-12-12T22:13:53.573 回答
1
struct Paragraph *dynamicParagraph = malloc(SIZE * sizeof(Paragraph));

而且由于在 C/C++ 中数组和指针基本上是一回事,所以您可以将其用作数组:

Paragraph specificParagraph = dynamicParagraph[index]; //Assuming index < SIZE and > 0
于 2012-12-12T22:10:54.310 回答
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 倍,等等) . 您可以决定退出循环并展示您的结果。或者完全不同的东西。

可能还有更好的组织方式;最好将数组管理代码分离到一个单独的函数中。但这应该让您了解所需的内容。

于 2012-12-12T22:57:24.540 回答
0

使用链表代替数组。在这种情况下,您只需要在需要时分配新成员。

于 2012-12-13T13:32:38.190 回答