Reputation: 41
I have written a code to enter the name, age, department id, company name, and salary respectively, of employees from a text file into a linked list. Right now, In my code, I have created an insert function and a display function. When I ran the code on the command prompt there were no errors found. However, my list did not get printed. Can someone help me out with this if possible? thankyou.
Here are the details of the file, it is called employee.txt:
Peter 30 1001 Apple 8000
Joseph 50 1002 Oracle 4000
Mary 40 1003 Samsung 6000
Lilly 40 1203 Samsung 7000
Tony 50 1002 Oracle 3000
Jake 30 1005 Apple 3000
Sam 40 1007 Samsung 4000
Lisa 30 1300 Oracle 5000
Kate 50 1200 Apple 6000
Rick 50 1313 Apple 4000
My Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct personTag {
char name[20];
int age;
};
struct officialTag {
int deptId;
char cmpName[20];
double salary;
};
struct employeeTag {
struct personTag personalInfo;
struct officialTag officialInfo;
struct employeeTag *next;
};
typedef struct employeeTag EmpTag;
typedef EmpTag *EmpTagPtr;
void insert(EmpTagPtr *s, char E_name[], int E_age, int E_deptid,
char E_cmpname[], double E_salary);
void displayEmployees(EmpTagPtr s);
int main() {
EmpTagPtr start = NULL;
char E_name[20];
int E_age;
int E_deptid;
char E_cmpname[20];
double E_salary;
// reading employee.txt file
FILE *fp;
fp = fopen("employee.txt", "r");
fscanf(fp, "%s,%d,%d,%s,%lf", E_name, &E_age, &E_deptid, E_cmpname,
&E_salary);
while (!feof(fp)) {
insert(&start, E_name, E_age, E_deptid, E_cmpname,
E_salary); // inserting data to the new node
fscanf(fp, "%s,%d,%d,%s,%lf", E_name, &E_age, &E_deptid, E_cmpname,
&E_salary);
}
fclose(fp);
displayEmployees(start);
return 0;
}
void insert(EmpTagPtr *s, char E_name[], int E_age, int E_deptid,
char E_cmpname[], double E_salary) {
EmpTagPtr current = *s;
EmpTagPtr prev = NULL;
// create an empty node
EmpTagPtr newNode;
newNode = (EmpTag *)malloc(sizeof(EmpTag));
// filling in the values
strcpy(newNode->personalInfo.name, E_name);
newNode->personalInfo.age = E_age;
newNode->officialInfo.deptId = E_deptid;
strcpy(newNode->officialInfo.cmpName, E_cmpname);
newNode->officialInfo.salary = E_salary;
newNode->next = NULL;
while (current != NULL &&
strcmp(current->personalInfo.name, prev->personalInfo.name) > 0) {
prev = current;
current = current->next;
}
if (prev == NULL) {
// add as the first node
newNode->next = *s;
*s = newNode;
} else {
prev->next = newNode;
newNode->next = current;
}
}
void displayEmployees(EmpTagPtr s) {
EmpTagPtr current = s;
while (current != NULL) {
// printing the data part
printf("Employee name: %s\n", current->personalInfo.name);
printf("Company name: %s\n", current->officialInfo.cmpName);
printf("Employee Age: %d\n", current->personalInfo.age);
printf("Department ID: %d\n", current->officialInfo.deptId);
printf("Employee Salary: %lf\n", current->officialInfo.salary);
printf("---------------------------------------------------------");
current = current->next; // move foward the current pointer
}
printf("NULL\n");
}
Upvotes: 2
Views: 139
Reputation: 118077
Your loop to read uses the wrong fscanf
format. The loop is also a bit overcomplicated. Just fscanf
and check that you successfully extracted the 5
elements. Note the limits for the strings and removed commas:
while (fscanf(fp, "%19s %d %d %19s %lf", E_name, &E_age, &E_deptid,
E_cmpname, &E_salary) == 5)
{
insert(&start, E_name, E_age, E_deptid, E_cmpname, E_salary);
}
The insert
function has a buggy loop to find the insertion point. prev
will be a NULL
pointer here:
while(current != NULL && strcmp(current->personalInfo.name,
prev->personalInfo.name) >0 )
{
prev = current;
current = current->next;
}
Suggested fix:
void insert(EmpTagPtr *s, char E_name[], int E_age, int E_deptid,
char E_cmpname[], double E_salary)
{
// create an empty node
EmpTagPtr newNode = malloc(sizeof *newNode);
// filling in the values
strcpy(newNode->personalInfo.name, E_name);
newNode->personalInfo.age = E_age;
newNode->officialInfo.deptId = E_deptid;
strcpy(newNode->officialInfo.cmpName, E_cmpname);
newNode->officialInfo.salary = E_salary;
// use `newNode` in the comparison:
while (*s && strcmp(newNode->personalInfo.name,
(*s)->personalInfo.name) > 0)
{
s = &(*s)->next;
}
// `s` now points at the `EmpTagPtr` pointer where the new node should
// be inserted for the list to be sorted in alphabetical order.
// If it's the first node to be inserted, `s` points at `start` so
// you do not need `prev` or `current`:
newNode->next = *s;
*s = newNode;
}
As can be seen in the demo, your program leaks memory so you need to add a function to clean that up.
More about the insertion logic:
start
as the next
member of an imaginary first dummy node and s
starts out pointing at start
.start
will point at NULL
.
*s
will therefore be == NULL
and the while loop will not do any laps.newNode->next = *s
(which is NULL
) and assign *s = newNode
(which means start
will point at newNode
). The first node is now completely linked.while
loop will compare the name of the newNode
with that of the dereferenced s
's name. EmpTagPtr current = *s;
followed by current->personalInfo.name
is the same as (*s)->personalInfo.name
.
strcmp(newNode->personalInfo.name, (*s)->personalInfo.name) > 0
we haven't found the insertion point and step s
to point at the next node's next
member, s = &(*s)->next
- and loop to check the conditions again.false
it means that newNode
should be inserted between the node to which the next
member s
points at belongs and the *s
node - and the loop terminates. When the loop terminates s
will therefore point at a next
member where the new node should be inserted.It can be hard to "see" it without actually doing this with pen and paper so I recommend doing just that. Insert 3 nodes using only pen and paper and draw the pointers to see where everything ends up. It usually gives me an "aha!" moment.
Upvotes: 2
Reputation: 1922
I think an important point to improve your programme is database normalization. You might end up with roughly:
Where, person.txt
is (an example),
1 Peter 30
2 Joseph 50
3 Mary 40
works.txt
1 1001 8000
2 1002 4000
3 1002 6000
department.txt
1001 1
1002 1
company.txt
1 Apple
Instead of duplicating data, this reduces data redundancy. This is good for if you want to add or make changes to your database. It also mirrors the usage (somewhat) in your programme.
Upvotes: 1
Reputation: 11
As Allan Wind already commented on your question, the first problem was that you had commas in fscanf
even though your data is seperated by spaces.
A bigger problem is that segmentation fault occurs in the following while loop in your insert()
function
while(current != NULL && strcmp(current->personalInfo.name , prev->personalInfo.name) >0 )
{
prev = current;
current = current->next;
}
This happens because you are accesing personalInfo
of prev
when prev
is set to NULL
. I assume that what you wanted to do here is insert an elemente into the linked list so that the list stays sorted alphabetically by names. In that case, you must compare names of current
and newNode
in strcmp
and NOT names of current
and prev
. Your condition in the while loop should look like this:
while(current != NULL && prev != NULL && strcmp(current->personalInfo.name , newNode->personalInfo.name) > 0 )
Upvotes: 1