目录
实验简介一、实验要求二、实验代码1. 完整代码2. 代码解析(1)get_next_question_number(2)add_question(3)delete_question(4)backup_questions(5)delete_all_questions(6)modify_question(7)search_question(8)count_questions(9)search_specific_content(10)get_question_count(11)get_random_number(12)is_question_selected(13)generate_exam_paper(14)main
三、效果展示1. 文档展示(1)选择题文档 choice_question.txt(2)填空题文档 fill_in_blank_questions.txt(3)试卷文档 exam_paper.txt
2. 菜单展示
总结实验文件领取
实验简介
老师在教学过程中,会经常以试卷的形式来检验学生的学习情况。现在由你来帮助老师设计一个试卷自动生成系统,完成从已有题库(题库包含2个文件,1个是选择题题库文件,1格式填空题题库文件)中随机提取指定题目书的题目生成一份新的试卷。该系统生成的试卷中只有2种题型:单项选择题、填空题(只有一个空)。
一、实验要求
单项选择题包括题目编号、题目、选项A、选项B、选项C、选项D、答案 填空题包括题目编号、题目、答案 功能: (1)试题添加:向试题库追加写入一道新的题目,要求题目编号自动生成,且与已存题目的编号不重复;所有内容不能为空。即不断充实题库; (2)试题删除:通过题目编号进行题目的删除,如果删除成功则提示删除成功,否则提示删除失败; (3)备份全部题目; (4)删除全部题目; (5)试题修改:通过题目编号查找对应题目,并修改指定的题目的内容,注意不是修改题目的全部内容,而是可以针对性的修改局部内容; (6)试题查询:通过题目编号查询指定的题目的所有内容; (7)统计共有多少道题目; (8)查询题目中含有某个特定内容(用户输入)的所有题目内容; (9)自动随机生成由单项选择题、填空题合在一起的试卷及标准答案2个文件(exam.txt和answer.txt),各题型的题目数由用户输入。注意选择题和填空题的题目数可以不一样;要求每次生成的试卷题目、顺序都不能完全相同。也就是要求真正的随机提取题目。 (10)以上功能要求通过菜单的方式进行操作;要求对相应内容进行必要的合法性检查。要求具有良好的人机交互界面。每个题型要提前录入至少10道题。
二、实验代码
1. 完整代码
直接先给出实验完整代码:
#include
#include
#include
#define CHOICE_QUESTION_FILE "choice_questions.txt"
#define FILL_IN_BLANK_QUESTION_FILE "fill_in_blank_questions.txt"
#define SINGLE_CHOICE_QUESTION 1
#define FILL_IN_THE_BLANK_QUESTION 2
#define MAX_QUESTION_LEN 256
#define MAX_FILENAME_LEN 256
#define MAX_OPTION_LEN 16
#define MAX_ANSWER_LEN 32
#define ADD_QUESTION 1
#define DELETE_QUESTION 2
#define BACKUP_QUESTIONS 3
#define DELETE_ALL_QUESTIONS 4
#define MODIFY_QUESTION 5
#define SEARCH_QUESTION 6
#define COUNT_QUESTIONS 7
#define SEARCH_SPECIFIC_CONTENT 8
#define GENERATE_EXAM_PAPER 9
#define EXIT 10
int get_next_question_number(const char *question_file, int question_type) {
FILE *fp;
int question_number;
int choice_question_number;
int fill_in_blank_question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return -1;
}
if (question_type == 1) {
choice_question_number = 1;
while (fscanf(fp, "%d %s %s %s %s %s %s", &question_number, question, option_a, option_b, option_c, option_d,
answer) != EOF) {
choice_question_number++;
}
fclose(fp);
return choice_question_number;
} else if (question_type == 2) {
fill_in_blank_question_number = 1;
while (fscanf(fp, "%d %s %s", &question_number, question, answer) != EOF) {
fill_in_blank_question_number++;
}
fclose(fp);
return fill_in_blank_question_number;
} else {
printf("无效问题类型\n");
return -1;
}
}
void add_question(const char *question_file, int question_type) {
FILE *fp;
int question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
fp = fopen(question_file, "a");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
if (question_type == 1) {
question_number = get_next_question_number(question_file, question_type);
printf("输入题目:");
scanf(" %s", question);
printf("输入选项A: ");
scanf(" %s", option_a);
printf("输入选项B: ");
scanf(" %s", option_b);
printf("输入选项C: ");
scanf(" %s", option_c);
printf("输入选项D: ");
scanf(" %s", option_d);
printf("输入正确选项: ");
scanf(" %s", answer);
fprintf(fp, "%d %s %s %s %s %s %s\n",
question_number, question, option_a, option_b, option_c, option_d, answer);
} else if (question_type == 2) {
question_number = get_next_question_number(question_file, question_type);
printf("输入题目:");
scanf(" %s", question);
printf("输入答案:");
scanf(" %s", answer);
fprintf(fp, "%d %s %s\n", question_number, question, answer);
} else {
printf("无效问题类型\n");
}
fclose(fp);
}
void delete_question(const char *question_file, int question_number, int question_type) {
FILE *fp;
FILE *temp_fp;
int curr_question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
temp_fp = fopen("temp.txt", "w");
if (temp_fp == NULL) {
printf("无法打开文件\n");
return;
}
if (question_type == 1) {
while (fscanf(fp, "%d %s %s %s %s %s %s",
&curr_question_number, question, option_a, option_b, option_c, option_d, answer) != EOF) {
if (curr_question_number != question_number) {
fprintf(temp_fp, "%d %s %s %s %s %s %s\n",
curr_question_number, question, option_a, option_b, option_c, option_d, answer);
}
}
} else if (question_type == 2) {
while (fscanf(fp, "%d %s %s", &curr_question_number, question, answer) != EOF) {
if (curr_question_number != question_number) {
fprintf(temp_fp, "%d %s %s\n", curr_question_number, question, answer);
}
}
} else {
printf("无效问题类型\n");
}
fclose(fp);
fclose(temp_fp);
remove(question_file);
rename("temp.txt", question_file);
}
void backup_questions(const char *question_file, int question_type) {
FILE *fp;
FILE *backup_fp;
int question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
backup_fp = fopen("question_backup.txt", "w");
if (backup_fp == NULL) {
printf("无法打开文件\n");
return;
}
if (question_type == SINGLE_CHOICE_QUESTION) {
while (fscanf(fp, "%d %s %s %s %s %s %s",
&question_number, question, option_a, option_b, option_c, option_d, answer) != EOF) {
fprintf(backup_fp, "%d %s %s %s %s %s %s\n",
question_number, question, option_a, option_b, option_c, option_d, answer);
}
} else if (question_type == FILL_IN_THE_BLANK_QUESTION) {
while (fscanf(fp, "%d %s %s", &question_number, question, answer) != EOF) {
fprintf(backup_fp, "%d %s %s\n", question_number, question, answer);
}
}
fclose(fp);
fclose(backup_fp);
}
void delete_all_questions(const char *question_file, int question_type) {
char backup_file[MAX_FILENAME_LEN];
sprintf(backup_file, "%s_backup", question_file);
// 将所有题目备份到另一个文件
backup_questions(question_file, question_type);
// 删除原文件
remove(question_file);
// 创建空文件
FILE *fp = fopen(question_file, "w");
fclose(fp);
}
void modify_question(const char *question_file, int question_type, int question_number) {
// 打开题目文件
FILE *fp = fopen(question_file, "r+");
if (fp == NULL) {
printf("无法打开文件 %s\n", question_file);
return;
}
char line[MAX_QUESTION_LEN]; // 用来存储每行读入的内容
int line_number = 0; // 用来记录当前行号
int modified = 0; // 用来标记是否修改了题目
// 遍历每一行,找到需要修改的题目
while (fgets(line, MAX_QUESTION_LEN, fp) != NULL) {
// 如果找到了需要修改的题目,则修改题目内容
if (line_number == question_number - 1) {
// 将文件指针移动到当前行开头
fseek(fp, -strlen(line), SEEK_CUR);
// 读入修改后的题目内容
if (question_type == SINGLE_CHOICE_QUESTION) {
char question[MAX_QUESTION_LEN];
while (strlen(question) == 0) {
printf("请输入修改后的题干:");
fgets(question, MAX_QUESTION_LEN, stdin);
question[strlen(question) - 1] = '\0'; // 去掉回车
}
printf("请输入修改后的选项A:");
char option_a[MAX_OPTION_LEN];
fgets(option_a, MAX_OPTION_LEN, stdin);
option_a[strlen(option_a) - 1] = '\0'; // 去掉回车
printf("请输入修改后的选项B:");
char option_b[MAX_OPTION_LEN];
fgets(option_b, MAX_OPTION_LEN, stdin);
option_b[strlen(option_b) - 1] = '\0'; // 去掉回车
printf("请输入修改后的选项C:");
char option_c[MAX_OPTION_LEN];
fgets(option_c, MAX_OPTION_LEN, stdin);
option_c[strlen(option_c) - 1] = '\0'; // 去掉回车
printf("请输入修改后的选项D:");
char option_d[MAX_OPTION_LEN];
fgets(option_d, MAX_OPTION_LEN, stdin);
option_d[strlen(option_d) - 1] = '\0'; // 去掉回车
printf("请输入修改后的正确答案:");
char answer[MAX_ANSWER_LEN];
fgets(answer, MAX_ANSWER_LEN, stdin);
answer[strlen(answer) - 1] = '\0';
// 将修改后的题目内容写入文件
fprintf(fp, " %s %s %s %s %s %s ", question, option_a, option_b, option_c, option_d, answer);
} else {
// 如果是填空题,则只需要输入修改后的题干和答案
printf("请输入修改后的题干:");
char question[MAX_QUESTION_LEN];
fgets(question, MAX_QUESTION_LEN, stdin);
question[strlen(question) - 1] = '\0'; // 去掉回车
printf("请输入修改后的答案:");
char answer[MAX_QUESTION_LEN];
fgets(answer, MAX_QUESTION_LEN, stdin);
answer[strlen(answer) - 1] = '\0'; // 去掉回车
// 将文件指针移动到当前行开头
fseek(fp, -strlen(line), SEEK_CUR);
// 将修改后的题目内容写入文件
fprintf(fp, " %s %s ", question_number, question, answer);
}
// 标记已经修改了题目,退出循环
modified = 1;
break;
}
line_number++;
}
// 如果未找到需要修改的题目,则输出提示信息
if (!modified) {
printf("未找到需要修改的题目\n");
}
// 关闭文件
fclose(fp);
}
void search_question(const char *question_file, int question_type, int question_number) {
FILE *fp;
int found = 0;
int tmp_question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
if (question_type == SINGLE_CHOICE_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
// 查找指定题目
while (fscanf(fp, "%d %s %s %s %s %s %s",
&tmp_question_number, question, option_a, option_b, option_c, option_d, answer) != EOF) {
if (tmp_question_number == question_number) {
found = 1;
break;
}
}
// 如果找到了指定题目,输出题目信息
if (found) {
printf("题目编号:%d\n", question_number);
printf("题目:%s\n", question);
printf("选项 A:%s\n", option_a);
printf("选项 B:%s\n", option_b);
printf("选项 C:%s\n", option_c);
printf("选项 D:%s\n", option_d);
printf("答案:%s\n", answer);
} else {
printf("未找到指定题目\n");
}
fclose(fp);
} else if (question_type == FILL_IN_THE_BLANK_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
// 查找指定题目
while (fscanf(fp, "%d %s %s", &tmp_question_number, question, answer) != EOF) {
if (tmp_question_number == question_number) {
found = 1;
break;
}
}
// 如果找到了指定题目,输出题目信息
if (found) {
printf("题目编号:%d\n", question_number);
printf("题目:%s\n", question);
printf("答案:%s\n", answer);
} else {
printf("未找到指定题目\n");
}
fclose(fp);
} else {
printf("无效题目类型\n");
}
}
int count_questions(const char *question_file, int question_type) {
FILE *fp;
int count = 0;
if (question_type == SINGLE_CHOICE_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 0;
}
// 统计题目数量
int question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s %s %s %s %s",
&question_number, question, option_a, option_b, option_c, option_d, answer) != EOF) {
count++;
}
fclose(fp);
} else if (question_type == FILL_IN_THE_BLANK_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 0;
}
// 统计题目数量
int question_number;
char question[MAX_QUESTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s", &question_number, question, answer) != EOF) {
count++;
}
fclose(fp);
} else {
printf("无效题目类型\n");
}
return count;
}
void search_specific_content(const char *question_file, int question_type, const char *specific_content) {
FILE *fp;
if (question_type == SINGLE_CHOICE_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
// 查找指定题目
int question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s %s %s %s %s", &question_number, question, option_a, option_b, option_c, option_d,
answer) != EOF) {
if (strstr(question, specific_content) != NULL || strstr(option_a, specific_content) != NULL ||
strstr(option_b, specific_content) != NULL || strstr(option_c, specific_content) != NULL ||
strstr(option_d, specific_content) != NULL || strstr(answer, specific_content) != NULL) {
printf("题目编号:%d\n", question_number);
printf("题目:%s\n", question);
printf("选项A:%s\n", option_a);
printf("选项B:%s\n", option_b);
printf("选项C:%s\n", option_c);
printf("选项D:%s\n", option_d);
printf("答案:%s\n", answer);
}
}
fclose(fp);
} else if (question_type == FILL_IN_THE_BLANK_QUESTION) {
fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return;
}
// 查找指定题目
int question_number;
char question[MAX_QUESTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s", &question_number, question, answer) != EOF) {
if (strstr(question, specific_content) != NULL || strstr(answer,
specific_content) != NULL) {
printf("题目编号:%d\n", question_number);
printf("题目:%s\n", question);
printf("答案:%s\n", answer);
}
}
fclose(fp);
}
}
int get_question_count(const char *question_file, int question_type) {
int count = 0;
FILE *fp = fopen(question_file, "r");
if (fp == NULL) {
printf("无法打开文件\n");
return 0;
}
if (question_type == SINGLE_CHOICE_QUESTION) {
int curr_question_number;
char question[MAX_QUESTION_LEN];
char option_a[MAX_OPTION_LEN];
char option_b[MAX_OPTION_LEN];
char option_c[MAX_OPTION_LEN];
char option_d[MAX_OPTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s %s %s %s %s", &curr_question_number, question,
option_a, option_b, option_c, option_d, answer) != EOF) {
count++;
}
} else if (question_type == FILL_IN_THE_BLANK_QUESTION) {
int curr_question_number;
char question[MAX_QUESTION_LEN];
char answer[MAX_ANSWER_LEN];
while (fscanf(fp, "%d %s %s", &curr_question_number, question, answer) != EOF) {
count++;
}
} else {
printf("无效问题类型\n");
}
fclose(fp);
return count;
}
int get_random_number(int min, int max) {
return rand() % (max - min + 1) + min;
}
int number = 1;
int is_question_selected(int question_number, int *question_numbers) {
int i;
for (i = 0; i choice_question_count) {
printf("选择题数量大于最大的选择题数量 %d,应该小于等于最大的选择题数量\n", choice_question_count);
return;
}
int choice_question_numbers[MAX_QUESTION_LEN] = {0};
int choice_question_number;
int count = 0; // 已经抽取到的题目数量
fprintf(exam_paper_fp, "选择题:\n");
while (count fill_in_blank_question_count) {
printf("填空题数量大于最大的填空题数量 %d,应该小于等于最大的填空题数量\n", fill_in_blank_question_count);
return;
}
int fill_in_blank_question_numbers[MAX_QUESTION_LEN] = {0};
int fill_in_blank_question_number;
count = 0;
fprintf(exam_paper_fp, "填空题:\n");
while (count |