首页 > 解决方案 > 如何将文件中的数据加载到链表c中

问题描述

程序应该读取一个简单的文本文件并将数据(名称和 ID)存储到一个链表中。

这是链表:

struct Prova
{
 char nome[16];
 int id;
};

typedef struct Node {
 struct Prova  struttura;
 struct Node * next;

}TNodo;
typedef TNodo* Nodo;

此函数创建链表:

void NewList(struct Prova  p, Nodo * pp)
{
 Nodo  temp;

 temp = (Nodo)malloc(sizeof(struct Node));

 temp->struttura = p;
 temp->next = *pp;

 *pp = temp;
}

这是我为读取文件而编写的函数:

void Load(Nodo *pp)
{
  FILE *f;
  struct Prova p;
  char * buffer;
  if(!(f = fopen(PATH, "r")))
  {
    perror("Error");
    exit(-1);
  }

  buffer = malloc(sizeof(struct Prova));

  while(fgets(buffer, sizeof(buffer), f))
    {
      if(sscanf(buffer, "%s%d", p.nome, &p.id) > 0)
      {
        NewList(p, pp);
      }
    }

free(buffer);
fclose(f);

}

我试图阅读的文本文件是这样的:

Stefano 31
Paperino 23
Pippo 1
Pluto 14

显示列表的功能如下:

void View(struct Prova  p)
{
 printf("%s %d\n", p.nome, p.id);

}

void ViewList(Nodo  nodo)
{
while(nodo != NULL)
{
  View(nodo->struttura);
  nodo = nodo->next;
}

该程序编译得很好,但它以奇怪的顺序输出数据。如果您需要更多信息,请告诉我,我认为这都与最新的函数 Load() 有关。

主要功能是这样的:

int main()
{
int scelta;
 struct Prova test;
Nodo lista = NULL;
 do {
   scelta = Menu();

   switch (scelta)
   {
     case 1:   Load(&lista); break     
     case 2: ViewList(lista); break;
     default: scelta = 0;
   }

 } while (scelta != 0);

 return 0;
}

现在输出是这样的:

在此处输入图像描述

标签: cpointerslinked-list

解决方案


由于传递sizeof(buffer)fgets(). buffer是一个指针,sizeof(buffer)将返回48基于底层架构32位或64位。将其更改为:

while(fgets(buffer, sizeof(struct Prova), f))

当您将sizeof(struct Prova)大小分配给buffer.

这也不是问题的正确解决方案。原因是——

说,您的文件包含以下数据:

abcdefghijklmno 123456789

名称部分是成员可以持有的15字符长,nome成员也可以持有小于id的数字。从流中读取字符,上面给出的数据的大小是字符。在您的代码中,您将大小内存分配给字节大小。因此,对于上面给出的数据,没有分配足够的内存来一次读取整行,因为读取直到字符被读取或到达换行符或文件结尾,以先发生者为准。因此,在这种情况下,部分行将被读取并传递给,其余行将在下一次迭代中读取并传递给123456789INT_MAXfgets25sizeof(struct Prova)bufferstruct Prova20bufferfgetssize-1sscanf()sscanf()这将给出不正确的结果。

您不应该buffer根据struct Prova. 相反,我建议采取buffer一些更大的尺寸,像这样(不需要动态分配它):

char buffer[100];

确保它应该足够大以在一次读取中容纳文件的一行fgets或修改您的代码以不填充p.nome并且p.id直到fgets命中换行符或 EOF 即确保读取整行然后只sscanf()读取p.nomeand p.id


推荐阅读