Omayma Benali
Omayma Benali

Reputation: 119

load list from file in c

I am unable to correctly specify the end of my list. I am not sure why but I think its because the condition of the while loop is allowing node to take data from memory and then making its next = NULL. I tried to replace node->next = NULL; with node = NULL; but it didn't work. I will be very happy to receive some helpful solutions or tips and thank you in advance.

#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;
}

EDIT: Thanks for the responses I corrected the problem you pointed to but I still don't know how to free the node that got EOF. Here is the new function:

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

    fscanf(f, "%10s%10s%lf", head->e.Fname, head->e.Lname, &head->e.salary);
    head->next = node;

    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;
}

Upvotes: 1

Views: 216

Answers (1)

Rohan Kumar
Rohan Kumar

Reputation: 5892

I think there are a few problems in your code:

  1. You're always allocating the head of the linked list in main(), what if your file is empty and no data is parsed via file. I think you should modify your LOAD_LIST method to return the new list head instead.

  2. In while loop of your LOAD_LIST method, you're allocating list *node before reading using fscanf. This means you have an extra node allocated no matter what happens during fscanf. I think you should allocate memory after reading via fscanf check whether number of characters parsed is equal to 3.

  3. Not sure why, but you're allocating memory of node->next while you're reading contents of node. What if it's the last line of file you're reading. You'll have an extra node in the end.

I moved your node memory allocation+initialization logic to a method createNewNode and I'm tracking head and prevNode variables to keep track of beginning and last allocated node of your linked list:

list* createNewNode(char firstName[], char lastName[], double salary) {
    list* newNode = (list *) malloc(sizeof(list));
    if (newNode == NULL) {
        printf("Node Memory allocation failed\n");
        return NULL;
    }

    strcpy(newNode->e.fName, firstName);
    strcpy(newNode->e.lName, lastName);
    newNode->e.salary = salary;
    newNode->next = NULL;
}

list* load_list(FILE *f)
{
    list *head = NULL, *prevNode = NULL;
    char firstName[100], lastName[100];
    double salary;

    while (fscanf(f, "%10s%10s%lf", firstName, lastName, &salary) == 3) {
        list *currentNode = createNewNode(firstName, lastName, salary);
        if (currentNode == NULL) {
            printf("memory allocation failed\n");
            break;
        }

        if (head == NULL) {
            head = currentNode;
            prevNode = currentNode;
        } else {
            prevNode->next = currentNode;
            prevNode = currentNode;
        }
    }
    return head;
}

// ...

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

    list* listhead = load_list(file);
    display(listhead);
    freeList(listhead);
    fclose(file);
    return 0;
}

I tested with a file like this:

Rohan Kumar 100
Robert Dicosta 200
Rupert Griffin 30
BadInput

This gives the following output:

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

Upvotes: 2

Related Questions