基于链表实现的链式管理系统(C语言课设)

举报
一枕眠秋雨 发表于 2024/03/10 15:47:46 2024/03/10
【摘要】 #include <stdio.h>#include <stdlib.h>#include <string.h>typedef struct Logincheck{    char account[1000];    int choose;}Login;typedef struct Student{    char num[100];    char name[20];    int gra...

软件程序:链式学生成绩管理系统

系统简介

该系统以链表为结构,对学生编号、成绩、姓名等信息进行增删改查排序等操作

系统设计与模块实现

1.创建链表模块

创建头节点(也可以不创建头节点,但是要传入二级指针,因为当链表为空的时候,需要对头指针所指向的空间进行更改,所以需要传址调用)。

首先创建一个头节点,初始化。

其次,开辟节点空间

//创建头节点

ListNode* createHead()

{

ListNode* Head = (ListNode*)malloc(sizeof(ListNode));

if (Head == NULL)

return NULL;

Head->next = NULL;

return Head;

}

//创建节点

ListNode* createNode(Stu student)

{

ListNode* pcur = (ListNode*)malloc(sizeof(ListNode));

if (pcur == NULL)

return NULL;

pcur->student = student;

pcur->next = NULL;

return pcur;

}

2.插入学生信息

插入链表节点,存放学生信息。

pcur指针指向节点空间,并逐步更新pcur

void insertNode(ListNode* head, Stu student)

{

ListNode* pcur = createNode(student);

pcur->next = head->next;

head->next = pcur;

}

打印学生信息

打印链表。

定义一个遍历链表的指针,读取节点中存储的数据。

void printList(ListNode* head)

{

ListNode* pcur = head->next;

printf("编号\t姓名\t成绩\n");

while (pcur)

{

printf("%s\t%s\t%d\n", pcur->student.num, pcur->student.name, pcur->student.grade);

pcur = pcur->next;

}

}

3.查找学生信息

查找链表对应数据的节点。

定义一个遍历链表的指针,找到目标节点后将其输出到终端。

void seekNode(ListNode* head, char* num)

{

ListNode* pcur = head->next;

while (pcur && strcmp(pcur->student.num, num))

{

pcur = pcur->next;

}

if (pcur == NULL)

printf("数据不存在\n");

else

{

printf("编号姓名成绩\n");

printf("%s\t%s\t%d\n", pcur->student.num, pcur->student.name, pcur->student.grade);

}

}

4.修改学生信息

修改指定节点的数据。

定义一个遍历链表的指针,找到目标节点后,对节点中的数据进行修改。

void modifyNode(ListNode* head, char* num, Stu student)

{

ListNode* pcur = head->next;

while (pcur && strcmp(pcur->student.num, num))

{

pcur = pcur->next;

}

if (pcur == NULL)

printf("要修改的数据不存在\n");

else if (!is_repeat(pcur->student.num))

printf("该编号已存在,请检查后重新修改!\n");

else

{

pcur->student = student;

FILE* pf = fopen("学生数据.txt", "w+");//将修改后的数据拷贝到文件中

pcur = head->next;

while (pcur)

{

fprintf(pf, "%s\t%s\t%d\n", pcur->student.num, pcur->student.name, pcur->student.grade);

pcur = pcur->next;

}

printf("修改成功\n");

fclose(pf);

}

}

5.登录系统

传入一个密码字符串,通过对账户文件中的数据进行比对,如果比对成功,则传回一个字符串“access”,否则传回“fail”

//登录界面

Login logInterface()

{

Login log;

printf("******************\n");

printf("请输入账户密码\n");

scanf("%s", log.account);

printf("请选择登录或注册(0.登录 1.注册)\n");

scanf("%d", &log.choose);

printf("******************\n");

return log;

}
//登录检测

char* loginCheck(Login log)

{

FILE* pf = NULL;

if (log.choose)//判断用户是要注册还是登录

{

pf = fopen("账户数据.txt", "a");

fprintf(pf, "%s\n", log.account);

printf("注册成功\n");

fclose(pf);

return "access";//注册成功,返回一个token

}

else if (log.choose == 0)

{

pf = fopen("账户数据.txt", "r");

if (pf == NULL)

printf("用户不存在!\n");

else

{

while (1)//比对数据,成功返回一个token

{

char strcheck[1000] = { 0 };

int judge = fscanf(pf, "%s", strcheck);

if (!strcmp(strcheck, log.account))

return "access";

if (judge == EOF)

break;

}

fclose(pf);

}

}

return "fail";

}

6.数据初始化

将文件中的数据封装成一个链表。

逐行读取文件中的数据,并将文件中的数据封装成结构体插入到链表中。

void initData(FILE* pf, ListNode* head)

{

pf = fopen("学生数据.txt", "r");

if (pf == NULL)

printf("数据读取失败,请重试\n");

else

{

ListNode* pcur = head->next;

Stu student;

while (fscanf(pf, "%s%s%d", student.num, student.name, &student.grade) != EOF)

{

insertNode(head, student);

}

fclose(pf);

}

}

7.数据存储

将链表中的数据存储到文件中。

将链表中的数据同步到文件中。

int saveData(FILE* pf, Stu student)

{

pf = fopen("学生数据.txt", "a");

if (pf == NULL)

printf("数据录入失败\n");

else if (!is_repeat(student.num))

printf("该编号已存在,请检查后重新录入!\n");

else

{

fprintf(pf, "%s\t%s\t%d\n", student.num, student.name, student.grade);//将录入的数据保存在文件中

printf("已成功录入\n");

return 1;

fclose(pf);

}

return 0;

}

8.备份恢复

将删除的数据进行恢复。

将备份数据进行恢复。

void restoreBackup(FILE* pf, char* num)

{

pf = fopen("学生数据.txt", "a");

FILE* pfs = fopen("数据备份.txt", "r");

if (pfs == NULL)

printf("该目录下没有数据备份,无法恢复\n");

else

{

Stu student;

int flag = 1;

while (fscanf(pfs, "%s%s%d", student.num, student.name, &student.grade) != EOF)

{

if (!strcmp(num, student.num))

{

fprintf(pf, "%s\t%s\t%d\n", student.num, student.name, student.grade);

flag = 0;

}

}

if (flag)

printf("要恢复的数据不存在\n");

else printf("已成功恢复备份!\n");

fclose(pf);

fclose(pfs);

}

}

9.数据排序

按学生成绩对数据进行排序。

采用冒泡排序,对结构体进行排序。

void sortData(ListNode* head)

{

for (ListNode* first = head->next; first != NULL; first = first->next)

{

for (ListNode* second = head->next; second != NULL; second = second->next)

{

if (second->next != NULL)

{

if (second->student.grade < second->next->student.grade)

{

Stu student = second->student;

second->student = second->next->student;

second->next->student = student;

}

}

}

}

}

10.用户操作

获取用户键盘信息

void keyDown(ListNode* head, FILE* pf)

{

int input = 0;

printf("请用户选择操作方式\n");

scanf("%d", &input);

Stu student;

switch (input)

{

case 0:

printf("程序正在退出\n");

system("pause");

exit(0);

break;

case 1:

if (head->next == NULL)

printf("暂时没有数据,无法浏览\n");

else printList(head);

break;

case 2:

printf("请用户输入学生信息:\n");

scanf("%s %s %d", student.num, student.name, &student.grade);

if (saveData(pf, student))

insertNode(head, student);

break;

case 3:

printf("请用户输入要删除的学生编号:");

scanf("%s", student.num);

deleteNode(head, student.num, pf);

break;

case 4:

printf("请用户输入要修改的学生的编号:");

char str[1000];

scanf("%s", str);

printf("请用户输入新的学生信息:\n");

scanf("%s %s %d", student.num, student.name, &student.grade);

modifyNode(head, str, student);

break;

case 5:

printf("请用户输入要查找的学生编号:");

scanf("%s", student.num);

seekNode(head, student.num);

break;

case 6:

printf("请输入要恢复的学生编号\n");

char back[1000] = { 0 };

scanf("%s", back);

if (!is_repeat(back))

printf("编号重复,请检查后重新输入\n");

else

{

restoreBackup(pf, back);

initData(pf, head);

if (!remove("数据备份.txt"))

printf("备份已删除\n");

}

break;

case 7:

sortData(head);

printList(head);

break;

default:

printf("非法操作,请重新输入!!!\n");

break;

}

}

遇到的难点及解决方法

1.在对文件打开后没有进行关闭,导致无法对某个文件进行移除,链表中的数据没有及时保存到文件当中

在每次调用fopen函数后,检查对文件操作结束后是否调用fclose函数

2.在进行数据判重的时候,如何对录入的学生数据进行判重,如何对修改的数据进行判重(修改后的数据可以与修改前的数据相同,但不能与文件中的其他数据重复)。

可以在调用modifyData函数之前判断新的数据是否满足上述条件

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。