学生管理系统代码
好好看,好好学,知识点的部分看不懂就多查。
内容很多,仔细看。
c
#include <stdio.h>
#include <stdlib.h>
#define M 100
#define N 10
//定义学生相关信息结构体
typedef struct stu
{
char sn[13];
char name[9];
char sex;
float corse[N];
} stu;
//知识点:函数声明的使用情况:自主创建(定义)的函数在主函数后面的时候,需要在主函数前面声明;如果是在主函数前面的话,不需要声明。了解一下C语言的是如何扫描和编译代码的
//数据初略分析函数
int maxs(stu a[], int n, int ii);
int mins(stu a[], int n, int ii);
float ave(stu a[], int n, int ii);
int sum(stu a[], int n, int ii);
void sorts(stu a[], int n, int ii); //从小到大排序,采用的是选择排序
//学生数据分析(新增)
void total_scores(stu a[], int n, float* total);
float max_student_score(float total[], int n);
float min_student_score(float total[], int n);
float average_student_score(float total[], int n);
//整体的插入与删除
void outdata(stu a[], int n);
stu indata(stu a[], int n);
int inalldata(stu a[]);
//数据的插入,删除,统计,查找
void counts(stu a[], int n, int m[], int ii);
int ins(stu a[], int n, int pos, stu x);
int del(stu a[], int n, int pos);
int lookfor(stu a[], int n, int x, int ii);
//文件的打开与修改
int opendata(stu a[]);
int writedata(stu a[], int n);
int dataflag; //是否有数据
int fileflag; //数据改动过
int main()
{
//知识点:stu是结构体的变量名,类似于int的使用方式,注意有typeof和没有的区别,顺便理解一下typeof的作用
stu a[M];
int n;
//代码规范:赋值等号左右留空格
n = interface(a); //进入46行
//代码规范:逗号后面加空格
seebye(a, n);
return 0;
}
//主要的功能区,所有的功能实现都是靠这个函数调用
int interface(stu a[])
{
stu s; //s是student
int m[5], n, ii; //m数组用来统计班级优良情况,n是总人数,ii是科目
int sel, pos, sn; //sel是select,sn是按科目分数查找的学生的序号,pos是用于删除数据和插入数据时指明位置的变量
int x, t; //x是对应的查找函数时,输入的科目分数,t是排序是承接学生信息的暂时变量
int maxdata, mindata, sumdata;
float avedata;
float total[M] = { 0 };
char ch;
//代码规范:赋值等号左右留空格
dataflag = 0;
//代码规范:赋值等号左右留空格
fileflag = 0;
do
{
//代码规范:赋值等号左右留空格
sel = menu(); //进入menu函数,输出菜单
if (sel == 1 || sel == 2 || sel == 3 || sel == 4 || sel == 5 || sel == 8 || sel == 11)
{
ls:
printf("\n请选择一门课程\n");
printf("-------------\n");
printf(" 1: 数学\n 2:物理\n 3: 英语\n 4: 思政\n 5: 编程\n");
printf("-------------");
printf("\n选择哪一门课程:");
scanf("%d", &ii);
if (ii < 1 || ii>5)
{
printf("课程号错误,请重新输入!\n");
goto ls;
}
printf("\n");
}
//知识点:用过C语言代码做到对文件的修改
if (sel == 0)
{
//代码技巧:通过这种变量传承的方式,判断是否执行(这个地方的传参往往就是代表true,false,用变量来承接的话,更加可控
if (fileflag)
{
printf("文件改动过,还没保存,需要保存吗?\n回答Y或者y: ");
fflush(stdin);
scanf("%c", &ch);
//知识点:writedata()修改文件内容,和python里面的write函数,但是在C语言里面的自己写函数才能达到更好的效果
if (ch == 'Y' || ch == 'y') writedata(a, n);//跳转到291行
}
break;
}
else if (sel == 1)
{
maxdata = maxs(a, n, ii - 1); //跳转到maxs函数,输出该科目的最大值
printf("最大数:%d\n", maxdata);
}
else if (sel == 2)
{
mindata = mins(a, n, ii - 1); //跳转到mins函数,输出该科目的最小值
printf("最小数:%d\n", mindata);
}
else if (sel == 3)
{
avedata = ave(a, n, ii - 1); //跳转到ave函数,输出该科目的平均值
printf("平均数:%.2f\n", avedata);
}
else if (sel == 4)
{
sumdata = sum(a, n, ii - 1); //跳转到sum函数,输出该科目的总共分数
printf("总和:%d\n", sumdata);
}
else if (sel == 5) //对数据排序
{
sorts(a, n, ii - 1); //跳转到sorts函数,从小到大排序该科目的分数
outdata(a, n);
}
else if (sel == 6)
{
outdata(a, n); //输出数据
}
else if (sel == 7)
{
n = inalldata(a); //创建班级数据
outdata(a, n);
}
else if (sel == 8)
{
counts(a, n, m, ii - 1); //返回一个数组,统计学习情况,跳转到479行
printf("-----------------\n");
printf(" 优秀人数: %d\n 良好人数: %d\n 一般人数: %d\n 及格人数: %d\n 不及格数: %d\n", m[0], m[1], m[2], m[3], m[4]);
printf("-----------------\n");
}
else if (sel == 9) //插入数据
{
l2:
if (n >= M)
printf("\n成绩表已满,不能再插入了!");
else
{
printf("请输入要插入的位置:");
scanf("%d", &pos);
if (pos < 1 || pos > n)
{
printf("位置输入有错,请重新输入!");
goto l2;
}
l5:
printf("请输入要插入的值:");
s = indata(a, n); //通过indata函数创建要插入的数据
n = ins(a, n, pos, s); //插入数据,跳转到
printf("插入结果:");
outdata(a, n);
}
}
else if (sel == 10)
{
l3:
printf("请输入要删除的位置:");
scanf("%d", &pos);
if (pos < 1 || pos > n)
{
printf("位置输入有错,请重新输入!");
goto l3;
}
n = del(a, n, pos); //删除元素,返回删除后班级人数的长度
if (n == 0)
{
printf("\n成绩表被清空!");
dataflag = 0;
}
else
{
printf("删除结果:");
outdata(a, n);
}
}
else if (sel == 11)
{
l4:
printf("请输入要查找的值:");
scanf("%d", &x);
if (x < 0 || x > 100)
{
printf("输入值有错,请重新输入!\n");
goto l4;
}
sn = lookfor(a, n, x, ii - 1); //查找逻辑是按照课程的分数来找到对应的人的序号
if (sn == 0) printf("要查找的数据不存在!\n");
else printf("该数据序号为%d\n", sn);
}
else if (sel == 12)
{
l6:
n = opendata(a);
if (n == 0)
{
printf("文件不存在,请创建数据!\n");
goto l6;
}
else
outdata(a, n);
dataflag = 1;
}
else if (sel == 13)
{
writedata(a, n);
printf("数据保存成功!\n");
}
else if (sel == 14)
{
total_scores(a, n, total);
float max_score = max_student_score(total, n);
float min_score = min_student_score(total, n);
float avg_score = average_student_score(total, n);
printf("最高分数:%.2f\n", max_score);
printf("最低分数:%.2f\n", min_score);
printf("平均分数:%.2f\n", avg_score);
}
printf("\n按任意键继续!");
fflush(stdin);
getchar();
} while (1);
return n;
}
//页面显示的菜单栏部分
int menu()
{
int dd; //用于承接 输入选择菜单栏的数字
printf("\n\n 班级成绩管理系统");
while (1)
{
ll2:
system("cls");
printf("\n 功能选择\n");
printf(" ---------------\n");
printf(" | 1 求最大数 |\n");
printf(" | 2 求最小数 |\n");
printf(" | 3 求平均数 |\n");
printf(" | 4 数据求和 |\n");
printf(" | 5 数据排序 |\n");
printf(" | 6 输出数据 |\n");
printf(" | 7 创建数据 |\n");
printf(" | 8 统计数据 |\n");
printf(" | 9 插入数据 |\n");
printf(" | 10 删除数据 |\n");
printf(" | 11 查找数据 |\n");
printf(" | 12 获取数据 |\n");
printf(" | 13 保存数据 |\n");
printf(" | 14 学生数据 |\n");
printf(" | 0 退出系统 |\n");
printf(" ---------------\n");
printf(" 请选择一个功能:");
scanf("%d", &dd);
//代码规范:在if条件语句里面,每个符号中间都要留空格
if (dd < 0 || dd > 15)
{
printf("\n选择有错,请重新选择!\n");
printf("\n按任意键继续!");
//代码解释:清楚缓冲区(缓冲区称为stdin),也就是所谓的清缓存
fflush(stdin);
//代码技巧:这里用的getchar()会自动给到dd变量,至于为什么可以百度(核心在于getchar函数返回的是int型变量),然后继续做while循环
getchar();
}
else if (dd == 0 || dd == 7 || dd == 12 || dataflag == 1) break;
else
{
printf("\n无数据,请选择创建数据!");
printf("\n按任意键继续!");
fflush(stdin);
getchar();
}
}
return dd;
}
// 打开文件
int opendata(stu a[])
{
FILE* fp;
int n = 0;
fp = fopen("score.dat", "rb");
if (!fp) return 0;
fseek(fp, 0, SEEK_END);
n = ftell(fp) / sizeof(struct stu);
fseek(fp, 0, SEEK_SET);
fread(a, sizeof(stu), n, fp);
fclose(fp);
dataflag = 1;
return n;
}
// 纯纯的对文件的操作,看不懂就百度吧,我也没怎么学过
int writedata(stu a[], int n)
{
FILE* fp;
fp = fopen("score.dat", "wb+");
if (!fp) return 0;
fwrite(a, sizeof(stu), n, fp);
fclose(fp);
fileflag = 0;
return 1;
}
//求最大值函数,就是遍历数组,然后去最大值就好了,没什么技术含量
int maxs(stu a[], int n, int ii)
{
int i;
int max;
//注意代码规范
max = a[0].corse[ii];
for (i = 1; i < n; i++)
if (a[i].corse[ii] > max)
max = a[i].corse[ii];
return max;
}
//求最小值函数
int mins(stu a[], int n, int ii)
{
int i;
//注意代码规范和命名,直接语义化命名是最好的
int min;
min = a[0].corse[ii];
for (i = 1; i < n; i++)
if (a[i].corse[ii] < min)
min = a[i].corse[ii];
return min;
}
//求平均值函数
float ave(stu a[], int n, int ii)
{
int i;
int aveg;
aveg = 0;
for (i = 1; i < n; i++)
aveg = aveg + a[i].corse[ii];
return aveg / (float)n;
}
//求和函数
int sum(stu a[], int n, int ii)
{
int i;
int sum;
sum = 0;
for (i = 1; i < n; i++)
sum = sum + a[i].corse[ii];
return sum;
}
//排序函数,采用的是选择排序,还有很多排序方法,你们搞数据的,排序的算法估计得了如指掌
void sorts(stu a[], int n, int ii)
{
int i, j, k;
int m;
stu t;
for (i = 0; i < n; i++)
{
k = i;
m = a[i].corse[ii];
for (j = i + 1; j < n; j++)
{
if (m < a[j].corse[ii])
{
k = j;
m = a[j].corse[ii];
}
}
t = a[i];
a[i] = a[k];
a[k] = t;
}
fileflag = 1;
}
//输出修改的数据
void outdata(stu a[], int n)
{
int i;
printf("\n 数据显示!\n");
printf("%10s%10s%6s%6s%6s%6s%6s%6s\n", "姓名", "学号", "性别", "数学", "物理", "英语", "思政", "编程");
for (i = 0; i < 30; i++) printf("---");
printf("\n");
for (i = 0; i < n; i++)
if (a[i].sex == '1')
printf("%10s%10s%6s%6.1f%6.1f%6.1f%6.1f%6.1f\n", a[i].name, a[i].sn, "男 ", a[i].corse[0], a[i].corse[1], a[i].corse[2], a[i].corse[3], a[i].corse[4]);
else
printf("%10s%10s%6s%6.1f%6.1f%6.1f%6.1f%6.1f\n", a[i].name, a[i].sn, "女 ", a[i].corse[0], a[i].corse[1], a[i].corse[2], a[i].corse[3], a[i].corse[4]);
for (i = 0; i < 30; i++) printf("---");
printf("\n");
}
// 个人信息的输入,包括姓名,学号,性别,学科成绩
stu indata(stu a[], int n)
{
stu s;
printf("\n姓名:");
fflush(stdin);
scanf("%s", s.name);
printf("学号:");
fflush(stdin);
scanf("%s", s.sn);
le1:
printf("性别:(1:男,2:女)");
fflush(stdin);
scanf("%c", &s.sex);
if (s.sex != '1' && s.sex != '2')
{
printf("输入有错,请输入1或者2\n");
//知识点:goto语句是为了方便编译器执行的跳转,是一种避免异常的一种有效方式,避免运用大量的循环造成代码运行时间的增多(你明年学了数据结构就会懂)类似python里面的try语句
goto le1;
}
le2:
printf("数学:");
fflush(stdin);
scanf("%f", &s.corse[0]);
if (s.corse[0] < 0 || s.corse[0] > 100)
{
printf("输入有错!重新输入!\n");
goto le2;
}
le3:
printf("物理:");
fflush(stdin);
scanf("%f", &s.corse[1]);
if (s.corse[1] < 0 || s.corse[1] > 100)
{
printf("输入有错!重新输入!\n");
goto le3;
}
le4:
printf("英语:");
fflush(stdin);
scanf("%f", &s.corse[2]);
if (s.corse[2] < 0 || s.corse[2] > 100)
{
printf("输入有错!重新输入!\n");
goto le4;
}
le5:
printf("思政:");
fflush(stdin);
scanf("%f", &s.corse[3]);
if (s.corse[3] < 0 || s.corse[3] > 100)
{
printf("输入有错!重新输入!\n");
goto le5;
}
le6:
printf("编程:");
fflush(stdin);
scanf("%f", &s.corse[4]);
if (s.corse[4] < 0 || s.corse[4] > 100)
{
printf("输入有错!重新输入!\n");
goto le6;
}
fileflag = 1;
dataflag = 1;
return s;
}
//班级整体人数的输入
int inalldata(stu a[])
{
int n, i;
stu s;
printf("班级数据输入!\n");
l1:
printf("请输入班级人数:");
scanf("%d", &n);
//在做项目的时候,学会加入这种输入值的判断,这样会提升代码的复用性(也就是你的代码别人可以轻松使用)
if (n < 2 || n > M)
{
printf("输入有错,请重新输入!");
goto l1;
}
for (i = 0; i < n; i++)
{
printf("\n学生%d数据输入!", i + 1);
s = indata(a, n);//进行对每个学生的具体信息输入
a[i] = s;
}
fileflag = 1;
dataflag = 1;
return n;
}
//班级分数优良差统计
void counts(stu a[], int n, int m[], int ii)
{
int i;
//初始化数组列表,让其元素为0,这里不使用m[n] = {0},是因为这个方法必须是在定义 m 数组的时候使用,而不是后期赋值的时候使用。
for (i = 0; i < 5; i++)
m[i] = 0;
//遍历班级学生分数情况,统计
for (i = 0; i < n; i++)
{
if (a[i].corse[ii] >= 90 && a[i].corse[ii] <= 100) m[0]++;
else if (a[i].corse[ii] >= 80 && a[i].corse[ii] < 90) m[1]++;
else if (a[i].corse[ii] >= 70 && a[i].corse[ii] < 80) m[2]++;
else if (a[i].corse[ii] >= 60 && a[i].corse[ii] < 70) m[3]++;
else if (a[i].corse[ii] >= 0 && a[i].corse[ii] < 60) m[4]++;
}
}
//指定位置插入元素数据。这个地方好好想想,以后在数据机构里面很常见
int ins(stu a[], int n, int pos, stu x)
{
int i;
//代码解释:将pos后面的元素全部后移一个单位,此时pos位为空
for (i = n - 1; i >= pos; i--)
a[i + 1] = a[i];
//将x(新建立的数据)插入pos位置
a[pos] = x;
fileflag = 1;
//细节:插入元素后,数组长度会增 1
return n + 1;
}
//删除元素,和上面的插入一样,只不过是反的而已,好好想一下,数据结构里面经常见到这两种操作
int del(stu a[], int n, int pos)
{
int i;
for (i = pos - 1; i < n; i++)
a[i] = a[i + 1];
fileflag = 1;
return n - 1;
}
//根据学科分数查找学生的序号
int lookfor(stu a[], int n, int x, int ii)
{
int i, flag;
flag = 0;
for (i = 0; i < n; i++)
{
if (a[i].corse[ii] == x)
{
flag = 1;
break;
}
}
if (flag) return i + 1;
else return 0;
}
//退出程序
void seebye(stu a[], int n)
{
if (n == 0)
printf("\n无数据!\n");
else
outdata(a, n);
printf("\n\n\n谢谢使用,再见!\n\n\n\n");
fflush(stdin);
getchar();
}
// 实现新函数
//统计一个学生的所有分数
void total_scores(stu a[], int n, float* total)
{
for (int i = 0; i < n; i++)
{
float sum = 0;
for (int j = 0; j < N; j++)
{
sum += a[i].corse[j];
}
total[i] = sum;
}
}
//下面的三个函数,都是通过循环遍历得到的,也称为迭代
//找寻所有学生当中分最高的
float max_student_score(float total[], int n)
{
float max = total[0];
for (int i = 1; i < n; i++)
{
if (total[i] > max)
{
max = total[i];
}
}
return max;
}
//找寻所有学生当中分最低的
float min_student_score(float total[], int n)
{
float min = total[0];
for (int i = 1; i < n; i++)
{
if (total[i] < min)
{
min = total[i];
}
}
return min;
}
//求整体学生的平均分
float average_student_score(float total[], int n)
{
float sum = 0;
for (int i = 0; i < n; i++)
{
sum += total[i];
}
return sum / n;
}
//学会代码规范
// 像"< > ? / \ || && "这种符号之间,两边放入变量的时候,打空格;
// 对于定义变量的时候,逗号和变量之间打空格,int i, j, k;
// 变量的命名最好采用语义化命名,比如 学生------stu 这种的;
// 不要写成代码shi山,读起来很痛苦
看完了之后是不是不那么的凯凯心心了😂😂😂
学代码是这样的,努力看吧❤️