从c中的文件加载列表

从c中的文件加载列表,c,list,file,C,List,File,我无法正确指定列表的结尾。我不知道为什么,但我认为这是因为while循环的条件是允许节点从内存中获取数据,然后使其next=NULL。我试图替换node->next=NULL带有节点=NULL但它不起作用。我将非常高兴收到一些有用的解决方案或提示,并提前向您表示感谢 #include <stdio.h> #include <stdlib.h> #include <malloc.h> //my variables typedef struct { ch

我无法正确指定列表的结尾。我不知道为什么,但我认为这是因为
while
循环的条件是允许节点从内存中获取数据,然后使其
next=NULL
。我试图替换
node->next=NULL带有
节点=NULL但它不起作用。我将非常高兴收到一些有用的解决方案或提示,并提前向您表示感谢

#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

//my variables
typedef struct {
    char Fname[len];
    char Lname[len];
    double salary;
} employee;

// list of employees
typedef struct list {
    employee e;
    struct list *next;
} list;

void LOAD_LIST(FILE *f, list *head)
{
    list *node = (list *)malloc(sizeof(list));
    node = head;

    while (fscanf(f, "%10s%10s%lf", node->e.Fname, node->e.Lname, &node->e.salary) != EOF)
    {
        node->next = (list *)malloc(sizeof(list));
        if (node->next == NULL)
        {
            printf("memory allocation failed\n");
            break;
        }
        node = node->next;
    }
    node->next = NULL;
}

void DISPLAY(list *node)
{
    while (node != NULL)
    {
        printf("%s | %s | %.2lf\n", node->e.Fname, node->e.Lname, node->e.salary);
        node = node->next;
    }
}

void freeList(struct list *head)
{
    list *tmp;

    while (head != NULL)
    {
        tmp = head;
        head = head->next;
        free(tmp);
    }
}

int main()
{
    FILE *file = fopen("file.txt", "r");
    list *listhead = (list *)malloc(sizeof(listhead));

    LOAD_LIST(file, listhead);
    DISPLAY(listhead);
    freeList(listhead);
    fclose(file);
    return 0;
}

我认为您的代码中存在一些问题:

  • 您总是在
    main()
    中分配链表的标题,如果您的文件是空的,并且没有通过文件解析数据,该怎么办。我认为您应该修改
    LOAD\u LIST
    方法以返回新的列表头

  • LOAD_LIST
    方法的
    while
    循环中,在使用
    fscanf
    读取之前分配
    LIST*节点。这意味着无论在fscanf期间发生什么,都会分配一个额外的节点。我认为您应该在阅读后通过
    fscanf
    分配内存,检查解析的字符数是否等于3

  • 不确定原因,但您正在读取
    节点的内容时分配
    节点->下一个
    的内存。如果这是您正在读取的文件的最后一行呢。最后会有一个额外的节点

  • 我将节点内存分配+初始化逻辑移动到方法
    createNewNode
    ,并跟踪
    head
    prevNode
    变量,以跟踪链接列表的开始和最后分配的节点:

    list*createNewNode(char firstName[],char lastName[],双薪){
    list*newNode=(list*)malloc(sizeof(list));
    if(newNode==NULL){
    printf(“节点内存分配失败\n”);
    返回NULL;
    }
    strcpy(newNode->e.fName,firstName);
    strcpy(newNode->e.lName,lastName);
    newNode->e.salary=salary;
    newNode->next=NULL;
    }
    列表*加载列表(文件*f)
    {
    列表*head=NULL,*prevNode=NULL;
    char firstName[100],lastName[100];
    双薪;
    而(fscanf(f,“%10s%10s%lf”、名、姓和薪水)==3){
    list*currentNode=createNewNode(名字、姓氏、薪水);
    if(currentNode==NULL){
    printf(“内存分配失败\n”);
    打破
    }
    if(head==NULL){
    head=当前节点;
    prevNode=currentNode;
    }否则{
    prevNode->next=currentNode;
    prevNode=currentNode;
    }
    }
    回流头;
    }
    // ...
    int main(){
    FILE*FILE=fopen(“FILE.txt”、“r”);
    列表*列表头=加载列表(文件);
    显示器(列表头);
    自由列表(列表头);
    fclose(文件);
    返回0;
    }
    
    我使用如下文件进行了测试:

    Rohan Kumar 100
    Robert Dicosta 200
    Rupert Griffin 30
    BadInput
    
    这将提供以下输出:

    c-posts : $ ./a.out 
    Rohan | Kumar | 100.00
    Robert | Dicosta | 200.00
    Rupert | Griffin | 30.00
    

    node=malloc(…)后跟
    节点=头部
    是内存泄漏:您丢失了malloced内存。在
    main
    中,您不会初始化刚刚分配的
    listhead
    。您应该检查
    fscanf
    是否读取了正确数量的参数,即3。您附加了一个节点,然后读取了它的数据。如果读取失败,则必须删除此节点。注意:
    ALLCAPS
    名称通常是为C中的常量和宏保留的。不需要强制转换
    malloc
    的返回,这是不必要的。请参阅:。您不需要在
    main()
    中为
    listfead
    分配,只需声明指针并将其地址传递到
    LOAD\u LIST()
    并更新地址即可<代码>节点=头部覆盖您刚才分配的内存块的地址,造成内存泄漏。感谢您的努力这实际上很有帮助,但我试图做的是尽量少使用变量,因为我认为太多变量会使代码在执行时变得混乱和缓慢。。。ofc在这种情况下,速度是不明显的,但如果它是一个长期的项目,它会影响我的节目质量吗?我的意思是使用更少的变量,同时保持它的可理解性好还是不好?哦,如果你想减少变量的使用,你可能想先分配内存,使用fscanf读取并释放fscanf失败的情况我介绍的大多数变量都是函数范围变量,每当控件移出函数时,这些变量就会被销毁。读取的局部变量是正确的方法。没有必要分配,直到你知道你有一个成功的阅读。。。
    c-posts : $ ./a.out 
    Rohan | Kumar | 100.00
    Robert | Dicosta | 200.00
    Rupert | Griffin | 30.00