C语言 将文本文件扫描到链表中



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

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;

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

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

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

编辑:如下@merlin2011所示,此答案只会帮助您解决程序崩溃问题,但不会完全使您的程序像您期望的那样工作。 但是,希望一旦它没有崩溃,您将能够更好地调试它。

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

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

temp_head开始。 代码仅使用 temp_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 = (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++;
    }
}

相关内容

  • 没有找到相关文章