C 将文本文件扫描到链接列表中

C 将文本文件扫描到链接列表中,c,input,linked-list,text-files,scanf,C,Input,Linked List,Text Files,Scanf,我只是在学习链表,我必须做一个包含很多部分的作业,但我刚开始,我需要做的第一件事是将输入文件读入链表。 文件的一部分是: George Washington,2345678 约翰·亚当斯,3456789 托马斯·杰斐逊,4567890 詹姆斯·麦迪逊,0987654 詹姆斯·门罗,9876543 约翰·昆西·亚当斯,8765432 共包含26行 我现在想做的只是在文件中读取。 我尝试使用这段代码(目前主要使用) #包括 #包括 结构节点{ 字符名[20]; int-id; 结构节点*下一步; }

我只是在学习链表,我必须做一个包含很多部分的作业,但我刚开始,我需要做的第一件事是将输入文件读入链表。 文件的一部分是:

George Washington,2345678
约翰·亚当斯,3456789
托马斯·杰斐逊,4567890
詹姆斯·麦迪逊,0987654
詹姆斯·门罗,9876543
约翰·昆西·亚当斯,8765432

共包含26行

我现在想做的只是在文件中读取。 我尝试使用这段代码(目前主要使用)

#包括
#包括
结构节点{
字符名[20];
int-id;
结构节点*下一步;
}*头部;
内部主(空){
结构节点*temp;
temp=(结构节点*)malloc(sizeof(结构节点));
压头=温度;
文件*ifp;
ifp=fopen(“AssignmentOneInput.txt”,“r”);
int c=0;
while(cname);
fscanf(ifp、%d、&temp->id);
printf(“%d\n”,c);
温度=温度->下一步;
C++;
}
对于输出,我知道会扫描第一个名称和第一个ID,因为c的值显示为0(现在我任意使用c的值来控制fscanf)。但在那之后,程序崩溃了。所以问题一定出在
temp=temp->next它编译得很好

我对链表很陌生,所以我真的不知道自己在做什么


谢谢你的帮助

首先,由于您使用的是
C
,因此无需强制转换
malloc

其次,您必须自己为每个新节点分配内存

第三,数组的名称已经衰减为指针,因此您不应该使用它的
&
,因为这样您将获得指向指针的指针,而指针不是您想要的

最后,您需要修改
scanf
语法来处理字段中的空格

#include <stdio.h>
#include <stdlib.h>

#include <string.h>

struct node{

    char name[20];
    int id;
    struct node *next;

}*head;



int main(void){

    struct node *temp;
    temp = malloc(sizeof(struct node));
    temp->next = NULL;
    head = temp;

    FILE *ifp;
    ifp = fopen("AssignmentOneInput.txt", "r");

    int c = 0;

    char buffer[1024];
    memset(buffer, 0, 1024);
    while(c<5){
        fgets(buffer, 1024, ifp);
        sscanf(buffer, "%19[^,], %d", temp->name, &temp->id);
        printf("%d %s %d\n",c, temp->name, temp->id);
        temp->next = malloc(sizeof(struct node));
        temp = temp->next;
        temp->next = NULL;
        c++;
    }
}
#包括
#包括
#包括
结构节点{
字符名[20];
int-id;
结构节点*下一步;
}*头部;
内部主(空){
结构节点*temp;
temp=malloc(sizeof(struct node));
temp->next=NULL;
压头=温度;
文件*ifp;
ifp=fopen(“AssignmentOneInput.txt”,“r”);
int c=0;
字符缓冲区[1024];
memset(缓冲区,0,1024);
while(cname,&temp->id);
printf(“%d%s%d\n”,c,temp->name,temp->id);
temp->next=malloc(sizeof(结构节点));
温度=温度->下一步;
temp->next=NULL;
C++;
}
}

在以下几行中,您为列表中的单个元素(一个
结构节点
)分配了足够的空间,并将
指针指向它:

temp = (struct node *)malloc(sizeof(struct node));
head = temp;
稍后,将值读入该元素的
name
id
字段:

fscanf(ifp, "%s", &temp->name);
fscanf(ifp, "%d", &temp->id);
但是
temp->next
指向什么?到目前为止,您只为单个元素分配了空间。在将每个后续元素添加到列表中时,需要为其分配空间


编辑:正如@merlin2011在下面指出的,这个答案只会帮助您解决程序崩溃问题,但不会完全让您的程序按预期工作。不过,希望您能够在它没有崩溃时更好地调试它。

主要问题当然是
temp=temp->next
将temp设置为从未初始化的字段
next
,导致代码中断。下一个回路出现故障

有链接列表问题和输入问题。建议在找到好数据之前不要分配空间

温度头开始。代码仅使用temp\u headnext字段

struct node temp_head;
temp_head.next = NULL;
struct node *p = &temp_head;
每当代码读取行数据时,建议使用
fgets()
读取行,然后扫描缓冲区

char buf[100];
while (fgets(buf, sizeof buf, ifp) != NULL) {
  struct node nbuf;
使用
sscanf()
扫描缓冲区。使用
'%[^,]'
阅读直到
,'

  if (2 != sscanf(buf, " %19[^,],%d", nbuf.name, &nbuf.id)) {
    break;  // Invalid data encountered
  }
  nbuf.next = NULL;

  // Code does not allocate data until good data was found 
  p->next = malloc(sizeof *(p->next));
  if (p->next == NULL) break;  // OOM
  p = p->next;
  *p = nbuf;  // Copy the data
}

head = temp_head.next;

注:

强制转换
temp=(结构节点*)malloc(sizeof(结构节点))是不需要的

考虑这种分配方式:
temp=malloc(sizeof*temp)
,在我看来,它更容易编码,维护更少

fscanf(ifp、%s、&temp->name);fscanf(ifp、%d、&temp->id)有3个问题:对字符串输入没有限制、不需要的
&
以及无法检查扫描结果。请注意,上面的代码使用
(2!=sscanf(buf,“%19[^,]”,%d“、nbuf.name和nbuf.id)
,这将字符串输入限制为19
char
(为终止
'\0'
留出空间),在字段为数组时不使用
&
,并检查是否成功扫描了两个字段


main()
结束之前,代码应该释放分配的数据。

您必须在每次循环中malloc一个新节点,您必须将上一个next设置为指向新节点
fscanf(ifp,'%s',&temp->name);
将读取“George”,而不是“George Washington”这个答案解决了内存问题,但不足以使代码按预期工作。@merlin2011——没错。因为这显然是一项学校作业,我选择了简单地解决眼前的问题,并希望它能让OP取得进展。我将尝试在答案中指出这一点。是的。我设法解决了它,现在它已经完成了它没有崩溃。在我的主要关注点只是让它运行之前。这不是与OP的问题无关吗?@Peter Schneider OP的扫描和所有问题都联系在一起。@Peter Schneider Code的temp=temp->next;将从未初始化的temp设置为字段next,导致它在下一个循环中隔离故障-如果它走得那么远。
fscanf(ifp,“%d”,&temp->id);
将无法将“Washington”转换为一个数字,并且代码没有检查这一点,这使得调试器在
temp
中看到的内容变得复杂;
可能会溢出
temp
,但如果保存了OP输入,则不会发生这种情况。
  if (2 != sscanf(buf, " %19[^,],%d", nbuf.name, &nbuf.id)) {
    break;  // Invalid data encountered
  }
  nbuf.next = NULL;

  // Code does not allocate data until good data was found 
  p->next = malloc(sizeof *(p->next));
  if (p->next == NULL) break;  // OOM
  p = p->next;
  *p = nbuf;  // Copy the data
}

head = temp_head.next;