将文本文件扫描到链表中

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;

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

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() 结束之前,代码应该释放分配的数据。