#include#include#include#include
#define STDIN_FILENO 0
#define MAX_LEN 8
#define BACKSPACE 8
#define ENTER 13
#define ALARM 7
#define DATA_FILE "./data.txt"
#define USERNAME "root"
#define PASSWD "root"
/**
* 学生结构体
**/typedefstruct{char no[7];char name[9];chargender;float scores[3];floattotal_score;floatavg_score;
} Student;
Student*stulist; //所有学生列表
int stunum; //学生数量
char *stuproperty[7] ={"不指定","学号","姓名","性别","课程1","课程2","课程3"};/**
* 密码输出星号函数
**/
intgetch() {structtermios tm, tm_old;int fd =STDIN_FILENO, c;if (tcgetattr(fd, &tm) < 0) return -1;
tm_old=tm;
cfmakeraw(&tm);if(tcsetattr(fd, TCSANOW, &tm) < 0) return -1;
c=fgetc(stdin);if(tcsetattr(fd, TCSANOW, &tm_old) < 0) return -1;returnc;
}char *getpwd(const char *prompt)
{int i=0, ch;static char p[MAX_LEN+1]="";
printf("%s", prompt);while((ch = getch())!= -1 && ch !=ENTER)
{if(i == MAX_LEN && ch !=BACKSPACE)
{
putchar(ALARM);continue;
}if(ch ==BACKSPACE)
{if(i==0)
{
putchar(ALARM);continue;
}
i--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
}else{
p[i]=ch;
putchar('*');
i++;
}
}if(ch == -1)
{while(i != -1)
{
p[i--] = '\0';
}returnNULL;
}
p[i]='\0';
printf("\n");returnp;
}/**
* 登录验证
**/
voidvalidate() {char *username = (char *) malloc(sizeof(char) * 8);
printf("\n\t请输入用户名:");
scanf("%s", username);
getchar();char *passwd = getpwd("\n\t请输入密码:");if (strcmp(username, USERNAME) != 0 || strcmp(passwd, PASSWD) != 0) {
printf("\n\t用户名或密码错误,程序即将退出\n");
getchar();
exit(0);
}
}/**
* 交换函数
**/
void swap(Student *stulist, int i, intj) {
Student stutemp=stulist[i];
stulist[i]=stulist[j];
stulist[j]=stutemp;
}/**
* 字符串重复函数
**/
char *strrep(char c, intn) {char *str = (char *) malloc(sizeof(c) * n + 1);inti;for (i = 0; i < n; i++) {*str++ =c;
}*str = '\0';
str-=n;returnstr;
}/**
* 结果输出函数
**/
void print_result(Student *stulist, intstunum) {inti;float sum[3] = {0};float avg[3] = {0};float max[3] = {0};float min[3] ={
stunum> 0 ? stulist[0].scores[0] : 0,
stunum> 0 ? stulist[0].scores[1] : 0,
stunum> 0 ? stulist[0].scores[2] : 0,
};
printf("\n\t位置\t学号\t姓名\t性别\t课程1\t课程2\t课程3\t总分\t平均分\n\n");for (i = 0; i < stunum; i++) {
Student*s = &stulist[i];
printf("\t%d\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", i, s->no, s->name, s->gender == '1' ? "男" : "女", s->scores[0], s->scores[1], s->scores[2], s->total_score, s->avg_score);
sum[0] += s->scores[0];
sum[1] += s->scores[1];
sum[2] += s->scores[2];
avg[0] = sum[0] /stunum;
avg[1] = sum[1] /stunum;
avg[2] = sum[2] /stunum;
max[0] = s->scores[0] > max[0] ? s->scores[0] : max[0];
max[1] = s->scores[1] > max[1] ? s->scores[1] : max[1];
max[2] = s->scores[2] > max[2] ? s->scores[2] : max[2];
min[0] = s->scores[0] < min[0] ? s->scores[0] : min[0];
min[1] = s->scores[1] < min[1] ? s->scores[1] : min[1];
min[2] = s->scores[2] < min[2] ? s->scores[2] : min[2];
}//输出各科目成绩统计
printf("\n\t\t最高分\t最低分\t总分\t平均分");
printf("\n\t课程1\t%.1f\t%.1f\t%.1f\t%.f", max[0], min[0], sum[0], avg[0]);
printf("\n\t课程2\t%.1f\t%.1f\t%.1f\t%.f", max[1], min[1], sum[1], avg[1]);
printf("\n\t课程3\t%.1f\t%.1f\t%.1f\t%.f\n", max[2], min[2], sum[2], avg[2]);
}/**
* 插入学生记录
**/
voidadd_stu() {
Student stu;intno;
printf("\n\t请输入插入的位置:");
scanf("%d", &no);
printf("\n\t请输入学号:");
scanf("%s", stu.no);
printf("\n\t请输入姓名:");
scanf("%s", stu.name);
printf("\n\t请输入性别(1男2女):");
getchar();
scanf("%c", &stu.gender);
printf("\n\t请输入课程1成绩:");
scanf("%f", &stu.scores[0]);
printf("\n\t请输入课程2成绩:");
scanf("%f", &stu.scores[1]);
printf("\n\t请输入课程3成绩:");
scanf("%f", &stu.scores[2]);
Student*s = &stu;
stu.total_score= stu.scores[0] + stu.scores[1] + stu.scores[2];
stu.avg_score= stu.total_score / 3;if (stulist ==NULL) {
stulist= (Student *) malloc(sizeof(Student));
}else{
stulist= (Student *) realloc(stulist, sizeof(Student) * (stunum + 1));
}//插入指定编号位置
if (no >= 0 && no
memmove(&stulist[no + 1], &stulist[no], (stunum - no) * sizeof(Student));
}else{//插到末尾
no =stunum;
}
memcpy(&stulist[no], &stu, sizeof(Student));
stunum++;
}/**
* 查询学生
**/
voidquery_stu() {//输出查询菜单
inti;for (i = 0; i < 7; i++) {
printf("\n\t%d.%s", i + 1, stuproperty[i]);
}
printf("\n\n\t请输入查询条件编号:");intchoice;floatlow;floathigh;char *condition = (char *) malloc(sizeof(char) * 8);
scanf("%d", &choice);switch(choice) {case 1: break;case 5:case 6:case 7:
printf("\n\t请输入成绩下限:");
scanf("%f", &low);
printf("\n\t请输入成绩上限:");
scanf("%f", &high);break;default:
printf("\n\t请输入要查询的值:");
scanf("%s", condition);
}//筛选符合条件的学生
Student *sturesult = (Student *) malloc(sizeof(Student) *stunum);int resultnum = 0;for (i = 0; i < stunum; i++) {switch(choice) {case 2:if (strcmp(stulist[i].no, condition) == 0)
sturesult[resultnum++] =stulist[i];break;case 3:if (strcmp(stulist[i].name, condition) == 0)
sturesult[resultnum++] =stulist[i];break;case 4:if (stulist[i].gender == *condition)
sturesult[resultnum++] =stulist[i];break;case 5:case 6:case 7:if (stulist[i].scores[choice - 5] >= low && stulist[i].scores[choice - 5] <=high)
sturesult[resultnum++] =stulist[i];break;default:
sturesult[resultnum++] =stulist[i];break;
}
}//输出查询结果
print_result(sturesult, resultnum);
}/**
* 编辑学生
**/
voidedit_stu() {intno;
printf("\n\t请输入要编辑的学生位置:");
scanf("%d", &no);if (no < 0 || no >= stunum) no = 0;//输出编辑菜单
inti;for (i = 1; i < 7; i++) {
printf("\n\t%d.%s", i, stuproperty[i]);
}intchoice;char *value = (char *) malloc(sizeof(char) * 8);
printf("\n\n\t请输入要编辑的属性编号:");
scanf("%d", &choice);
printf("\n\t请输入要新的属性值:");
scanf("%s", value);//修改属性
switch(choice) {case 1:
memcpy(stulist[no].no, value,sizeof(char) * 7);break;case 2:
memcpy(stulist[no].name, value,sizeof(char) * 9);break;case 3:
stulist[no].gender= *value;break;case 4:case 5:case 6:
stulist[no].scores[choice- 4] =atof(value);//重新计算平均成绩和总成绩
stulist[no].total_score = stulist[no].scores[0] + stulist[no].scores[1] + stulist[no].scores[2];
stulist[no].avg_score= stulist[no].total_score / 3;break;default:break;
}
}/**
* 删除学生
**/
voiddel_stu() {intno;
printf("\n\t请输入要删除的学生的位置:");
scanf("%d", &no);if (no < 0 || no >= stunum) no = 0;
memmove(&stulist[no],&stulist[no + 1],sizeof(Student) * (stunum - no - 1)
);
stunum--;
}/**
* 学生排序
**/
voidsort_stu() {//输出排序菜单
inti;
Student*sturesult = (Student *) malloc(sizeof(Student) *stunum);
memcpy(sturesult, stulist, stunum* sizeof(Student));for (i = 1; i < 7; i++) {
printf("\n\t%d.%s", i, stuproperty[i]);
}intchoice;
printf("\n\n\t请输入要排序的字段编号:");
scanf("%d", &choice);//使用选择排序
for (i = 0; i < stunum; i++) {intj;int min =i;for (j = i + 1; j < stunum; j++) {switch(choice) {case 1:if (strcmp(sturesult[j].no, stulist[min].no) < 0)
min=j;break;case 2:if (strcmp(sturesult[j].name, stulist[min].name) < 0)
min=j;break;case 3:if (sturesult[j].gender
min=j;break;case 4:case 5:case 6:if (sturesult[j].scores[choice - 4] < stulist[min].scores[choice - 4])
min=j;break;default:break;
}
}
swap(sturesult, i, min);
}//输出排序结果
print_result(sturesult, stunum);//是否保存
printf("\n\t请问是否需要保存排序结果(输入1/0):");
scanf("%d", &choice);if (choice == 1) {
free(stulist);
stulist=sturesult;
}else{
free(sturesult);
}
}/**
* 初始化,将数据文件读取进数组
**/
voidinit_sys() {
FILE*fp = fopen(DATA_FILE, "rb");if (fp ==NULL) {
stunum= 0;
stulist=NULL;
}else{
fread(&stunum, sizeof(int), 1, fp);
stulist= (Student *) malloc(sizeof(Student) *stunum);
fread(stulist,sizeof(Student), stunum, fp);
fclose(fp);
}
}/**
* 程序结束,将数据写入文件
**/
voiduinit_sys() {
FILE*fp = fopen(DATA_FILE, "wb");
fwrite(&stunum, sizeof(int), 1, fp);
fwrite(stulist,sizeof(Student), stunum, fp);
fclose(fp);
}/**
* 成绩统计
**/
voidstatistics() {//3门课,每门课10个区间
int courses[3][10] = {0};inti, j;for (i = 0; i < stunum; i++) {for (j = 0; j < 3; j++) {int q = (int) (stulist[i].scores[j] / 10);if (q > 9) q = 9;if (q < 0) q = 0;
courses[j][q]++;
}
}for (i = 0; i < 3; i++) {
printf("\n\n\t课程%d统计图:", i + 1);
printf("\n\t区间\t人数\t条形图");for (j = 0; j < 10; j++) {char *str = strrep('*', courses[i][j]);
printf("\n\t%d-%d\t%d\t%s", j * 10, (j + 1) * 10 - 1, courses[i][j], str);
free(str);
}
}
printf("\n");
}voidmain() {
validate();
init_sys();int flag = 1;while(flag) {char *menu[] ={"添加学生记录","查询学生记录","编辑学生记录","删除学生记录","排序学生记录","统计学生记录","退出系统"};//输出主菜单
char *title = strrep('*', 33);
printf("\n\t%s\t", title);inti;for (i = 0; i < 7; i++) {
printf("\n\t*\t%d.%s\t\t*", i + 1, *(menu +i));
}
printf("\n\t%s\t\n\n", title);
printf("\n\t请输入要执行的操作编号:");//等待选择功能
intchoice;
scanf("%d", &choice);switch(choice) {case 1:
add_stu();break;case 2:
query_stu();break;case 3:
edit_stu();break;case 4:
del_stu();break;case 5:
sort_stu();break;case 6:
statistics();break;default:
flag= 0;
printf("\n\tBye\n");
}
}
uinit_sys();
}