将文本文件扫描到链表中
Scanning in a text file into a linked list
我只是在学习链表,我必须做一个有很多部分的作业,但我刚开始,我需要做的第一件事就是将输入文件读入链表.
文件的一部分是:
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("%d\n", c);
temp = temp->next;
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++;
}
}
在下面几行中,您已经为列表中的单个元素(一个 struct node
)分配了足够的 space,并将您的 head
指针指向它:
temp = (struct node *)malloc(sizeof(struct node));
head = temp;
稍后您将值读入此元素的 name
和 id
字段:
fscanf(ifp, "%s", &temp->name);
fscanf(ifp, "%d", &temp->id);
但是 temp->next
指向什么?到目前为止,您只为单个元素分配了 space。您需要为添加到列表中的每个后续元素分配 space。
编辑:如@merlin2011 所示,此答案只会帮助您解决程序崩溃问题,但不会完全让您的程序按预期运行。但是,希望您能够在它没有崩溃后更好地调试它。
主要问题当然是 temp = temp->next
将 temp 设置为从未初始化的字段 next
,导致代码分段。下一个循环出错。
存在链表问题和输入问题。建议在找到好的数据之前不要分配 space。
从 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
(为终止 '[=28=]'
留出空间,当字段是数组时不使用 &
,并且检查是否成功扫描了 2 个字段。
在 main()
结束之前,代码应该释放分配的数据。
我只是在学习链表,我必须做一个有很多部分的作业,但我刚开始,我需要做的第一件事就是将输入文件读入链表. 文件的一部分是:
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("%d\n", c);
temp = temp->next;
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++;
}
}
在下面几行中,您已经为列表中的单个元素(一个 struct node
)分配了足够的 space,并将您的 head
指针指向它:
temp = (struct node *)malloc(sizeof(struct node));
head = temp;
稍后您将值读入此元素的 name
和 id
字段:
fscanf(ifp, "%s", &temp->name);
fscanf(ifp, "%d", &temp->id);
但是 temp->next
指向什么?到目前为止,您只为单个元素分配了 space。您需要为添加到列表中的每个后续元素分配 space。
编辑:如@merlin2011 所示,此答案只会帮助您解决程序崩溃问题,但不会完全让您的程序按预期运行。但是,希望您能够在它没有崩溃后更好地调试它。
主要问题当然是 temp = temp->next
将 temp 设置为从未初始化的字段 next
,导致代码分段。下一个循环出错。
存在链表问题和输入问题。建议在找到好的数据之前不要分配 space。
从 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
(为终止 '[=28=]'
留出空间,当字段是数组时不使用 &
,并且检查是否成功扫描了 2 个字段。
在 main()
结束之前,代码应该释放分配的数据。