C语言实现成绩管理系统

Student.h

#pragma once

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>

#define DEFAULT_SIZE 3 // list默认大小
#define INCREASE_SIZE 2 // 每次扩容的大小

typedef struct Student{
	char student_id[20];// 学号
	char name[20];// 姓名
	int grade;// 年级
	int class_num;// 班级
	float score;// 成绩
}Student;

typedef struct Stulist
{
	Student* data;// Student结构体,等价于静态的数组
	int count;// 当前成绩管理系统中人数

	int capacity;// 当前成绩管理系统的容量
}Stulist;

Stulist list;

//初始化成绩管理系统
int InitStulist(Stulist* p);
//销毁成绩管理系统
void DestroyStulist(Stulist* p);

// FindByStudent_id
// 信息添加(学号、姓名、年级、班级、成绩)
void Add_students(Stulist* p);
// 信息查看(输入学号查看该学生的信息)
void Display_student(Stulist* p);
// 成绩修改(输入学号,可以看到当前成绩,并修改)
void Modify_score(Stulist* p);

// 班级成绩统计(指定班级的平均成绩、最高分、最低分、及格率)
void Class_statistics(Stulist* p);
// 年级成绩统计(指定年级的平均成绩、最高分、最低分、及格率)
void Grade_statistics(Stulist* p);

// 成绩排序
void ScoreSort(Stulist* p);
// 打印所有学生的信息
void Display_students(Stulist* p);

// 保存list中信息到本地文件
void Save_data(const Stulist* p);
// 加载本地文件中信息到list
void Load_data(Stulist* p);

Student.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Student.h"

void UpCapacity(Stulist* p)
{
	if (p->count == p->capacity)// 数据量等于list容量
	{
		Student* ptr = (Student*)realloc(p->data, (p->capacity + INCREASE_SIZE) * sizeof(Student));
		//要扩容空间的起始地址,(当前容量大小+要扩容的大小)*该类型的字节大小
		if (ptr == NULL)// 扩容失败
		{
			printf("UpCapacity:%s\n", strerror(errno));
			return;
		}
		else
		{
			p->data = ptr;
			p->capacity += INCREASE_SIZE;
			printf("增容成功!!!\n");
		}
	}
}

// 加载本地文件中信息到list
void Load_data(Stulist* p)
{
	// 创建文件指针(以二进制的形式读)
	FILE* pfRead = fopen("Studentlist.txt", "rb");
	if (pfRead == NULL)// 找不到文件
	{
		perror("Load_data");// 打印错误信息
		return;
	}
	Student tmp = { 0 };

	// 读文件,文件中的数据大于3(考虑扩容)
	while (fread(&tmp, sizeof(Student), 1,pfRead) == 1)// fread返回成功读取的个数
	{
		UpCapacity(p);// 扩容
		p->data[p->count] = tmp;
		p->count++;
	}
	// 关闭文件
	fclose(pfRead);
	pfRead = NULL;
}

int InitStulist(Stulist* p)
{
	assert(p);
	p->data =(Student*) calloc(DEFAULT_SIZE, sizeof(Student));// 第一次calloc=malloc+memset
	if (p->data == NULL)// 申请空间失败
	{
		printf("InitStulist fail\n");
		return -1;
	}
	p->count = 0;
	p->capacity = DEFAULT_SIZE;
	// 加载文件中的信息到list
	Load_data(p);
	return 0;
}


void DestroyStulist(Stulist* p)
{
	assert(p);
	free(p->data);
	p->data = NULL;
}

// 通过学号查找该学生是否已经存在
int FindByStudent_id(Stulist* p, char student_id[])
{
	assert(p);
	// 遍历
	for (int i = 0; i < p->count; i++)
	{
		if (0 == strcmp(p->data[i].student_id, student_id))
		{
			return i;// 找到返回数据的下标
		}
	}
	return -1;
}

// 信息添加(学号、姓名、年级、班级、成绩)
void Add_students(Stulist* p)
{
	assert(p);
	UpCapacity(p);
	printf("请输入学号:>");
	scanf("%s", p->data[p->count].student_id);
	int ret = FindByStudent_id(p, p->data[p->count].student_id);
	if (ret!=-1)
	{
		printf("该学生已存在,请重新操作\n");
		return;
	}
	printf("请输入姓名:>");
	scanf("%s", p->data[p->count].name);
	printf("请输入年级:>");
	scanf("%d", &p->data[p->count].grade);
	printf("请输入班级:>");
	scanf("%d", &p->data[p->count].class_num);
	printf("请输入成绩:>");
	scanf("%f", &p->data[p->count].score);

	p->count++;
	printf("添加成功\n");
}

// 信息查看(输入学号查看该学生的信息:学号、姓名、年级、班级、成绩)
void Display_student(Stulist* p)
{
	assert(p);
	char student_id[20] = { 0 };

	printf("请输入学号:>");
	scanf("%s", student_id);
	int ret = FindByStudent_id(p, student_id);
	if (ret == -1)
	{
		printf("要查找的学生不存在\n");
		return;
	}
	printf("%-20s\t%-20s\t%-5s\t%-5s\t%6s\n",
		"学号", "姓名", "年级", "班级", "成绩");

	printf("%-20s\t%-20s\t%-5d\t%-5d\t%-6.2f\n",
		p->data[ret].student_id,
		p->data[ret].name,
		p->data[ret].grade,
		p->data[ret].class_num,
		p->data[ret].score);
}
// 成绩修改(输入学号,可以看到当前成绩,并修改)
void Modify_score(Stulist* p)
{
	assert(p);
	char student_id[20] = { 0 };

	printf("请输入学号:>");
	scanf("%s", student_id);
	int ret = FindByStudent_id(p, student_id);
	if (ret == -1)
	{
		printf("要修改的学生不存在\n");
		return;
	}
	printf("该学生当前成绩为:>%.2f\n", p->data[ret].score);
	printf("请输入要修改的目标成绩:>");
	scanf("%f", &p->data[ret].score);
}

// 班级成绩统计(指定班级的平均成绩、最高分、最低分、及格率)
void Class_statistics(Stulist* p)
{
	assert(p);
	int class_num;// 班级
	float total_score = 0, max_score = 0, min_score = 200;// 总分,最高分,最低分
	int pass_cnt = 0;// 及格人数,默认>=90及格
	printf("请输入班级:>");
	scanf("%d", &class_num);
	// 遍历
	for (int i = 0; i < p->count; i++)
	{
		if (p->data[i].class_num == class_num)// 按班级找
		{
			total_score += p->data[i].score;
			if (p->data[i].score > max_score)// 最高分
			{
				max_score = p->data[i].score;
			}
			if (p->data[i].score < min_score)// 最低分
			{
				min_score = p->data[i].score;
			}
			if (p->data[i].score >= 90)// 及格人数
			{
				pass_cnt++;
			}
		}
	}
	float average_score = total_score / p->count;
	float pass_rate = (float)pass_cnt / p->count;
	printf("%-5s\t%-9s\t%-7s\t%-7s\t%-7s\n",
		"班级", "平均成绩", "最高分", "最低分", "及格率");// %% -> %
	printf("%-2d\t%-6.2f\t%-6.2f\t%-6.2f\t%-5.2f%%\n",
		class_num, average_score, max_score, min_score, pass_rate);
}
// 年级成绩统计(指定年级的平均成绩、最高分、最低分、及格率)
void Grade_statistics(Stulist* p)
{
	assert(p);
	int grade;// 年级
	float total_score = 0, max_score = 0, min_score = 200;// 总分,最高分,最低分
	int pass_cnt = 0;// 及格人数,默认>=90及格
	printf("请输入年级:>");
	scanf("%d", &grade);
	// 遍历
	for (int i = 0; i < p->count; i++)
	{
		if (p->data[i].grade == grade)// 按年级找
		{
			total_score += p->data[i].score;
			if (p->data[i].score > max_score)// 最高分
			{
				max_score = p->data[i].score;
			}
			if (p->data[i].score < min_score)// 最低分
			{
				min_score = p->data[i].score;
			}
			if (p->data[i].score >= 90)// 及格人数
			{
				pass_cnt++;
			}
		}
	}
	float average_score = total_score / p->count;
	float pass_rate = (float)pass_cnt / p->count;
	printf("%-5s\t%-9s\t%-7s\t%-7s\t%-7s\n",
		"年级", "平均成绩", "最高分", "最低分", "及格率");// %% -> %
	printf("%-2d\t%-6.2f\t%-6.2f\t%-6.2f\t%-5.2f%%\n",
		grade, average_score, max_score, min_score, pass_rate);
}

int cmp_score(const void* e1, const void* e2)
{
	return ((*(Student*)e2).score - (*(Student*)e1).score);
}
 //成绩排序
void ScoreSort(Stulist* p)
{
	assert(p);
	qsort(p->data, p->count, sizeof(Student), cmp_score);
	printf("排序成功\n");
}
// 打印所有学生的信息
void Display_students(Stulist* p)
{
	assert(p);
	ScoreSort(p);
	printf("%-20s\t%-20s\t%-5s\t%-5s\t%6s\n",
		"学号", "姓名", "年级", "班级", "成绩");
	for (int i = 0; i < p->count; i++)
	{
		printf("%-20s\t%-20s\t%-5d\t%-5d\t%-6.2f\n",
			p->data[i].student_id,
			p->data[i].name,
			p->data[i].grade,
			p->data[i].class_num,
			p->data[i].score);
	}
}

// 保存list中信息到本地文件
void Save_data(const Stulist* p)
{
	assert(p);
	// 创建文件指针
	FILE* pfWrite = fopen("Studentlist.txt", "wb");
	if (pfWrite == NULL)
	{
		perror("Load_data");// 打印错误信息
		return;
	}
	// 写文件
	for (int i = 0; i < p->count; i++)
	{
		fwrite(p->data + i, sizeof(Student), 1, pfWrite);
	}
	// 关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "Student.h"


enum option//枚举
{
	Exit,
	Display,
	Add,
	Modify,
	Sort,
	Class_statistic,
	Grade_statistic
};
void menu()
{
	printf("*************************    MENU   ************************\n");
	printf("**********      1.成绩查看        2.成绩录入      **********\n");
	printf("**********      3.成绩修改        4.成绩排序      **********\n");
	printf("**********      5.班级成绩统计    6.年级成绩统计  **********\n");
	printf("**********      0.退出                            **********\n");
	printf("************************************************************\n");
}
void switch_case1(int input)// 管理员
{
	switch (input)
	{
	case Display:
	case Add:
	case Modify:
		printf("无权限使用此功能,请重新选择\n");
		break;
	case Sort:
		Display_students(&list);
		break;
	case Class_statistic:
		Class_statistics(&list);
		break;
	case Grade_statistic:
		Grade_statistics(&list);
		break;
	case Exit:
		printf("已退出学生成绩管理系统\n");
		break;
	default:
		printf("选择错误,请重新选择\n");
		break;
	}

}
void switch_case2(int input)// 普通用户
{
	switch (input)
	{
	case Display:
		Display_student(&list);
		break;
	case Add:
		Add_students(&list);
		break;
	case Modify:
		Modify_score(&list);
		printf("修改成功\n");
		break;
	case Sort:
	case Class_statistic:
	case Grade_statistic:
		printf("无权限使用此功能,请重新选择\n");
		break;
	case Exit:
		Save_data(&list);
		DestroyStulist(&list);
		printf("已退出学生成绩管理系统\n");
		break;
	default:
		printf("选择错误,请重新选择\n");
		break;
	}
}

int login()
{
	int flag = 0;
	int N = 3,cnt=0;// 可输入密码的次数,匹配次数
	char username[20];
	char password[20];

	printf("********************   学生信息管理系统   *******************\n");
	printf("请输入用户名和密码:>\n");

	while (N--)// 先while(N),再N--,
	{
		printf("username:>");
		scanf("%s", username);

		printf("password:>");
		scanf("%s", password);
		if (strcmp(username, "admin") == 0 && strcmp(password,"12345")==0)// 管理员
		{
			printf("登录成功(管理员)\n");
			flag = 1;
			cnt++;
			break;
		}
		else if(strcmp(password, "12345")==0)// 普通用户
		{
			printf("登录成功(普通用户)\n");
			flag = 0;
			cnt++;
			break;
		}
		if (N >= 1)
		{
			printf("用户名和密码错误,请重新输入\n");
			//printf("%d", N);
		}
		else
			printf("用户名和密码错误\n");
	}
	if (cnt == 0)
		flag = -1;
	return flag;
}
int main()
{
	int input;

	InitStulist(&list);

	int ret = login();// 登录

	if (ret == 1)// 管理员
	{
		do
		{
			menu();
			printf("请选择:>");
			scanf("%d", &input);

			switch_case1(input);
		} while (input);
	}
	else if(ret == 0)// 普通用户
	{
		do
		{
			menu();
			printf("请选择:>");
			scanf("%d", &input);

			switch_case2(input);
		} while (input);
	}
	else
	{
		printf("登录失败,请稍后重试\n");
	}

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值