一起来做一个 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
今生今世伴你左右 ~ 挺好挺好
出题功能的实现
因为是用 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");
}
}
三级项目完成 ~ 是不是还挺简单的 ?
成品也上传到这里啦
没积分的朋友们也可以关注我公众号来拿源码~
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
· PowerShell开发游戏 · 打蜜蜂
· 凌晨三点救火实录:Java内存泄漏的七个神坑,你至少踩过三个!