如何将文件中的数据加载到链表c中

时间:2018-05-02 10:31:54

标签: c pointers linked-list

程序应该读取一个简单的文本文件,并将数据(名称和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;
}

目前输出为:

enter image description here

1 个答案:

答案 0 :(得分:1)

由于将sizeof(buffer)传递给fgets(),问题正在发生。 buffer是指针,sizeof(buffer)将根据基础架构4位或8位返回3264。将其更改为:

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

,因为您要将sizeof(struct Prova)尺寸分配给buffer

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

说,你的文件有这些数据:

abcdefghijklmno 123456789

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

您不应根据buffer的大小将内存分配到struct Prova。相反,我建议采用更大尺寸的buffer,如下所示(无需动态分配):

char buffer[100];

确保它应该足够大,以便在fgets的一次读取中容纳文件的一行,或修改您的代码,以便在p.nome之前填充p.idfgets点击换行符或EOF即确保读取整行,然后只sscanf() p.nomep.id