在文本文件中扫描到链接列表

时间:2015-01-26 21:13:08

标签: c input linked-list text-files scanf

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

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;它编译得很好。

我对链接列表很新,所以我真的不知道自己在做什么。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

首先,由于您在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++;
    }
}

答案 1 :(得分:1)

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

temp = (struct node *)malloc(sizeof(struct node));
head = temp;

稍后您会将值读入此元素的nameid字段:

fscanf(ifp, "%s", &temp->name);
fscanf(ifp, "%d", &temp->id);

temp->next指向的是什么?你到目前为止只为一个元素分配了空间。在将每个后续元素添加到列表中时,需要为每个后续元素分配空间。

编辑:正如@ merlin2011所示,这个答案只会帮助您解决程序崩溃问题,但不会让您的程序完全正常运行。但是,希望你能够在没有崩溃的情况下更好地调试它。

答案 2 :(得分:1)

主要问题当然是temp = temp->next设置从未初始化的字段next的临界值,导致代码段。在下一个循环中出现故障。

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

temp_head开头。代码仅使用next的{​​{1}}字段。

temp_head

每当代码读取行数据时,建议使用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));,IMO更容易编码,维护更少。

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

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