[英]How to create sorted linked list using array of structure in c
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.
这是包含一些信息的student.txt文件,我将它们带到数组中,并使用数组创建了一个排序链表,但它没有列出任何信息。 I could not find why it is happening!
我找不到为什么会这样! Here is the onlineGDB session .
这是 onlineGDB 会话。
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.在
sortByNum
中, for (int i = 0; i <= num; ++i)
的循环运行了一次迭代。 You should use i < num
to iterate exactly num
times.您应该使用
i < num
精确地迭代num
次。
in sortByNum()
, the test if (head = NULL)
is incorrect.在
sortByNum()
中,测试if (head = NULL)
不正确。 You should write:你应该写:
if (head == NULL)
while (!feof(ptr))
is incorrect too. while (!feof(ptr))
也不正确。 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.您应该将数组长度传递给
fileIntoArray
,这样它就可以避免写入超出数组的末尾。
the node
structures should have pointers to the studInfo
entries in the array, not copies. node
结构应该有指向数组中studInfo
条目的指针,而不是副本。
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.在
list
,如果作为参数传递的列表为空,则测试while (p->link != NULL)
将导致崩溃。
fileIntoArray
and sortByNum
should return a result instead of storing it to a caller variable via a pointer. fileIntoArray
和sortByNum
应该返回一个结果,而不是通过指针将其存储到调用者变量中。
hiding pointers behind typedefs such as NODEPTR
is not recommended.不建议将指针隐藏在诸如
NODEPTR
之类的 typedef 后面。 Use struct node *ptr
or possibly define node
as a typedef
for struct node
and write node *ptr
.使用
struct node *ptr
或可能将node
定义为struct node
的typedef
并写入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;
}
Corrected list
function, see comment in the code.更正了
list
功能,请参见代码中的注释。
Provided an implementation of Insertion Sort on the given data structure.在给定的数据结构上提供了插入排序的实现。 (There is a more concise implementation available: Insertion Sort on Wikipedia .)
(有一个更简洁的实现可用: Wikipedia 上的插入排序。)
Please note that the code below is reduced.请注意,下面的代码已减少。 It just contains what is necessary to illustrate the sorting.
它只包含说明排序所必需的内容。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct studInfo {
int studNr;
char studName[12];
int grade;
};
struct node {
struct studInfo info;
struct node *link;
};
typedef struct node *NODEPTR;
void list(NODEPTR headNum) {
NODEPTR p = headNum;
int line = 0;
while (p != NULL) { // corrected from p->link != NULL
line++;
if (line > 25) {
printf("Tab a button\n");
getchar();
line = 1;
}
printf("%d %d %s \t %d\n", line, p->info.studNr,
p->info.studName, p->info.grade);
p = p->link;
}
}
// Insertion Sort
NODEPTR sort(NODEPTR root, bool sortByName) {
if (root == NULL || root->link == NULL) {
// All lists with less than two elements are already sorted.
return root;
}
// put first element into sorted list
NODEPTR sorted_root = root;
// start iteration with second element
NODEPTR iterator = root->link;
// set end of sorted list
sorted_root->link = NULL;
while (iterator != NULL) {
// trace position directly before insertion point
NODEPTR previous = NULL;
// iterate over already sorted list
NODEPTR sorted_iterator = sorted_root;
// determine insertion point in already sorted list
while (
// list end not reached
sorted_iterator != NULL
&&
// need to advance in sorted list for proper position
(sortByName ?
strcmp(sorted_iterator->info.studName, iterator->info.studName) <= 0
:
sorted_iterator->info.studNr < iterator->info.studNr)) {
previous = sorted_iterator;
sorted_iterator = sorted_iterator->link;
}
if (previous == NULL) {
// prepend sorted list with element
NODEPTR tmp = sorted_root;
sorted_root = iterator;
iterator = iterator->link;
sorted_root->link = tmp;
} else if (sorted_iterator == NULL) {
// append new last element in sorted list
previous->link = iterator;
NODEPTR tmp = iterator->link;
iterator->link = NULL;
iterator = tmp;
} else {
// insert element at correct position
NODEPTR tmp = iterator->link;
previous->link = iterator;
iterator->link = sorted_iterator;
iterator = tmp;
}
}
return sorted_root;
}
int main() {
struct studInfo allStudent[3];
allStudent[0].studNr = 303; strcpy(allStudent[0].studName,"Bella"); allStudent[0].grade = 1;
allStudent[1].studNr = 202; strcpy(allStudent[1].studName,"Carla"); allStudent[1].grade = 2;
allStudent[2].studNr = 101; strcpy(allStudent[2].studName,"Adeline"); allStudent[2].grade = 3;
struct node links[3];
links[0].info = allStudent[0]; links[0].link = &links[1];
links[1].info = allStudent[1]; links[1].link = &links[2];
links[2].info = allStudent[2]; links[2].link = NULL;
NODEPTR head;
head = &links[0];
printf("Sort by student number\n");
head = sort(head, false);
list(head);
printf("Sort by student name\n");
head = sort(head, true);
list(head);
return 0;
}
Students in the code are in inverse order, now see if the sorting works:代码中的同学是倒序的,现在看看排序是否有效:
$ gcc students.c
$ ./a.out
Sort by student number
1 101 Adeline 3
2 202 Carla 2
3 303 Bella 1
Sort by student name
1 101 Adeline 3
2 303 Bella 1
3 202 Carla 2
$
Seems to work just fine.似乎工作得很好。 :-)
:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.