C语言 学生成绩管理系统(基于文件读写操作及单向动态链表的创建,遍历和排序)
本程序为作者的大一下学期的c语言期末作业,用编译器VS2019写成,如有问题和不足,欢迎大家指出共同探讨。
程序主要实现的功能有:学生信息的录入(动态链表创建),输出所有学生信息(链表遍历),输出排名(单向链表排序),以及一系列基于链表操作的查询,修改,添加学生成绩和求平均分,统计分数区域人数等功能。
总体思路:读取文件,创建单向动态链表储存文件中已有的学生成绩。通过对链表的操作,继续录入学生成绩,并且实现输出,修改等功能。在退出程序之前用"w+"模式新建文件重新写入链表中的学生成绩和信息来覆盖原文件。这种方法避免了对文件的直接操作,如在文件中查找删除或修改某个值,转为对链表节点的操作,相对而言更加简便。但这种方法不适用于大量数据的操作。
//函数声明和结构体
为方便修改,本程序中宏定义科目数N为4
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#include<stdlib.h>
#define N 4
//函数声明
void add_stu(int stu_num, struct student* head);//存储学生信息
void menu(struct student* p);//菜单
void list_initi(struct student* p);//链表初始化
void present_all(struct student* p);//展示全部学生成绩
void present_one(struct student* p);//输出某学生成绩
void score_analy(struct student* p);//分析学生成绩
void score_zone(struct student* p);//统计不同分数区域学生人数
struct student* search(struct student* head);//通过姓名或学号查找某个学生信息,返回指向该学生指针
void sort(struct student* head);//显示成绩排名
void revise(struct student* p);//选择修改或添加学生信息
void reinput(struct student* p);//修改信息
void upfile(struct student* p);//更新文件
void back_menu(struct student* p);//返回初始菜单
struct student
{
long ID;
char name[20];
char sex[20];
double score[N];
struct student* next;
};
//主函数部分
创建头结点,调用list_initi()读取文件内容储存到链表中,调用menu()菜单供用户进行功能选择。当menu()函数执行完即用户选择退出后,选择是否更新文件,调用upfile()来新建文件覆盖原文件。
int main(void)
{
char ch;
struct student* head = (struct student*)malloc(sizeof(struct student));//头结点
head->next = NULL;
list_initi(head);
menu(head);
printf("是否更新文件?Y/N\n");
getchar();
scanf_s("%c", &ch, 1);
if (ch == 'y' || ch == 'Y')
upfile(head);
return 0;
}
//读取文件,链表初始化
while (fgets(line, sizeof(line), fpRow))用于计算文件行数,防止读入空行产生无效节点。
while (!feof(fp) && j < row)循环,一边创建链表节点,一边将读出的值赋给节点
void list_initi(struct student* head)//链表初始化
{
FILE* fpRow;
fopen_s(&fpRow, "1班学生成绩信息.txt", "r+");
char line[1024];
int row = 0; //行数
while (fgets(line, sizeof(line), fpRow))
{
if (line[0] == '\n' || line[0] == '\r') // 判断空行
{
break; // 跳出
}
else
{
row++;
}
}
fclose(fpRow);
int j = 0;
int i;
FILE* fp;
fopen_s(&fp, "1班学生成绩信息.txt", "r+");
struct student* p = head;
if (fgetc(fp) != EOF)
{
rewind(fp);
while (!feof(fp) && j < row)
{
struct student* q = (struct student*)malloc(sizeof(struct student));//构建新节点存放下一个学生信息
fscanf_s(fp, "%s", &q->name, 20);
fscanf_s(fp, "%d", &q->ID);
fscanf_s(fp, "%s", &q->sex, 20);
for (i = 0; i < N; i++)
{
fscanf_s(fp, "%lf", &q->score[i]);
}
p->next = q;//原p指向新节点
q->next = NULL;
p = q;//q代替原p成为链表尾部
j++;
}
}
fclose(fp);
}
//调用主菜单
用switch跳转到对应功能模块
void menu(struct student* head)//主菜单
{
struct student* temp = NULL;
system("cls");
int cho, stu_num = 0;
printf("-------------------------------------------------------------\n");
printf("\t\t1.录入学生信息\n\n");
printf("\t\t2.显示全部学生各科成绩\n\n");
printf("\t\t3.各科成绩统计分析\n\n")</