Here is student.txt file with some information and I took them to the array and I created a sorted linked list using the array, but it is not listing any information. I could not find why it is happening! Here is the onlineGDB session.
Who can find my mistake in the code and explain it?
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct studInfo {
int studNr;
char studName[12];
int grade;
};
struct node {
struct studInfo info;
struct node *link;
};
typedef struct node *NODEPTR;
NODEPTR getnode(void);
void fileIntoArray(struct studInfo allStudent[],int *num);
void sortByNum(struct studInfo allstudent[], NODEPTR *, int num);
void list(NODEPTR);
int main() {
struct studInfo allStudent[150];
NODEPTR headNum, headName;
int choice;
int num;
fileIntoArray(allStudent, &num);
sortByNum(allStudent, &headNum, num);
list(headNum);
return 0;
}
void fileIntoArray(struct studInfo allStudent[], int *num) {
FILE *ptr = fopen("student.txt", "r");
int i = 0;
while (!feof(ptr)) {
fscanf(ptr, "%d%s%d", &allStudent[i].studNr,
allStudent[i].studName, &allStudent[i].grade);
i++;
}
*num = i;
fclose(ptr);
}
void sortByNum(struct studInfo allStudent[], NODEPTR *headNum, int num) {
NODEPTR head, p, save, prev;
head = NULL;
for (int i = 0; i <= num; ++i) {
p = getnode();
p->info = allStudent[i];
if (head = NULL) {
head = p;
p->link = NULL;
} else {
if (p->info.studNr < head->info.studNr) {
p->link = head;
head = p;
} else {
save = head;
while ((save->info.studNr < p->info.studNr) &&(save != NULL)) {
prev = save;
save = save->link;
if (save == NULL) {
prev->link = p;
p->link = NULL;
} else {
p->link = prev->link;
prev->link = p;
}
}
}
}
}
*headNum = head;
}
void list(NODEPTR headNum) {
NODEPTR p = headNum;
int line = 0;
while (p->link != NULL) {
line++;
if (line > 25) {
printf("Tab a button\n");
getchar();
line = 1;
}
printf("%d %d %s %d\n", line, p->info.studNr,
p->info.studName, p->info.grade);
p = p->link;
}
}
NODEPTR getnode() {
NODEPTR q;
q = (NODEPTR)malloc(sizeof(struct node));
return(q);
}
There are multiple problems:
in sortByNum
, the loop for (int i = 0; i <= num; ++i)
runs one iteration too far. You should use i < num
to iterate exactly num
times.
in sortByNum()
, the test if (head = NULL)
is incorrect. You should write:
if (head == NULL)
while (!feof(ptr))
is incorrect too. You should instead write:
while (fscanf(ptr, "%d%s%d", &allStudent[i].studNr,
allStudent[i].studName, &allStudent[i].grade) == 3) {
i++;
}
you should pass the array length to fileIntoArray
so it can avoid writing beyond the end of the array.
the node
structures should have pointers to the studInfo
entries in the array, not copies.
the node insertion code is too complicated and probably incorrect.
in list
, the test while (p->link != NULL)
will cause a crash if the list passed as argument is empty.
fileIntoArray
and sortByNum
should return a result instead of storing it to a caller variable via a pointer.
hiding pointers behind typedefs such as NODEPTR
is not recommended. Use struct node *ptr
or possibly define node
as a typedef
for struct node
and write node *ptr
.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct studInfo {
int studNr;
char studName[32];
int grade;
};
struct node {
struct studInfo *info;
struct node *link;
};
struct node *getnode(void);
int fileIntoArray(struct studInfo allStudent[], int len);
struct node *sortByNum(struct studInfo allstudent[], int num);
struct node *sortByName(struct studInfo allstudent[], int num);
void list(const struct node *p);
int main() {
struct studInfo allStudent[150];
int num = fileIntoArray(allStudent, 150);
struct node *headNum = sortByNum(allStudent, num);
struct node *headName = sortByName(allStudent, num);
printf("\nStudent list by ID:\n");
list(headNum);
printf("\nStudent list by name:\n");
list(headName);
return 0;
}
int fileIntoArray(struct studInfo allStudent[], int len) {
int i = 0;
FILE *ptr = fopen("student.txt", "r");
if (ptr != NULL) {
while (i < len && fscanf(ptr, "%d%31s%d",
&allStudent[i].studNr,
allStudent[i].studName,
&allStudent[i].grade) == 3) {
i++;
}
fclose(ptr);
}
return i;
}
struct node *sortByNum(struct studInfo allStudent[], int num) {
struct node *head = NULL;
for (int i = 0; i < num; ++i) {
struct node *p = getnode();
p->info = &allStudent[i];
if (head == NULL || p->info->studNr < head->info->studNr) {
p->link = head;
head = p;
} else {
struct node *prev = head;
while (prev->link && prev->link->info->studNr < p->info->studNr) {
prev = prev->link;
}
p->link = prev->link;
prev->link = p;
}
}
return head;
}
struct node *sortByName(struct studInfo allStudent[], int num) {
struct node *head = NULL;
for (int i = 0; i < num; ++i) {
struct node *p = getnode();
p->info = &allStudent[i];
if (head == NULL || strcmp(p->info->studName, head->info->studName) < 0) {
p->link = head;
head = p;
} else {
struct node *prev = head;
while (prev->link && strcmp(prev->link->info->studName, p->info->studName) < 0) {
prev = prev->link;
}
p->link = prev->link;
prev->link = p;
}
}
return head;
}
void list(const struct node *p) {
int line = 0, c;
while (p != NULL) {
line++;
if (line > 25) {
printf("Press enter>");
fflush(stdout);
while ((c = getchar()) != EOF && c != '\n')
continue;
printf("\r \r");
line = 1;
}
printf("%d %d %s %d\n", line, p->info->studNr,
p->info->studName, p->info->grade);
p = p->link;
}
}
struct node *getnode(void) {
struct node *q = malloc(sizeof(*q));
if (q == NULL) {
perror("cannot allocate node");
exit(1);
}
return q;
}