前言
算法课的第一次实验作业。在此浅作记录。
问题描述
随机点名程序(越不来上课的人,被点中的概率越高;实现抽查问题、预警等功能)。
问题分析
使用info.txt
文件存放各学生旷课次数的信息,在程序运行时使用一个包含学生姓名、旷课次数和当堂课的出勤情况的结构体数组记录并更新相关信息。
随机抽取功能的实现则是使用checklist
数组和rand
函数:在初始化时对每个学生的序号记录进checklist
数组中,其记录次数为2^(该学生的旷课次数),再用rand
函数便能实现”越不来上课的人,被点中的概率越高“的功能。当某学生的旷课次数超过最大次数时,则取消其考试资格,且初始化checklist
数组时不会将其序号计入。
点名及提问时用attendance
(初始值均为0)记录该学生出勤情况(1表示出勤,-1表示旷课),使点名函数在随机抽到已抽过的学生时将再次抽取,提问函数在抽到已经确认出勤的学生时会直接提问。预警功能则是在学生未出勤时进行预警。
该程序还加入了查询函数,可列出各学生的旷课次数。
完整代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
| #include <stdio.h> #include <stdlib.h> #include <math.h> #include <time.h> #define MAXSIZE 210 #define MAX_ABSENT_TIME 5 struct stu_info { char name[10]; int abs_time; int attendance; }stud[MAXSIZE]; int stu_num = 0; int checklist[20 * MAXSIZE] = { 0 }; int load() { FILE* fp; if ((fp = fopen("info.txt", "rb")) == NULL) { printf("无法打开文件!\n"); return 0; } while (!feof(fp)) { fscanf(fp, "%s", stud[++stu_num].name); fscanf(fp, "%d\n", &stud[stu_num].abs_time); stud[stu_num].attendance = 0; } printf("数据读取成功!共有%d名学生。\n", stu_num); fclose(fp); return 1; } void save() { int i; FILE* fp; if ((fp = fopen("info.txt", "wb")) == NULL) { printf("无法打开文件!\n"); return; } for (i = 1; i <= stu_num; i++) { fprintf(fp, "%s\n%d\n", stud[i].name, stud[i].abs_time); } printf("数据保存成功!即将退出......\n"); fclose(fp); return; } void initchecklist() { int i, j; for (i = 1; i <= stu_num; i++) { if (stud[i].abs_time != MAX_ABSENT_TIME) for (j = 0; j < pow(2, stud[i].abs_time); j++) checklist[++checklist[0]] = i; } } void alert(int id) { stud[id].abs_time++; if (stud[id].abs_time == MAX_ABSENT_TIME) printf("%s同学已旷课%d次,达到最大旷课次数,取消考试资格!\n", stud[id].name, stud[id].abs_time); else printf("%s同学已旷课%d次,请注意!\n", stud[id].name, stud[id].abs_time); return; } void check_att(int k) { int att; printf("%s同学是否出勤?\n", stud[checklist[k]].name); scanf("%d", &att); if (att) stud[checklist[k]].attendance = 1; else { stud[checklist[k]].attendance = -1; alert(checklist[k]); } return; } void CheckName(int num) { int i = 1, k; while (i <= num) { k = rand() % checklist[0] + 1; if (!stud[checklist[k]].attendance) { check_att(k); i++; } } return; } void AnswerQuestion(int num) { int i = 1, k, ans; while (i <= num) { k = rand() % checklist[0] + 1; if (!stud[checklist[k]].attendance) check_att(k); if (stud[checklist[k]].attendance == 1) { printf("%s同学,请回答:", stud[checklist[k]].name); scanf("%d", &ans); if (ans)printf("回答正确!\n"); else printf("回答错误!\n"); i++; } } return; } void find() { int i; for (i = 1; i < stu_num; i++) printf("%s同学已旷课%d次。\n", stud[i].name, stud[i].abs_time); return; } int main() { srand((unsigned)time(0)); int i, opt, n; if (!load())return 0; initchecklist(); printf("输入“1”以点名,输入“2”以抽查问题,输入“3”以查询旷课次数,输入“0”以保存并退出程序。\n"); while (1) { printf("请输入您要进行的操作:"); scanf("%d", &opt); if (!opt) { save(); return 0; } else if (opt == 1) { printf("输入点名人数:"); scanf("%d", &n); CheckName(n); } else if (opt == 2) { printf("输入提问人数:"); scanf("%d", &n); AnswerQuestion(n); } else if (opt == 3) { find(); } } return 0; }
|
后记
用到的基本上都是早已学过且用过多次的方法,写起来也没什么难度。与其说这是一个算法题目,不如说这就是一个超小型的项目。不过大项目也正是靠这些看起来很小的部分结合而成的,而且这也已经可以拿来在现实生活中运用了。
所以老师应该不会从大家的作业中拿一份出来用吧不会吧不会吧.jpg