一起来做一个 c++ 单项选择题标准化考试系统

题目要求

1、问题描述 :

设计一个单项选择题标准化考试系统,该系统要求能自动组卷和评分。

2、功能要求

(1)用文件保存试题库。(每个试题包括题干、4 个备选答案、标准答案)。
(2)试题录入:可随时增加试题到试题库中。
(3)试题抽取:每次从试题库中可以随机抽出 N 道题(N 由键盘输入)。
(4)答题:用户可实现输入自己的答案。
(5)自动判卷:系统可根据用户答案与标准答案的对比实现判卷并给出成绩。
(6)退出。

思路分析

考试系统,得有题目,先做一个题目类,就定义这些变量吧
在这里插入图片描述
然后对这个题进行分析归纳,通过功能要求初步确定要有这些模块~
在这里插入图片描述
有登录模块当然也应该有包含用户名和密码的用户类啦
在这里插入图片描述
简简单单~

接下来分别实现各个模块

各个模块的实现

题目类的创建

创建Timu.h头文件,然后随便写上变量就完事了~上代码:

class Timu {
public:
    Timu() {}
    ~Timu() {}
    string tigan;
    string A, B, C, D;
    char answer;
    void show() {
        cout << tigan << endl;
        cout << "A." << A << endl;
        cout << "B." << B << endl;
        cout << "C." << C << endl;
        cout << "D." << D << endl;
    }
};

管理题库模块的实现

整个题库用一个 Timu 类型的 vector 实现。
管理题库这事哪能是什么人都能干的?当然要设置权限了

bool quanxian()
{
    cout << "请输入密码来证明您的权限" << endl;
    string c;
    cin >> c;
    return c == "73748156";
}

7 3 7 4 8 1 5 6
今生今世伴你左右 ~ 挺好挺好

扫描二维码关注公众号,回复: 11373011 查看本文章

出题功能的实现

因为是用 vector 实现的题库,所以直接输入相关信息后插入 vector 就行,简简单单,看代码:

void addTimu(vector<Timu>& a) {
    Timu temp;
    string s, A, B, C, D, ans;
    cout << "请输入题干" << endl;
    cin >> temp.tigan;
    cout << "请输入A选项" << endl;
    cin >> temp.A;
    cout << "请输入B选项" << endl;
    cin >> temp.B;
    cout << "请输入C选项" << endl;
    cin >> temp.C;
    cout << "请输入D选项" << endl;
    cin >> temp.D;
    cout << "请输入正确选项" << endl;
    cin >> temp.answer;
    if (temp.answer >= 'a' && temp.answer <= 'z')temp.answer = temp.answer - 32;
    a.push_back(temp);
    cout << "添加完成" << endl;
}

突然觉得这个三级项目写的没有激情。。。。有点简单。。
在这里插入图片描述

题目的存储与读取

大概不能每次考试都重新打一遍题。。。太不人性化了
就把题库存到本地文件里吧
这里要用到c++文件流来实现,上代码
存储:

void save(vector<Timu>& a)
{
    ofstream ofs;
    ofs.open(FILENAME, ios::out);
    for (auto& i : a) {//录入每道题信息
        ofs << i.tigan << "\n" << i.A << "\n" << i.B << "\n"
            << i.C << "\n" << i.D << "\n" << i.answer << endl;
        //将所有信息存储
    }
    cout << "保存成功" << endl;
    ofs.close();//关闭文件
}

读取也差不多

void fetch(vector<Timu>& a)
{
    ifstream ifs;
    ifs.open(FILENAME, ios::in);//读文件
    if (!ifs.is_open())//判断是否存在
    {
        cout << "题库文件不存在" << endl;
        ifs.close();
        return;
    }

    Timu i;
    while (ifs >> i.tigan >> i.A >> i.B >> i.C >> i.D >> i.answer)//信息读取到temp中
    {
        a.push_back(i);
    }
    ifs.close();
    if (a.empty())
    {
        cout << "题库为空" << endl;
    }
    else
        cout << "当前题目数目为" << a.size() << "道" << endl;
}

把读取加在主函数里,保存放到出题同级菜单下就好

封装题库管理模块

加一个满足理科生审美的菜单

void showMenu2()
{
    cout << "*********************************" << endl;
    cout << "*******     学习使我快乐     ******" << endl;
    cout << "*******      出题请按 1      ******" << endl;
    cout << "*******    保存题库请按 2     ******" << endl;
    cout << "*******      退出请按 0     ******" << endl;
    cout << "*********************************" << endl;
}

我爱学习,学习使我快乐!
在这里插入图片描述

用switch实现整理题库的封装函数

void arrangeTiku(vector<Timu>& a) {

    char c;
    while (true)
    {
        showMenu2();
        cin >> c;
        switch (c) {
        case '0'://退出
            return;
        case '1'://出题
            addTimu(a);
            break;
        case '2'://保存
            save(a);
            break;
        }
        system("pause");
        system("cls");
    }
}

完美 ~ ~ 此处应该有掌声鼓励!

考试模块的实现

抽题功能的实现

c++没有封装随机数的方法,查了好多才知道该怎么在一定范围内取随机数,先加个这个#define random(x) (rand()%x)
然后在函数中这样调用就可以在指定范围内出随机数啦 ~
肯定要读入 N(抽取题目数量),把 N 传进函数里

void chouTimu(vector<Timu>a, vector<Timu>& b, int N)
{
    int x;
    for (int i = 0; i < N; ++i) {
        x = random(a.size());
        b.push_back(a[x]);
        a.erase(a.begin() + x);
    }
}

将抽出来的题目存在一个新的 Timu 类型 vector 中就完事啦 ~ 轻轻松松 ~ ~ ~

答题功能的实现

传入刚才抽出来的题目,读入答案,判断并记数,最后返回成绩

int answerTi(vector<Timu>a) {
    char c;
    int x = 0;
    for (int i = 0; i < a.size(); ++i) {
        a[i].show();
        cout << "请输入你的答案" << endl;
        cin >> c;
        if (c >= 'a' && c <= 'z')c = c - 32;
        if (c == a[i].answer)x++;
    }
    return 100 * x / a.size();
}

啧 ~ 这三级项目就快要完事了

考试模块的封装

读入要答题的数目,注意判断下题库里题目够不够就行

简简单单,直接上代码

void takeExam(vector<Timu>& a) {
    cout << "请输入你想要答题的数目" << endl;
    int N;
    cin >> N;
    if (N > a.size())
    {
        cout << "当前题目数量不足" << endl;
        return;
    }
    vector<Timu>b;
    chouTimu(a, b, N);
    int score = answerTi(b);
    cout << "你的成绩是" << score << endl;
}

完事,下一个 ~
在这里插入图片描述

用户类的创建

没啥可说的,就这俩变量

class User {
public:
    string password;
    string userName;
};

太简单,感觉他不配二级目录。。。。。

登录模块的创建

无非就是注册和登录,记得注册的时候把他用文件流存到本地文件里,下次还能登录就好 ~
先声明一个判断用户名是否存在的函数
代码如下:

int isUserExist(string name, vector<User>u) {
    for (int i = 0; i < u.size(); ++i) {
        if (u[i].userName == name) return i;
    }
    return -1;
}

接着是注册的代码:

void zhuce(vector<User>& u)
{
    string password;
    User tmp;
    string name;
    cout << "请输入用户名" << endl;
    cin >> name;
    int a = isUserExist(name, u);
    if (a == -1)
    {
        tmp.userName = name;
        cout << "请输入密码" << endl;
        cin >> password;
        tmp.password = password;
        u.push_back(tmp);
        ofstream ofs;
        ofs.open(FILENAME2, ios::out);
        for (auto& i : u) {//录入用户信息
            ofs << i.userName << " " << i.password << endl;
        }
        cout << "保存成功" << endl;
        ofs.close();//关闭文件
    }
    else cout << "该用户名已被使用,注册失败" << endl;
}

要记得判断用户名是否重复,以免出现问题 ~

然后是登录的代码:

bool denglu(vector<User>& u) {
    string name, password;
    cout << "请输入用户名" << endl;
    cin >> name;
    int a = isUserExist(name, u);
    if (a == -1) {
        cout << "用户名不存在,登录失败" << endl;
        return false;
    }
    else
    {
        cout << "请输入密码" << endl;
        cin >> password;
        if (u[a].password == password) {
            cout << "登录成功" << endl;
            return true;
        }
        else
        {
            cout << "密码错误,登录失败" << endl;
            return false;
        }
    }
}

遍历判断密码对不对就行

然后做一个美丽的菜单

void showMenu3() {
    cout << "*********************************" << endl;
    cout << "*******     学习使我快乐     ******" << endl;
    cout << "*******      登录请按 1      ******" << endl;
    cout << "*******      注册请按 2     ******" << endl;
    cout << "*******      退出请按 0     ******" << endl;
    cout << "*********************************" << endl;
}

注意这里要停一会,好好欣赏下菜单再往下 ~ ~ ~ ~
在这里插入图片描述

最后封装到一起就好啦

主函数的封装

创建两个 vector ,然后读入本地文件到 vector 中,接后边的主菜单函数,通过主菜单函数封装所有模块 ~

int main() {
    vector<Timu>tiku;
    vector<User>yonghu;
    fetch(tiku);
    fetchUser(yonghu);
    select(tiku, yonghu);
    return 0;
}

主菜单选项的封装

要先做一个主菜单

void showMenu1()
{
    cout << "******************************" << endl;
    cout << "*******   学习使我快乐    ******" << endl;
    cout << "*******    考试请按 1     ******" << endl;
    cout << "*******   整理题库请按 2   ******" << endl;
    cout << "*******    退出请按 0     ******" << endl;
    cout << "******************************" << endl;
}

样式还是依旧绝色

void select(vector<Timu>& a, vector<User>& b) {
    char s,choose0;
    int h = 0;
    do {
        showMenu3();
        cin >> choose0;
        switch (choose0)
        {
        case'1'://登录
            if (denglu(b))
            {
                h = 1;
                break;
            }
            else
                continue;
        case'2'://注册
            zhuce(b);
            break;
        case'0':
            cout << "欢迎下次使用" << endl;
            return;
        }
        system("pause");
        system("cls");
    } while ((choose0 != '0' && h != 1));
    while (true)
    {
        showMenu1();
        cin >> s;
        switch (s) {
        case '0'://退出
            cout << "欢迎下次使用" << endl;
            return;
        case '1'://考试
            takeExam(a);
            break;
        case '2'://整理题库
            if (quanxian())
                arrangeTiku(a);
            else cout << "密码错误,您没有权限" << endl;
            break;
        default:
            cout << "指令错误,请重新输入" << endl;
            break;
        }
        system("pause");
        system("cls");
    }
}

三级项目完成 ~ 是不是还挺简单的 ?
在这里插入图片描述
成品也上传到这里啦

燕大的朋友们也可以私信找我要代码的
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_46039856/article/details/106586344