我只是在学习链表,我必须做一个有很多部分的作业,但我刚开始,我需要做的第一件事就是将输入文件中的读取到链表中。该文件的一部分是:
George Washington, 2345678
John Adams, 3456789
Thomas Jefferson, 4567890
James Madison, 0987654
James Monroe, 9876543
John Quincy Adams, 8765432
共包含 26 行。
我现在想做的只是简单地读取文件。我尝试使用此代码(现在主要)
#include <stdio.h>
#include <stdlib.h>
struct node{
char name[20];
int id;
struct node *next;
}*head;
int main(void){
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
head = temp;
FILE *ifp;
ifp = fopen("AssignmentOneInput.txt", "r");
int c = 0;
while(c<26){
fscanf(ifp, "%s", &temp->name);
fscanf(ifp, "%d", &temp->id);
printf("%dn", c);
temp = temp->next;
c++;
}
对于输出,我知道名字和第一个 ID 被扫描,因为 c 的值显示为 0(现在我任意使用 c 的值来控制 fscanf)。但在那之后,程序崩溃了。所以问题一定出在temp = temp->next;
它编译得很好。
我对链表很陌生,所以我真的不知道我在做什么。
感谢您的帮助!
在以下行中,您已经为列表中的单个元素(一个struct node
)分配了足够的空间,并将head
指针指向它:
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_head
开始。 代码仅使用 temp_head
的next
字段。
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 = (struct node *)malloc(sizeof(struct node));
的演员阵容。
考虑这种分配方式:temp = malloc(sizeof *temp)
,IMO 它更容易编码,维护更少。
fscanf(ifp, "%s", &temp->name); fscanf(ifp, "%d", &temp->id);
有 3 个问题:字符串输入没有限制、不需要&
和无法检查扫描结果。 请注意,上面的代码使用 (2 != sscanf(buf, " %19[^,], %d", nbuf.name, &nbuf.id)
,它将字符串输入限制为 19 char
(为终止' '
留出空间),当字段是数组时不使用&
,并检查 2 个字段是否已成功扫描。
在main()
结束之前,代码应该释放分配的数据。
首先,既然你是用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 %dn",c, temp->name, temp->id);
temp->next = malloc(sizeof(struct node));
temp = temp->next;
temp->next = NULL;
c++;
}
}