Reputation: 119
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
Reputation: 5892
I think there are a few problems in your code:
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.
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.
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