【C语言程序设计实验】试卷管理系统(完整代码+函数详解) -->源代码文件文章末尾免费领取

2023-11-15


实验简介

       老师在教学过程中,会经常以试卷的形式来检验学生的学习情况。现在由你来帮助老师设计一个试卷自动生成系统,完成从已有题库(题库包含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 <stdio.h>
#include <stdlib.h>
#include <string.h>

#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 < MAX_QUESTION_LEN; i++) {
        if (question_numbers[i] == question_number) {
            return 1;
        }
    }
    return 0;
}

void generate_exam_paper(const char *choice_question_file,
                         const char *fill_in_blank_question_file,
                         int num_choice_questions,
                         int num_fill_in_blank_questions) {
// 打开题目文件
    FILE *choice_fp = fopen(choice_question_file, "r");
    if (choice_fp == NULL) {
        printf("无法打开选择题文件\n");
        return;
    }
    FILE *fill_in_blank_fp = fopen(fill_in_blank_question_file, "r");
    if (fill_in_blank_fp == NULL) {
        printf("无法打开填空题文件\n");
        return;
    }
// 打开考试试卷文件
    FILE *exam_paper_fp = fopen("exam_paper.txt", "w");
    if (exam_paper_fp == NULL) {
        printf("无法打开试卷文件\n");
        return;
    }
// 随机生成num_choice_questions道单项选择题
    int choice_question_count = get_question_count(choice_question_file, SINGLE_CHOICE_QUESTION);
    if (num_choice_questions > 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 < num_choice_questions) {
        choice_question_number = get_random_number(1, choice_question_count);
        if (choice_question_numbers[choice_question_number - 1] == 0) {
            choice_question_numbers[choice_question_number - 1] = 1;
            //print_question(exam_paper_fp, choice_fp, choice_question_number, SINGLE_CHOICE_QUESTION);
            fseek(choice_fp, 0, SEEK_SET);
            int curr_choice_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(choice_fp, "%d %s %s %s %s %s %s", &curr_choice_question_number, question,
                          option_a, option_b, option_c, option_d, answer) != EOF) {
                if (curr_choice_question_number == choice_question_number) {
// 找到了指定的题目,把它打印到考卷文件里
                    fprintf(exam_paper_fp, "%d.", number++);
                    fprintf(exam_paper_fp, "%s", question);
                    fprintf(exam_paper_fp, " A.%s", option_a);
                    fprintf(exam_paper_fp, " B.%s", option_b);
                    fprintf(exam_paper_fp, " C.%s", option_c);
                    fprintf(exam_paper_fp, " D.%s\n", option_d);
                    break;
                }
            }
            count++;
        }
    }
    fprintf(exam_paper_fp, "\n");
// 随机生成num_fill_in_blank_questions道填空题
    int fill_in_blank_question_count = get_question_count(fill_in_blank_question_file, FILL_IN_THE_BLANK_QUESTION);
    if (num_fill_in_blank_questions > 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 < num_fill_in_blank_questions) {
        fill_in_blank_question_number = get_random_number(1, fill_in_blank_question_count);
        if (!is_question_selected(fill_in_blank_question_number, fill_in_blank_question_numbers)) {
            //print_question(exam_paper_fp, fill_in_blank_fp, fill_in_blank_question_number, FILL_IN_THE_BLANK_QUESTION);
            int curr_fill_in_blank_question_number;
            char question[MAX_QUESTION_LEN];
            char answer[MAX_ANSWER_LEN];
            while (fscanf(fill_in_blank_fp, "%d %s %s", &curr_fill_in_blank_question_number, question, answer) != EOF) {
                if (curr_fill_in_blank_question_number == fill_in_blank_question_number) {
                    fseek(fill_in_blank_fp, 0, SEEK_SET);
                    fprintf(exam_paper_fp, "%d. %s\n", number++, question);
                    break;
                }
            }
            fill_in_blank_question_numbers[count] = fill_in_blank_question_number;
            count++;
        }
    }

// 关闭文件
    fclose(choice_fp);
    fclose(fill_in_blank_fp);
    fclose(exam_paper_fp);
}

int main() {
    int choice;
    int question_number;
    char content[MAX_QUESTION_LEN];
    int num_choice_questions;
    int num_fill_in_blank_questions;

    while (1) {
        printf("\n菜单:\n");
        printf("1. 添加题目\n");
        printf("2. 删除题目\n");
        printf("3. 备份全部题目\n");
        printf("4. 删除全部题目\n");
        printf("5. 修改题目\n");
        printf("6. 题目查询\n");
        printf("7. 统计题目个数\n");
        printf("8. 查询题目中含有某个特定内容的所有题目内容\n");
        printf("9. 生成试卷\n");
        printf("10. 退出\n");
        printf("输入数字选择对应操作: ");
        scanf("%d", &choice);
        if (choice == EXIT) {
            break;
        }

        switch (choice) {
            case ADD_QUESTION:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    add_question(CHOICE_QUESTION_FILE, question_number);
                } else if (question_number == 2) {
                    add_question(FILL_IN_BLANK_QUESTION_FILE, question_number);
                } else {
                    printf("无效的题目类型\n");
                }
                break;
            case DELETE_QUESTION:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    delete_question(CHOICE_QUESTION_FILE, question_number, question_number);
                } else if (question_number == 2) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    delete_question(FILL_IN_BLANK_QUESTION_FILE, question_number, question_number);
                } else {
                    printf("无效的题目类型\n");
                }
                break;
            case BACKUP_QUESTIONS:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    backup_questions(CHOICE_QUESTION_FILE, question_number);
                } else if (question_number == 2) {
                    backup_questions(FILL_IN_BLANK_QUESTION_FILE, question_number);
                } else {
                    printf("无效的题目类型\n");
                }
                break;
            case DELETE_ALL_QUESTIONS:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    delete_all_questions(CHOICE_QUESTION_FILE, question_number);
                } else if (question_number == 2) {
                    delete_all_questions(FILL_IN_BLANK_QUESTION_FILE, question_number);
                } else {
                    printf("无效的题目类型\n");
                }
                break;
            case MODIFY_QUESTION:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    modify_question(CHOICE_QUESTION_FILE, SINGLE_CHOICE_QUESTION, question_number);
                } else if (question_number == 2) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    modify_question(FILL_IN_BLANK_QUESTION_FILE, FILL_IN_THE_BLANK_QUESTION, question_number);
                } else {
                    printf("无效的数据类型\n");
                }
                break;
            case SEARCH_QUESTION:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    search_question(CHOICE_QUESTION_FILE, SINGLE_CHOICE_QUESTION, question_number);
                } else if (question_number == 2) {
                    printf("输入题号: ");
                    scanf("%d", &question_number);
                    search_question(FILL_IN_BLANK_QUESTION_FILE, FILL_IN_THE_BLANK_QUESTION, question_number);
                } else {
                    printf("无效的数据类型\n");
                }
                break;
            case COUNT_QUESTIONS:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                if (question_number == 1) {
                    printf("选择题的数量为: %d\n", count_questions(CHOICE_QUESTION_FILE, question_number));
                } else if (question_number == 2) {
                    printf("填空题的数量为: %d\n", count_questions(FILL_IN_BLANK_QUESTION_FILE, question_number));
                } else {
                    printf("无效的数据类型\n");
                }
                break;
            case SEARCH_SPECIFIC_CONTENT:
                printf("输入题目类型 (1 选择题, 2 填空题): ");
                scanf("%d", &question_number);
                printf("输入内容: ");
                scanf("%s", content);
                if (question_number == 1) {
                    search_specific_content(CHOICE_QUESTION_FILE, question_number, content);
                } else if (question_number == 2) {
                    search_specific_content(FILL_IN_BLANK_QUESTION_FILE, question_number, content);
                } else {
                    printf("无效的数据类型\n");
                }
                break;
            case GENERATE_EXAM_PAPER:
                number = 1;
                printf("输入选择题的数量: ");
                scanf("%d", &num_choice_questions);
                printf("输入填空题的数量: ");
                scanf("%d", &num_fill_in_blank_questions);
                generate_exam_paper(CHOICE_QUESTION_FILE,
                                    FILL_IN_BLANK_QUESTION_FILE,
                                    num_choice_questions,
                                    num_fill_in_blank_questions);
                break;
            default:
                printf("无效的选择\n");
                break;
        }
    }
    return 0;
}

2. 代码解析

(1)get_next_question_number

       get_next_question_number函数是用来获取下一个题目编号的函数。它接收一个参数,即题目所在的文件名,然后从文件中读取最后一条记录,并从中获取题目编号。然后,它将题目编号加1并返回,以便用于新题目的编号。例如,如果当前题库文件已有5道选择题,那么执行get_next_question_number(“questions.txt”, SINGLE_CHOICE_QUESTION)将会返回6。

(2)add_question

       add_question函数是一个用来添加题目的函数。它需要两个参数:question_file和question_type。question_file是一个字符串,表示题目文件的路径;question_type是一个整数,表示题目类型。
       在这个函数中,会根据question_type的值,询问用户输入不同类型的题目信息。如果question_type为SINGLE_CHOICE_QUESTION,则询问用户输入单选题的信息(包括题干、选项、正确答案等);如果question_type为FILL_IN_THE_BLANK_QUESTION,则询问用户输入填空题的信息(包括题干和答案等)。
       在用户输入了题目信息后,函数会将这些信息写入question_file指定的文件中,完成添加题目的操作。

(3)delete_question

       delete_question函数是用来删除给定的题目文件中的某一题的函数。在执行时,函数首先会打开给定的题目文件,然后读入每一行的内容,并判断当前行是否是要删除的题目。如果找到了要删除的题目,函数就会将文件指针移动到该行的开头,然后删除该行。函数最后会关闭打开的文件。

(4)backup_questions

       backup_questions函数用于备份题目文件。它打开指定的题目文件并从中读取题目内容,然后打开一个名为"question_backup.txt"的新文件并将读取到的题目内容写入该文件中。它支持两种题目类型,即选择题和填空题。对于选择题,函数会读取题号、题干、4个选项和正确答案,并将这些信息写入备份文件中。对于填空题,函数会读取题号、题干和答案,并将这些信息写入备份文件中。函数在读取完所有题目后关闭输入文件和输出文件。

(5)delete_all_questions

       delete_all_questions函数的功能是删除所有的题目。首先,它会将所有的题目备份到另一个文件。然后,它会删除原来的文件。最后,它会创建一个空的文件,以便之后可以继续添加新的题目。

(6)modify_question

       modify_question是用来修改已有题目的函数。在调用这个函数时,需要传入三个参数:题目文件名、题目类型(选择题或填空题)、题目编号。函数会先打开题目文件,然后读入每一行的内容,找到需要修改的题目,然后要求用户输入修改后的题目内容,并将修改后的题目内容写入文件。如果没有找到需要修改的题目,则提示未找到。最后,关闭文件并退出函数。

(7)search_question

       search_question函数用于在指定的试题文件中搜索指定的试题编号的试题。如果找到了该试题,则将该试题的信息打印出来,否则显示找不到该试题的信息。该函数需要三个参数:question_file表示试题文件的文件名,question_type表示试题类型(选择题或填空题),question_number表示试题编号。

(8)count_questions

       count_questions函数是用来计算题库中题目的数量的。它接受两个参数:question_file是题库的文件名,question_type是题目的类型(比如选择题、填空题等)。这个函数会打开题库文件,遍历文件中的每一行,并计算题目的数量。最后,它返回题目的数量。

(9)search_specific_content

       search_specific_content函数的功能是在给定的题目文件中搜索指定的内容,并将找到的所有题目的信息输出到屏幕上。题目文件参数表示要搜索的文件名,question_type参数表示题目的类型(选择题或填空题),specific_content参数表示要搜索的关键字。如果找不到任何匹配的题目,则函数会输出提示信息。

(10)get_question_count

       get_question_count的功能是统计给定文件中指定类型的题目数量。其中,question_file是指定的文件名,question_type是题目类型,该函数会返回文件中指定类型的题目数量。

(11)get_random_number

       get_random_number函数是用来生成一个在指定范围内的随机数的函数。它接受两个参数,min和max,表示随机数的范围。函数会返回一个在这个范围内的整数。

(12)is_question_selected

       is_question_selected函数用来检查一道题是否已经被选择过。它接受两个参数:一个是要检查的题目编号,另一个是一个整数数组,存储了所有已经被选择的题目编号。如果给定的题目编号在数组中出现过,则函数返回1,否则返回0。
       例如,假设有一个数组question_numbers存储了已经被选择的题目编号,则调用is_question_selected(3, question_numbers)可以用来检查题目编号为3的题目是否已经被选择过。如果3在question_numbers数组中出现过,则函数返回1,否则返回0。

(13)generate_exam_paper

       generate_exam_paper函数的功能是在指定的文件中选择指定数量的选择题和填空题,并生成一张考试试卷。它会读取指定的文件中的题目,随机选择num_choice_questions道选择题和num_fill_in_blank_questions道填空题,并将这些题目打印到输出流中。

(14)main

       main函数包含一个无限循环,用于显示菜单并执行用户选择的操作。用户可以选择添加题目、删除题目、备份全部题目、删除全部题目、修改题目、查询题目、统计题目个数、查询含有某个特定内容的所有题目或生成试卷,并实现对应的功能。


三、效果展示

1. 文档展示

(1)选择题文档 choice_question.txt

       choice_question为选择题题库文档,内容示例:

在这里插入图片描述
       选择题文档第一列为题目序号,第二列为题目题干,第三列为选项A内容,第四列为选项B内容,第五列为选项C内容,第六列为选项D内容,第七列为答案。

(2)填空题文档 fill_in_blank_questions.txt

fill_in_blank_questions.txt为填空题文档,内容示例:
在这里插入图片描述
填空题文档第一列为题目序号,第二列为题目题干,第三列为题目答案。

(3)试卷文档 exam_paper.txt

exam_paper.txt为生成随机试卷文档,生成示例:

在这里插入图片描述

2. 菜单展示

在这里插入图片描述
具体的功能可以自行运行尝试,这里我就不一一示范了。

总结

以上就是本次实验的内容,本文简单实现了一个试卷系统,内含一系列用于管理和生成试卷的功能,喜欢的话记得点赞关注加收藏,谢谢你的浏览。


实验文件领取

实验文件直接点击此处领取。有帮助的话可以点赞收藏关注,谢谢。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【C语言程序设计实验】试卷管理系统(完整代码+函数详解) -->源代码文件文章末尾免费领取 的相关文章

  • 软件测试|Python中如何提取列表中索引为奇数的元素

    简介 在Python中 我们经常需要从列表中提取特定位置的元素 如果我们想要提取列表中索引为奇数的元素 可以使用一些简单的方法来实现这一目标 本文将介绍如何在Python中提取列表中索引为奇数的元素 并提供示例代码来帮助大家更好地理解这个过
  • 软件测试|使用matplotlib绘制平行坐标系图

    简介 绘制平行坐标系图 Parallel Coordinates Plot 是一种用于可视化多维数据的强大方法 在这篇文章中 我们将介绍如何使用Matplotlib库创建平行坐标系图 以及如何解释和定制这种图表 我们将使用一个示例数据集来演
  • 基于java的学生成绩管理系统设计与实现

    基于java的学生成绩管理系统设计与实现 I 引言 A 研究背景和动机 学生成绩管理系统是一个重要的教育工具 能够帮助学校管理学生的成绩和考试结果 以便更好地评估学生的教育水平和发展潜力 Java是一种广泛应用的编程语言 具有跨平台 高效
  • 用CHAT分析高校体育智慧教学体系构建与探索研究现状

    CHAT回复 现阶段 高校体育智慧教学体系的构建与探索研究还处于初级阶段 但全球数字化转型大潮的推动下 一些较为前沿的研究和实践已经开始出现 1 教学平台的建设 很多高校已经开始尝试使用在线教育平台进行体育教学 把传统的面对面授课模式转变为
  • 软件测试|使用Python读写yaml文件,你会了吗?

    简介 YAML YAML Ain t Markup Language 是一种可读的数据序列化格式 它常用于配置文件和数据交换 Python 提供了许多库来处理 YAML 文件 在本文中 我们将探讨如何使用 PyYAML 库来读取和写入 YA
  • 【计算机毕业设计】电商个性化推荐系统

    伴随着我国社会的发展 人民生活质量日益提高 于是对电商个性化推荐进行规范而严格是十分有必要的 所以许许多多的信息管理系统应运而生 此时单靠人力应对这些事务就显得有些力不从心了 所以本论文将设计一套电商个性化推荐系统 帮助商家进行商品信息 在
  • 【计算机毕业设计】电影播放平台

    电影播放平台采用B S架构 数据库是MySQL 网站的搭建与开发采用了先进的java进行编写 使用了springboot框架 该系统从两个对象 由管理员和用户来对系统进行设计构建 主要功能包括 个人信息修改 对用户 电影分类 电影信息等功能
  • 【计算机毕业设计】二手图书交易系统

    随着世界经济信息化 全球化的到来和互联网的飞速发展 推动了各行业的改革 若想达到安全 快捷的目的 就需要拥有信息化的组织和管理模式 建立一套合理 动态的 交互友好的 高效的二手图书交易系统 当前的信息管理存在工作效率低 工作繁杂等问题 基于
  • 【计算机毕业设计】宝鸡文理学院学生成绩动态追踪系统

    研究开发宝鸡文理学院学生成绩动态追踪系统的目的是让使用者可以更方便的将人 设备和场景更立体的连接在一起 能让用户以更科幻的方式使用产品 体验高科技时代带给人们的方便 同时也能让用户体会到与以往常规产品不同的体验风格 与安卓 iOS相比较起来
  • 华为OD机试真题-分披萨-2023年OD统一考试(C卷)

    题目描述 吃货 和 馋嘴 两人到披萨店点了一份铁盘 圆形 披萨 并嘱咐店员将披萨按放射状切成大小相同的偶数扇形小块 但是粗心服务员将披萨切成了每块大小都完全不同奇数块 且肉眼能分辨出大小 由于两人都想吃到最多的披萨 他们商量了一个他们认为公
  • 2024诸多大厂春招提前启动!Android的程序员还在等什么

    春招 提前批 已开 xdm别打瞌睡了 格力 顺丰 酷狗 沃尔玛中国 理想 科大讯飞等开启春招 开始收简历了 还有hc的企业提前抢人 春招时间短 节奏快 招满即止 就算挂了也绝不能不投 对企业来说 秋招和春招都是储备人才的黄金时期 春招中 除
  • Python 文件的复制重命名以及xlsx文件中表格分开保存

    1 需要的头文件 import shutil import os import openpyxl 2 复制文件以及重命名 直接使用shutil库复制 重命名 移动即可 函数封装示例 source path 为全局变量被复制文件路径 dest
  • 计算机Java项目|学生成绩管理系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 计算机Java项目|电影购票系统

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 计算机Java项目|基于SSM的篮球系列网上商城设计与实现

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 计算机Java项目|基于SpringBoot个人空间平台的设计与实现

    作者简介 Java领域优质创作者 CSDN博客专家 CSDN内容合伙人 掘金特邀作者 阿里云博客专家 51CTO特邀作者 多年架构师设计经验 腾讯课堂常驻讲师 主要内容 Java项目 Python项目 前端项目 人工智能与大数据 简历模板
  • 详解Java信号量-Semaphore

    第1章 引言 大家好 我是小黑 今天 咱们一起来深入探讨一下Semaphore 在Java中 正确地管理并发是一件既挑战又有趣的事情 当谈到并发控制 大家可能首先想到的是synchronized关键字或者是ReentrantLock 但其实
  • 【心电图基线估计和去噪方法的群稀疏正则化】带有群稀疏正则化的心电图基线估计和去噪(Matlab实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码及文章
  • 基于节点电价的电网对电动汽车接纳能力评估模型研究(Matlab代码实现)

    欢迎来到本博客 博主优势 博客内容尽量做到思维缜密 逻辑清晰 为了方便读者 座右铭 行百里者 半于九十 本文目录如下 目录 1 概述 2 运行结果 3 参考文献 4 Matlab代码 数据
  • 【C#】基础巩固

    最近写代码的时候各种灵感勃发 有了灵感 就该实现了 可是 实现起来有些不流畅 总是有这样 那样的卡壳 总结下来发现了几个问题 1 C 基础内容不是特别牢靠 理解的不到位 导致自己想出来了一些内容 但是无法使用正确的C 代码实现 导致灵感无法

随机推荐

  • bi工程师面试题_【BI 大数据分析】职业规划 之横纵拓展

    这章有以下内容展示 技术需求与更新方面 挖深后需要了解的方面有那些 关于Linux系统 它在BI大数据分析框架是用来干什么 扮演什么角色 关于SQL编写 Q1 它在BI大数据分析框架是用来干什么 扮演什么角色 Q2 什么时候要用到SQL Q
  • YOLOv5-6.x源码分析(四)---- 模型搭建之yolo.py

    文章目录 前引 YOLOv5 6 x源码分析 四 yolo py 1 导入需要的包 2 parse model 2 1 获取对应参数 2 2 搭建网络的准备 2 3 更新args 计算c2 2 4 使用当前层的参数搭建当前层 2 5 打印并
  • Java在pdf文件中加入文字或图片

    pom 导入itextpdf 依赖
  • Python 印章代码(附有解析)

    1 题目 2 代码 共有n种图案的印章 每种图案的出现概率相同 小A买了m张印章 求小A集齐n种印章的概率 n m map int input split dp 0 for i in range n 1 for j in range m 1
  • 如何用计算机测试交易系统,一种自动售票机交易功能的测试系统和方法与流程...

    本发明涉及一种自动售票机检测领域 尤其是涉及一种自动售票机交易功能的测试系统和方法 背景技术 轨道交通的自动售票机 TVM 在接入线网投用之前 必须进行功能测试 以确保功能完备 交易完整 正常使用 目前的测试方法是通过人工购买车票的方法来测
  • Spring MVC如何进行数据校验呢?

    转自 Spring MVC如何进行数据校验呢 在web开发中 我们需要保证用户输入的合法性 那么SpringMVC中如何保证web 应用的合法性呢 下文将一一道来 如下所示 下文只讲述SpringMVC后端的验证方法 前端验证 由用户自身采
  • 独立按键(多个按键)控制LED移位

    这个代码设置的是两个按键对LED移位 分别是P3 1向右移 P3 0向左移 include
  • pycharm错Error updating package list: connect timed out误:解决(更换镜像源)

    问题 可能是网络问题 导致无法加载 报错 Error updating package list connect timed out 解决 File setting project interpreter 加号 manage reposit
  • vmware+CentOS5.0上安装oracle 10g数据库

    一 针对 Oracle 配置 Linux Linux 软件现已安装完毕 您需要针对 Oracle 对其进行配置 本部分将逐步讲解针对 Oracle 数据库 10g 配置 Linux 的过程 验证系统要求 要验证系统是否满足 Oracle 1
  • Docker简介以及安装使用(一)

    疫情下的上海 按下了暂停键 期待早日重回繁华 上海加油 文章目录 Docker简介 Docker的出现 Docker的优点 Docker的局限性 Docker架构 Docker的安装 Docker简介 Docker 是一个开源的应用容器引擎
  • 反馈判断方法

    负反馈放大器可组合成四种类型 即 电流串联 电流并联 电压串联 电压并联四种负反馈类型 正负反馈的判断 正负反馈的判断使用瞬时极性法 瞬时极性是一种假设的状态 它假设在放大电路的输入端引入一瞬时增加的信号 这个信号通过放大电路和反馈回路回到
  • 设计模式--Template模式 VS Strategy模式

    Template 模式和Strategy模式所要解决的问题类似 而且通常可以互换使用 Template模式使用继承来解决问题 Strategy模式使用委托来解决问题 如图1 template 模式 基类 BubbleSorter实现了通用算
  • 钉钉小程序头像剪切并压缩上传

    引入方式 json文件 usingComponents dd cropper components dd cropper dd cropper axml
  • 个人支付接口

    分享个人可以用的支付接口 用来实现收款实时回调 不用企业资质 不用签约 很方便 1 接口地址 请求地址 https www gogozhifu com shop api createOrder 2 注意事项 数据编码统一为utf 8 Req
  • 仿滴滴打车百度地图定位查找附近出租车或门店信息

    随着技术的发展 开发的复杂度也越来越高 传统开发方式将一个系统做成了整块应用 经常出现的情况就是一个小小的改动或者一个小功能的增加可能会引起整体逻辑的修改 造成牵一发而动全身 通过组件化开发 可以有效实现单独开发 单独维护 而且他们之间可以
  • 前置++与后置++区别 以及效率

    之前在杭州实习面试中科视拓时候面试官问道 前置 与后置 区别 以及效率 打破对C 的认识 后来 寒假回来看书后才恍然大悟 前置 和后置 的区别 C专家编程 中有如下描述 P276 人民邮电出版社 a表示取a的地址 增加它的内容 然后把值放在
  • 2021-Linux系统与管理 - (二)Linux系统命令【超详细】

    自说 Linux命令 Linux命令行的格式 Linux系统的基本命令 自说 学习Linux必定要学习的就是命令了 凡事都是一步一个脚印 这样才踏实 呢么在学习Linux这条道上 我们更加要循序渐进 先学会走再勇往直前 以下便是Linux命
  • 【Mysql】图解左、右、内与全连接

    一 前言 使用学生表与成绩表来演示Mysql中的各种连接查找 学生表的建表语句如下 CREATE TABLE student id int 11 NOT NULL AUTO INCREMENT COMMENT 自增序号 st id int
  • 深度学习的名词解释

    深度学习入门必须理解这25个概念 神经网络基础 1 神经元 Neuron 就像形成我们大脑基本元素的神经元一样 神经元形成神经网络的基本结构 想象一下 当我们得到新信息时我们该怎么做 当我们获取信息时 我们一般会处理它 然后生成一个输出 类
  • 【C语言程序设计实验】试卷管理系统(完整代码+函数详解) -->源代码文件文章末尾免费领取

    目录 实验简介 一 实验要求 二 实验代码 1 完整代码 2 代码解析 1 get next question number 2 add question 3 delete question 4 backup questions 5 del