特别基础版学生宿舍管理系统(C语言版)
本系统只有最基础功能,输入错误指令易报错,仅供小白批判性参考。
1.核心问题:我们的目的是什么?
目的是构建一个学生宿舍管理系统。由此想出我们需要进行管理的对象的组成是什么。
管理对象分为两个整体:学生和宿舍。
学生会有很多基础信息,此文仅以最基础的名字(name)和住宿状态(state)举例。
*住宿状态便于使用在退宿和空床位查看上。
宿舍要考虑的信息,此文以楼栋(building)、房间号(room)、床位数量(totalbeds)、入住人数(lived)和入住学生(student)举例。
2.如何表示这些数据信息?
使用结构体。
int condition:0表示未住,1表示入住 students[6]表示每个宿舍最多6人
3.如何引用和保存数据?
要让程序启动并读取数据,可以使用文件来达成目的。如果文件不存在,可以使用默认数据让程序能够运行。
同时要考虑到系统中多个函数都会访问各个宿舍,所以我们还需要设置全局变量。
Dormitory dorms[MAX_DORM];
int dorm_count = 0;
void loadFromFile(){ FILE *fp = fopen("dorm.txt", "r"); if(fp == NULL) { printf("Not find file. Loading local messages.\n"); dorm_count = 3; // 宿舍1:A栋 203(2人) strcpy(dorms[0].building, "A"); strcpy(dorms[0].room, "203"); dorms[0].totalbeds = 6; dorms[0].lived = 6; dorms[0].students[0] = (Student){ "LiuXiangqi", 1}; dorms[0].students[1] = (Student){ "YangYu", 1}; // 宿舍2:A 104(1人) strcpy(dorms[1].building, "HefengD"); strcpy(dorms[1].room, "6058"); dorms[1].totalbeds = 6; dorms[1].lived = 1; dorms[1].students[0] = (Student){ "LiYingjie", 1}; for(int i = 1; i < 6; i++){ dorms[1].students[i].condition = 0; } } else { // 文件存在,从文件读取 fscanf(fp, "%d\n", &dorm_count); for(int i = 0; i < dorm_count; i++) { fscanf(fp, "%s%s%d%d\n", dorms[i].building, dorms[i].room, &dorms[i].totalbeds, &dorms[i].lived); for(int j = 0; j < dorms[i].totalbeds; j++) { char name[20]; int condition; fscanf(fp, "%s %d\n", name, &condition); strcpy(dorms[i].students[j].name, name); dorms[i].students[j].condition = condition; } } fclose(fp); printf("Loading Success! Dormitory have %d\n", dorm_count); } }4.关于添加宿舍
先创建一个临时的new宿舍存放你需要录入的信息,最后再提交进去。
*关于while(getchar() != '\n')清空缓冲区的问题:
scanf读取后会在缓冲区留下换行符,导致输入被跳过。此处其实不会遇到此问题,但可以养成习惯。
void AddDormitory(){ Dormitory new; printf("Please enter the building:\n"); scanf("%s", new.building); while(getchar() != '\n'); printf("Please enter the room:\n"); scanf("%s", new.room); while(getchar() != '\n'); printf("Please enter the beds:\n"); scanf("%d", &new.totalbeds); while(getchar() != '\n'); for(int i = 0; i < new.totalbeds; i++){ new.students[i].condition = 0; } dorms[dorm_count] = new; dorm_count++; printf("Success!"); }5.关于查询宿舍
输入楼栋和房间号以查找到宿舍信息。其中定位到宿舍下标的逻辑会在多个函数应用到,所有可以把这部分单拎出来写一个函数。
int findDorm(char building[], char room[]) { for (int i = 0; i < dorm_count; i++) { if (strcmp(dorms[i].building, building) == 0 && strcmp(dorms[i].room, room) == 0) { return i; } } return -1; }然后是将这个函数应用到查询宿舍信息的函数
void SearchDorm(){ char building[20]; char room[10]; printf("Please enter the building: "); scanf("%s", building); while(getchar() != '\n'); printf("Please enter the room: "); scanf("%s", room); while(getchar() != '\n'); int goal = findDorm(building, room); if (goal == -1) { printf("Not found!! \n"); return; } printf("Dormitory %s, total beds %d, lived %d\n", dorms[goal].building, dorms[goal].room, dorms[goal].totalbeds, dorms[goal].lived); }6.关于学生入住
学生入住需要我们先找到目标宿舍->找到空床位->录入学生->更新全局变量
void checkin(){ char building[20]; char room[10]; printf("Please enter the building: "); scanf("%s", building); while(getchar() != '\n'); printf("Please enter the room: "); scanf("%s", room); while(getchar() != '\n'); int dormnum = findDorm(building, room); if (dormnum == -1) { printf("Not found!\n"); return; } int bednum = -1; for(int i = 0; i < dorms[dormnum].totalbeds; i++) { if (dorms[dormnum].students[i].condition == 0) { bednum = i; break; } } if (bednum == -1) { printf("full dormitory\n"); return; } Student stu; printf("Please enter the name: "); scanf("%s", stu.name); while(getchar() != '\n'); stu.condition = 1; dorms[dormnum].students[bednum] = stu; dorms[dormnum].lived++; printf("Success! \n"); }7.关于学生退宿
退宿需要输入姓名查询到宿舍,这里需要一个按姓名查找的功能。由于一个函数只能返回一个值,所以用指针参数返回额外信息。
由于要修改宿舍里学生的状态信息,所以要传入指针的地址,需要用到二级指针。
int Studentfindnum(char* name, Dormitory** sdom, int* sbed){ for (int i = 0; i < dorm_count; i++) { for (int j = 0; j < dorms[i].totalbeds; j++) { if (dorms[i].students[j].condition == 1 && strcmp(dorms[i].students[j].name, name) == 0) { *sdom = &dorms[i]; *sbed = j; return 1; } } } return 0; }再将此应用到退宿中。
void checkout() { char name[20]; printf("Please enter the name: "); scanf("%s", name); while(getchar() != '\n'); Dormitory *sdorm; int sbed; if(Studentfindnum(name, &sdorm, &sbed) == 0){ printf("Not found.\n"); return; } sdorm->students[sbed].condition = 0; sdorm->lived--; printf("Succeed!\n"); }8.关于查询学生
void StudentSearch(){ char name[20]; printf("Please enter the name:"); scanf("%s", name); while(getchar() != '\n'); Dormitory *sdorm; int sbed; if (Studentfindnum(name, &sdorm, &sbed)){ printf("%s %s \n", sdorm->building, sdorm->room); } else { printf("Not found. \n"); } }9.关于空床统计
可以考虑两种形式,一个是总共有多少空床,一个是每一栋有几个空床。
void Emptybed(){ int empty = 0; for(int i = 0; i < dorm_count; i++){ empty += (dorms[i].totalbeds - dorms[i].lived); } printf("Total empty beds: %d\n", empty); char building[10] = ""; for(int i = 0; i < dorm_count; i++){ if(strcmp(building, dorms[i].building) != 0){ if(i == 0) printf("\n"); else strcpy(building, dorms[i].building); printf("building%s:", building); } } printf("%s empty %d beds\n", dorms[i].rooms[i].totalbeds - dorms[i].lived); }10.关于入住率排序
按入住率排序需要计算每个宿舍的入住率并排序。
void Sort(){ Dormitory tmp[MAX_DORM]; for(int i = 0; i < dorm_count; i++){ tmp[i] = dorms[i]; } for(int i = 0; i < dorm_count-1; i++){ for(int j = 0; j < dorm_count-1-i; j++){ float r1 = 0.0f; if(tmp[j].totalbeds > 0){ r1 = (float)tmp[j].lived / tmp[j].totalbeds; } float r2 = 0.0f; if(tmp[j+1].totalbeds > 0){ r2 = (float)tmp[j+1].lived / tmp[j+1].totalbeds; } if(r1 < r2){ Dormitory tmp1 = tmp[j]; tmp[j] = tmp[j+1]; tmp[j+1] = tmp1; } } } for(int i = 0; i < dorm_count; i++){ float n = 0.0f; if(tmp[i].totalbeds > 0){ n = (float)tmp[i].lived / tmp[i].totalbeds * 100; } printf("%s, %s, %d, %d, %.1f%%\n", tmp[i].building, tmp[i].room, tmp[i].totalbeds, tmp[i].lived, n); } }