没写过C语言,学了一晚上C的结果,为交作业新鲜出炉的
环境是 Ubuntu. 编译器 gcc
#include<stdio.h> #include<stdlib.h> #include<memory.h> #include<termio.h> #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" /** * 学生结构体 **/ typedef struct { char no[7]; char name[9]; char gender; float scores[3]; float total_score; float avg_score; } Student; Student *stulist; //所有学生列表 int stunum; //学生数量 char *stuproperty[7] = { "不指定", "学号", "姓名", "性别", "课程1", "课程2", "课程3" }; /** * 密码输出星号函数 **/ int getch() { struct termios 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; return c; } 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'; } return NULL; } p[i]='\0'; printf("\n"); return p; } /** * 登录验证 **/ void validate() { 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, int j) { Student stutemp = stulist[i]; stulist[i] = stulist[j]; stulist[j] = stutemp; } /** * 字符串重复函数 **/ char *strrep(char c, int n) { char *str = (char *) malloc(sizeof(c) * n + 1); int i; for (i = 0; i < n; i++) { *str++ = c; } *str = '\0'; str -= n; return str; } /** * 结果输出函数 **/ void print_result(Student *stulist, int stunum) { int i; 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]); } /** * 插入学生记录 **/ void add_stu() { Student stu; int no; 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 < stunum) { memmove(&stulist[no + 1], &stulist[no], (stunum - no) * sizeof(Student)); } else { //插到末尾 no = stunum; } memcpy(&stulist[no], &stu, sizeof(Student)); stunum++; } /** * 查询学生 **/ void query_stu() { //输出查询菜单 int i; for (i = 0; i < 7; i++) { printf("\n\t%d.%s", i + 1, stuproperty[i]); } printf("\n\n\t请输入查询条件编号: "); int choice; float low; float high; 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); } /** * 编辑学生 **/ void edit_stu() { int no; printf("\n\t请输入要编辑的学生位置: "); scanf("%d", &no); if (no < 0 || no >= stunum) no = 0; //输出编辑菜单 int i; for (i = 1; i < 7; i++) { printf("\n\t%d.%s", i, stuproperty[i]); } int choice; 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; } } /** * 删除学生 **/ void del_stu() { int no; 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--; } /** * 学生排序 **/ void sort_stu() { //输出排序菜单 int i; 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]); } int choice; printf("\n\n\t请输入要排序的字段编号: "); scanf("%d", &choice); //使用选择排序 for (i = 0; i < stunum; i++) { int j; 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 < stulist[min].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); } } /** * 初始化,将数据文件读取进数组 **/ void init_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); } } /** * 程序结束,将数据写入文件 **/ void uinit_sys() { FILE *fp = fopen(DATA_FILE, "wb"); fwrite(&stunum, sizeof(int), 1, fp); fwrite(stulist, sizeof(Student), stunum, fp); fclose(fp); } /** * 成绩统计 **/ void statistics() { //3门课,每门课10个区间 int courses[3][10] = {0}; int i, 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"); } void main() { validate(); init_sys(); int flag = 1; while (flag) { char *menu[] = { "添加学生记录", "查询学生记录", "编辑学生记录", "删除学生记录", "排序学生记录", "统计学生记录", "退出系统" }; //输出主菜单 char *title = strrep('*', 33); printf("\n\t%s\t", title); int i; 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请输入要执行的操作编号: "); //等待选择功能 int choice; 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(); }