概述
本项目包括 学生发展与数据驱动平台6.2.cpp
、学生信息.txt
、用户账号.txt
、注意事项.txt
。运行代码前前先仔细看 注意事项
。
如图:
IDE
注意事项.txt
内容如下:
1. “学生信息.txt”、“用户账号.txt”需要用ANSI编码,否则会中文乱码。
2. “学生信息.txt”、“用户账号.txt”需要与本cpp文件处于同一目录下。
3. 尽量不要直接打开“学生信息.txt”修改信息,除非你清楚以下要求:
3.1 学号是12位没有前导0的正数,且具有唯一性。
3.2 “学生信息.txt”依次存储每一位学生的信息。对于某一位学生,
依次存储学号、姓名、语文成绩、数学成绩、英语成绩和总成绩。
3.3 如果因为某些bug导致“学生信息.txt”出现错误信息,你可以直接
打开它修改学生信息。
4. 如果你不想改变“学生信息.txt”,运行程序的时候需要保证:
4.1 程序开始的时候选择[n]
4.2 弹出菜单的时候不要选择[0]
5. 同[3],“用户账号.txt”只有你清楚各项数据的含义、格式要求的时候才允许你进行手动更改。
6. 对用户账号的操作是实时更新到硬盘中的,不同于对于学生信息的操作:允许每次操作后选择是否更新到硬盘。
7. 第一个管理员权限用户账号需要手动添加到“用户账号.txt”文件中,不过现在这个文件中已经有管理员账号了,可以通过管理员来赋予普通用户管理员身份。
8. 推荐小熊猫C++运行代码,其他IDE可能会出现中文乱码现象,这就需要你自己调整编码了。
9. 当前代码功能并不完善,在我觉得代码已经够好之前,会不定时更新代码。
学生信息.txt
内容如下:
540307010223 陆长生 90 73 83 246
540307130223 叶秋白 63 45 75 183
540307250105 红缨 73 47 47 167
540307010315 石生 74 47 77 198
540307010225 石昊 98 93 32 223
540307010325 唐三 39 45 93 177
540307010327 千仞雪 82 23 99 204
540307250104 千道流 48 93 70 211
540307290130 波塞西 34 93 83 210
980654321048 唐晨 99 99 99 297
123456789452 比比东 78 80 99 257
540207010315 MXT 100 100 100 300
567643532432 卡拉米 57 45 98 200
835902340238 路人甲 60 60 60 180
323290480824 路人乙 70 70 70 210
843492304421 路人丙 65 65 65 195
555555553826 小白 99 99 99 297
540207010312 Github 59 100 100 259
666666666666 麦克阿瑟 100 59 100 259
114514114514 一二三四五六七 100 60 79 239
用户账号.txt
内容如下:
100000 password2656 1 你学号是什么? 542207010315
1000000 password1 0 MXT的学号是什么? 542207010315
100000023 password331 0 MXT是几班的(输入一个1~3内的整数)? 3
2656512631 11111111aaaa 0 huanzi是谁? WH
114546 114546a123 0 lsq是谁? zheshidaan
学生发展与数据驱动平台6.2.cpp
更新日志:
12.7 发布
12.8 更新,登录界面将输入的密码以 *
显示,更加安全。
C
o
d
e
Code
Code
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <iomanip> // 包含C++的格式化输出库函数setw()
#include <fstream> // 包含用于文件读入、写入的类“ifstream”
#include <sstream> // 包含用于按照空格分离字符串的类“stringstream”
#include <conio.h> // conio.h是Windows特有的,不属于标准的C/C++头文件,包含getch()
#include <string>
#include <vector>
#include <ctime> // 用于实时输出时间
#include <map>
#define int long long // 全局的整型均为long long
using namespace std;
const int inf = 1e18;
struct student{
int id; // 学号
string name; // 姓名
int Chinese; // 语文成绩
int math; // 数学成绩
int English; // 英语成绩
int sum; // 总成绩
};
class User{
public:
long long ID; // 账号 account number(6~10位正整数)
string password; // 8~16位,含有数字和字母,字符只能是ASCII表33~126范围内
bool admin; // 是否拥有管理员权限
string question; // 找回密码时的问题(不含空格的字符串[长度1~40])
string answer; // 找回密码时的答案(不含空格的字符串[长度1~40])
};
bool cmp_id_in(student x, student y) {
return x.id < y.id;
}
bool cmp_id_de(student x, student y) {
return x.id > y.id;
}
bool cmp_sum_in(student x, student y) {
return x.sum < y.sum;
}
bool cmp_sum_de(student x, student y) {
return x.sum > y.sum;
}
void log_in(); // 使用账号登录(普通账号,管理员账号)
void startup_welcome(); // 欢迎页面
void add_student(int add_num, int first_ist_idx); // 有add_num组学生信息需要添加,从指定位置开始依次向后插入
void get_all_student(); // 输出所有学生的信息
void sorted_in_id(); // 按照学号排序
void sorted_in_sum(); // 按照总成绩排序
void change_in_id(); // 按照学号批量修改信息
void change_in_name(); // 按照姓名批量修改信息
void change_single(int idx); // 修改students[i]的各项信息
void delete_in_id(); // 按照学号批量删除学生的信息
void delete_in_name(); // 按照姓名批量删除学生的信息
void find_in_id(); // 按学号查找学生信息
void find_in_name(); // 按姓名查找学生信息
int is_integer(string str); // 如果str代表一个整数,返回这个整数;否则返回-inf
int line_number(); // 直到读取一行代表一个数字的字符串,返回这个数字
string line_string(); // 直到读取一行不含空格的字符串,返回这个字符串
void print_in_idx(int idx);// 输出students[i]学生的信息
void print_list_head(); // 输出表头
void read_information(); // 读入硬盘中的学生信息
void save_information(); // 把学生信息保存到硬盘
string change_for_output(string s); // 字符串长度超过8的部分用"..."代替
string get_now_time(); // 返回一个格式化的时间字符串
void EXIT(){cout << "程序已退出\n";exit(0);} // 退出系统
bool password_format(string s); // 判断这个字符串是否符合密码的格式要求
void read_user_id(); // 读入账号密码
void save_user_id(); // 保存账号密码
int find_account_number(int numb); // 返回账号在数组中下标,不存在则返回-1
void backstage(); // 管理员专属后台,可以对用户账号进行操作
void get_all_users(); // 输出所有用户的信息
void print_in_idx_user(int idx); // 输出us[i]用户的信息
void change_user_rights(); // 改变某个用户的权限
void delete_in_id_users(); // 按照账号批量删除用户
string hide_password(); // 输入的密码以'*'显示
vector <student> students; // 保存所有的学生信息
vector <User> us; // 保存用户信息(账号、密码、密保信息、权限)
bool ADMIN = 0; // 当前用户是否拥有管理员权限
map<int, int> mp_id; // 标记存在的学号
signed main() {
system("color 0F");
log_in();
return 0;
}
void log_in() {
read_user_id();
while (1) {
cout << "\n---请输入你的账号密码---\n";
cout << "其他选项:[-1]退出系统,[0]找回密码,[1]注册账号\n";
cout << "账号->";
int op = line_number();
if (op == -1) {
cout << "你选择了[-1]退出系统\n";
EXIT();
} else if (op == 0) {
cout << "你选择了[0]找回密码\n";
int ID;
while (1) {
cout << "请输入你要找回密码的账号(6~10位正整数)->\n";
ID = line_number();
if (ID >= 100000 && ID <= 9999999999) {
int found = 0;
for (auto p : us) {
if (p.ID == ID) {
int num = 3;
while (num --) {
cout << "请回答你设置的密保问题:\n";
cout << p.question << "\n";
string ans; getline(cin, ans);
if (p.answer == ans) {
cout << "你的密码是[" << p.password << "],不要再忘了~\n";
break;
} else {
if (num) {
cout << "答案错误,还有" << num << "次机会,笨蛋~\n";
} else {
cout << "密码和密保都记不住,你小子真是个人才(-_- )自己去找管理员吧\n";
}
}
}
found = 1;
break;
}
}
if (found) {
break;
} else {
cout << "你输入的账号不存在\n";
}
} else {
cout << "你输入的账号过长或过短\n";
}
}
} else if (op == 1) {
cout << "你选了[1]注册账号\n";
bool OK = 0;
while (OK == 0) {
cout << "请输入你要注册的账号(6~10位正整数)->";
int ID = line_number();
if (ID >= 100000 && ID <= 9999999999) {
int found = 0;
for (auto p : us) {
if (p.ID == ID) {
found = 1;
break;
}
}
if (found) {
cout << "你要注册的账号已经存在!\n";
} else {
User u;
u.ID = ID;
while (OK == 0) {
cout << "请输入8~16位密码,要求含有数字和字母,字符只能是ASCII表33~126范围内->";
string pw = line_string();
if (password_format(pw)) {
cout << "请牢记你的密码:[" << pw << "]\n";
u.password = pw;
cout << "请输入密保问题(不含空格,最多50个字节)->";
while (1) {
u.question = line_string();
if (u.question.size() > 50) {
cout << "太长了\n";
} else {
cout << "密保问题满足要求~\n";
break;
}
}
cout << "请输入密保答案(不含空格,最多50个字节)->";
while (1) {
u.answer = line_string();
if (u.answer.size() > 50) {
cout << "太长了\n";
} else {
cout << "密保问题满足要求~\n";
OK = 1;
break;
}
}
us.push_back(u);
save_user_id();
} else {
cout << "你输入的密码格式不符合要求\n";
}
}
}
} else {
cout << "你输入的账号过长或过短\n";
}
}
} else {
if (op >= 100000 && op <= 9999999999) {
User u;
u.ID = op;
int idx = find_account_number(op);
if (idx == -1) {
cout << "账号[" << op << "]不存在\n";
} else {
int num = 5;
while (num --) {
cout << "请输入账号[" << op << "]的密码(8~16位)->";
string pw = hide_password();
if (us[idx].password == pw) {
if (us[idx].admin) {
ADMIN = 1;
}
cout << "欢迎登录,当前账号为$" << (ADMIN ? "管理员用户" : "普通用户") << "$\n\n";
startup_welcome();
return;
} else {
if (num) {
cout << "密码错误还有" << num << "次机会,笨蛋~\n";
} else {
cout << "你试错次数已经用完,请重新登录QAQ\n";
break;
}
}
}
}
} else {
cout << "你输入的账号是负数,或长度过长、过短QAQ\n";
}
}
}
}
void startup_welcome() { // 主页面
read_information();
int save_for_every_op = -1;
while (save_for_every_op == -1) {
cout << "是否每次操作之后都保存信息到硬盘[y/n]?";
string op = line_string();
if (op == "y") {
save_for_every_op = 1;
} else if (op == "n") {
save_for_every_op = 0;
}
}
if (save_for_every_op == 1) {
cout << "学生信息将在每次操作之后更新到硬盘~\n";
} else {
cout << "学生信息不会自动更新到硬盘。如果你需要更新,需要手动操作。\n";
}
system("cls");
while (1) {
printf("\n**********************************************************************************************\n");
cout <<"$ 欢迎使用学生信息管理系统(时间:" << get_now_time() << ") $\n";
printf("$ [1] 录入学生信息(ADMIN) $\n");
printf("$ [2] 输出所有学生成绩 $\n");
printf("$ [3] 按学号查找学生信息 $\n");
printf("$ [4] 按姓名查找学生信息 $\n");
printf("$ [5] 按位置查找学生信息 $\n");
printf("$ [6] 按学号对学生排序 $\n");
printf("$ [7] 按总成绩对学生排序 $\n");
printf("$ [8] 按学号修改学生信息(ADMIN) $\n");
printf("$ [9] 按姓名修改学生信息(ADMIN) $\n");
printf("$ [10] 按学号删除某条学生信息(ADMIN) $\n");
printf("$ [11] 按姓名删除某条学生信息(ADMIN) $\n");
printf("$ [12] 在指定位置添加一条学生信息(ADMIN) $\n");
if (save_for_every_op == 0) {
printf("$ [0] 将学生信息写入硬盘 $\n");
}
printf("$ [-1] 退出程序 $\n");
printf("$ [100] 清屏 $\n");
printf("$ [101] 进入管理员专属后台(ADMIN) $\n");
printf("**********************************************************************************************\n");
printf("请输入您的选择(-1 ~ 0,1 ~ 12,100。不能含有多余空格):\n");
int wrong_numb = 0;
string line; getline(cin, line);
int choice = is_integer(line);
if (save_for_every_op == 0 && choice == 0) {
cout << "学生信息已经写入硬盘\n";
save_information();
continue;
}
switch (choice) {
case 1:{
if (ADMIN) {
printf("用户选择了数字1,录入学生信息\n");
printf("请输入录入的学生数量:\n");
int add_num = line_number();
add_student(add_num, students.size());
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
}
case 2:
printf("用户选择了数字2,查询所有数据\n");
get_all_student();
break;
case 3:
printf("用户选择了数字3,按学号查找学生信息\n");
find_in_id();
break;
case 4:
printf("用户选择了数字4,按姓名查找学生信息\n");
find_in_name();
break;
case 5:{
printf("用户选择了数字5,按位置查找学生信息\n");
int len = students.size();
while (1) {
printf("请问你要查找第几个位置的学生的信息[1~%lld]?\n", len);
int pos = line_number();
if (pos >= 1 && pos <= len) {
print_list_head();
print_in_idx(pos - 1);
break;
} else {
printf("是不是憨憨,让你输入的位置范围是[1~%lld],艹\n", len);
}
}
break;
}
case 6:
printf("用户选择了数字6,按学号排序\n");
sorted_in_id();
break;
case 7:
printf("用户选择了数字7,按总成绩排序\n");
sorted_in_sum();
break;
case 8:
if (ADMIN) {
printf("用户选择了数字8,按学号修改学生信息\n");
change_in_id();
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
case 9:
if (ADMIN) {
printf("用户选择了数字9,按姓名修改学生信息\n");
change_in_name();
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
case 10:
if (ADMIN) {
printf("用户选择了数字10,按学号删除某条学生信息\n");
delete_in_id();
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
case 11:
if (ADMIN) {
printf("用户选择了数字11,按姓名删除某条学生信息\n");
delete_in_name();
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
case 12:{
if (ADMIN) {
printf("用户选择了数字12,在指定位置添加一条学生信息\n");
int len = students.size();
while (1) {
printf("请问你要将信息添加到第几个位置[1~%lld]?\n", len + 1);
int pos = line_number();
if (pos >= 1 && pos <= len + 1) {
add_student(1, pos - 1);
break;
} else {
printf("是不是憨憨,让你输入的位置范围是[1~%lld],艹\n", len + 1);
}
}
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
}
case -1:
EXIT();
case 100:
system("cls");
break;
case 101:
if (ADMIN) {
backstage();
} else {
cout << "您没有该操作的权限亲~\n";
}
break;
default:
wrong_numb = 1;
printf("请输入正确的数字\n");
}
if (save_for_every_op) {
save_information();
}
if (wrong_numb == 0 && choice != 100) {
int retn = 0;
while (retn == 0) {
cout << "若要返回主菜单,请输入[r]:\n";
string op; getline(cin, op);
if (op == "r") {
retn = 1;
}
}
}
}
}
void add_student(int add_num, int first_ist_idx) {
for (int i = 1; i <= add_num; i ++) {
printf("请输入第%lld个学生的信息\n", i);
student stu;
printf("请输入12位学号:");
while (1) {
stu.id = line_number();
if (stu.id >= 100000000000 && stu.id <= 999999999999) {
break;
} else {
cout << "学号太短辣,请输入12位数字~\n";
}
}
if (mp_id[stu.id]) {
printf("学号已经存在!\n");
printf("请选择:[1:重新输入][2:直接调过当前学生]:");
int op = -1;
while (op != 1 && op != 2) {
op = line_number();
}
if (op == 1) {
i --;
}
continue;
}
mp_id[stu.id] = 1;
printf("请输入学生的名字(不能有空格):\n");
stu.name = line_string();
printf("请输入语文成绩:\n");
stu.Chinese = line_number();
printf("请输入数学成绩:\n");
stu.math = line_number();
printf("请输入英语成绩:\n");
stu.English = line_number();
stu.sum = stu.Chinese + stu.math + stu.English;
students.insert(students.begin() + first_ist_idx ++, stu);
}
printf("所有学生数据已经录入\n");
}
void get_all_student() {
print_list_head();
int len = students.size();
for (int i = 0; i < len; i ++) {
print_in_idx(i);
}
printf("**********************************************************************************************\n\n");
}
void sorted_in_id() {
while (1) {
printf("根据学号按照升序还是降序排序[1:升序][2:降序]?");
string op = line_string();
if (op == "1") {
sort(students.begin(), students.end(), cmp_id_in);
break;
} else if (op == "2") {
sort(students.begin(), students.end(), cmp_id_de);
break;
} else {
printf("非法输入\n");
}
}
}
void sorted_in_sum() {
while (1) {
printf("根据总成绩按照升序还是降序排序[1:升序][2:降序]?");
string op = line_string();
if (op == "1") {
sort(students.begin(), students.end(), cmp_sum_in);
break;
} else if (op == "2") {
sort(students.begin(), students.end(), cmp_sum_de);
break;
} else {
printf("非法输入\n");
}
}
}
void change_in_id() {
while (1) {
printf("请输入你需要修改信息的学号(输入-1退出按照学号修改信息程序):");
int id = line_number();
if (id == -1)
break;
// cout << "mp_id[" << id << "] = " << mp_id[id] << "\n";
int found = 0;
int Size = students.size();
for (int i = 0; i < Size; i ++) {
if (students[i].id == id) {
change_single(i);
found = 1;
}
}
if (not found) {
printf("[%lld]没有这个人\n", id);
}
}
}
void change_in_name() {
while (1) {
printf("请输入你需要修改信息的姓名(输入-1退出按照姓名修改信息程序):");
string Name = line_string();
if (Name == "-1") {
break;
}
int found = 0;
int Size = students.size();
for (int i = 0; i < Size; i ++) {
if (Name == students[i].name) {
change_single(i);
found = 1;
}
}
if (not found) {
cout << "[" << Name << "]" << "没有这个人\n";
}
}
}
void change_single(int idx) {
while (1) {
print_list_head();
auto& [id, name, Chin, math, Engl, sum] = students[idx];
cout << id << "\t\t" << name << "\t\t" << Chin << "\t\t" << math << "\t\t" << Engl << "\t\t" << sum << "\n";
printf("输入你要修改的项:[-1:退出修改该学生的信息][0:学号][1:姓名][2:语文][3:数学][4:英语]:\n");
int op = line_number();
switch (op) {
case -1:
cout << "该学生信息的修改已结束\n";
return;
case 0:
printf("输入新的12位学号:\n");
int new_id;
while (1) {
new_id = line_number();
if (new_id >= 100000000000 && new_id <= 999999999999) {
break;
} else {
cout << "学号太短辣,请输入12位数字~\n";
}
}
mp_id[id] = 0;
mp_id[new_id] = 1;
id = new_id;
break;
case 1:{ // switch的case里边如果要定义string字符串,需要用花括号括住这个case里边的语句
printf("输入新姓名:\n");
name = line_string();
break;
}
case 2:
printf("请输入新语文分数:\n");
Chin = line_number();
break;
case 3:
printf("请输入新数学分数:\n");
math = line_number();
break;
case 4:
printf("请输入新英语分数:\n");
Engl = line_number();
break;
default:
printf("就这么几个简单的数字,还能输错?\n");
}
sum = Chin + math + Engl;
}
}
void delete_in_id() {
printf("请依次输入要删除的学生的学号,以[回车]隔开。输入[-1]结束。\n");
while (1) {
int id_delete = line_number();
if (id_delete == -1) {
printf("信息删除系统即将退出\n");
return;
}
if (mp_id[id_delete]) {
mp_id[id_delete] = 0;
int len = students.size();
for (int i = 0; i < len; i ++) {
if (students[i].id == id_delete) {
students.erase(students.begin() + i);
cout << "该学生信息已删除\n";
break;
}
}
} else {
printf("系统中不存在学号为%lld的学生\n", id_delete);
}
}
}
void delete_in_name() {
printf("请依次输入要删除的学生的姓名,以[回车]隔开。输入[-1]结束。\n");
while (1) {
string name_delete = line_string();
if (name_delete == "-1") {
printf("信息删除系统即将退出\n");
return;
}
int found = 0;
int len = students.size();
for (int i = 0; i < len; i ++) {
if (students[i].name == name_delete) {
found = 1;
printf("找到学号为%lld的学生,输入[y]删除该学生信息,", students[i].id);
printf("输入[-1]退出信息删除系统,输入其他跳过该学生:\n");
string op = line_string();
if (op == "y") {
mp_id[students[i].id] = 0;
students.erase(students.begin() + i);
i --;
len --;
cout << "该学生信息已删除\n";
} else if (op == "-1") {
return;
} else {
continue;
}
}
}
if (not found) {
cout << "系统中不存在名字是[" << name_delete << "]的学生\n";
}
}
}
int is_integer(string str) { // 如果str代表一个整数且-1e12<=numb<=1e12,返回这个整数;否则返回-inf
// cout << "str:[" << str << "]\n";
int number = 0;
int not_number = 0;
int res = 0;
for (auto p : str) {
if (p >= '0' && p <= '9') {
number ++;
res = res * 10 + p - '0';
} else {
not_number ++;
}
}
if ((not_number == 0 || (number && not_number == 1 && str[0] == '-')) && number <= 12) { // str代表一个整数
if (str[0] == '-') return -1 * res;
return res;
} else {
return -inf;
}
}
void find_in_id() {
printf("请输入要查询的学生的学号,以空格隔开。输入[-1]结束。\n");
string line;
getline(cin, line); // 读入一行字符串
stringstream line_stream; // 字符串数据流,可以从中读取数据,也可以将数据写入到其中
line_stream.str(line); // 将line当做一个数据流存储到linestream字符串中
string id_find;
print_list_head();
vector <string> a;
while (line_stream >> id_find) {
if (id_find == "-1") {
printf("信息查询系统即将退出\n");
break;
}
int x = is_integer(id_find);
if (x >= 0) { // 输入的学号是自然数/即有可能作为一个学号
if (mp_id[x]) {
int len = students.size();
for (int i = 0; i < len; i ++) {
if (students[i].id == x) {
print_in_idx(i); // 输出这个学生的数据
break;
}
}
} else {
string s = "[" + to_string(x) + "]对应的学生不存在\n";
a.emplace_back(s);
}
} else {
string s = "[" + id_find +"]学号只能是12位正整数\n";
a.emplace_back(s);
}
}
for (auto p : a) cout << p;
}
void find_in_name() {
printf("请输入要查找的学生的姓名,以空格隔开。输入[-1]结束。\n");
string line;
getline(cin, line); // 读入一行字符串
stringstream line_stream; // 字符串数据流,可以从中读取数据,也可以将数据写入到其中
line_stream.str(line); // 将line当做一个数据流存储到linestream字符串中
string name_find;
print_list_head();
vector <string> a;
while (line_stream >> name_find) {
if (name_find == "-1") {
printf("信息查找系统即将退出\n");
break;
}
int found = 0;
int len = students.size();
for (int i = 0; i < len; i ++) {
if (students[i].name == name_find) {
print_in_idx(i);
found = 1;
}
}
if (found == 0) {
string s = "[" +name_find + "]这个人不存在\n";
a.emplace_back(s);
}
}
for (auto p : a) cout << p;
}
void print_in_idx(int idx) {
auto [id, name, Chin, math, Engl, sum] = students[idx];
cout << id << "\t\t" << left << setw(16) << change_for_output(name) << Chin << "\t\t" << math << "\t\t" << Engl << "\t\t" << sum << "\n";
}
void print_list_head() {
printf("\n**********************************************************************************************\n");
printf("学号\t\t\t姓名\t\t语文\t\t数学\t\t英语\t\t总成绩\n");
}
void read_information() { // 读入硬盘内容(学生信息)
ifstream ip_file;
ip_file.open("学生信息.txt");
if (ip_file.is_open()) {
int id_read;
while (ip_file >> id_read) {
string name;
int Chin, math, Engl, sum;
ip_file >> name >> Chin >> math >> Engl >> sum;
students.push_back({id_read, name, Chin, math, Engl, sum});
mp_id[id_read] = 1;
}
ip_file.close();
} else {
cout << "无法读取硬盘中的学生信息!\n";
}
}
void save_information() { // 保存学生信息到硬盘
ofstream op_file;
op_file.open("学生信息.txt");
if (op_file.is_open()) {
for (auto p : students) {
auto [id, name, Chin, math, Engl, sum] = p;
op_file << id << "\t\t" << left << setw(16) <<
name << Chin << "\t\t" << math << "\t\t" << Engl << "\t\t" << sum << "\n";
}
op_file.close();
} else {
cout << "无法保存学生信息到硬盘!\n";
}
}
int line_number() {
while (1) {
// cin.ignore(); // 忽略一个字符,通常用于忽略回车键或换行符
string s; getline(cin, s);
if (is_integer(s) == -inf) { // 如果s代表的数字不在[-1e12, 1e12]范围内,或表示的不是一个数字
cout << "输入的内容不是数字,或者数字过长,请重新输入\n";
} else {
return is_integer(s);
}
}
}
string line_string() {
while (1) {
string s; getline(cin, s);
if (s.find(' ') == s.npos) {
return s;
} else {
cout << "输入的内容含有空格,请重新输入\n";
}
}
}
string change_for_output(string s) {
return s.substr(0, 8) + (s.size() > 8 ? "..." : "");
}
string get_now_time() { // 返回一个格式化的时间字符串
time_t timer;
struct tm *now;
time(&timer);
now = localtime(&timer);
string s = asctime(now);
return s.substr(0, s.size() - 1);
}
void read_user_id() {
ifstream ip_file;
ip_file.open("用户账号.txt");
if (ip_file.is_open()) {
int id_read;
while (ip_file >> id_read) {
string password;
bool admin;
string question, answer;
ip_file >> password >> admin >> question >> answer;
us.push_back({id_read, password, admin, question, answer});
}
cout << "账号信息读取完毕~\n";
ip_file.close();
} else {
cout << "无法读取硬盘中的账号信息!\n";
}
}
void save_user_id() {
ofstream op_file;
op_file.open("用户账号.txt");
if (op_file.is_open()) {
for (auto p : us) {
auto [id, pw, ad, qu, an] = p;
op_file << id << "\t\t" << pw << "\t\t" << ad << "\t\t" << qu << "\t\t" << an << "\n";
}
} else {
cout << "无法保存用户账号到硬盘\n";
}
}
bool password_format(string s) { // 8~16位,含有数字和字母,字符只能是ASCII表33~126范围内
if (s.size() < 8 || s.size() > 16)
return 0;
int ok = 1;
int number = 0;
int letter = 0;
for (auto p : s) {
if (p < 33 || p > 126) {
ok = 0;
break;
}
if (p >= 'a' && p <= 'z' || p >= 'A' && p <= 'Z') {
letter ++;
}
if (p >= '0' && p <= '9') {
number ++;
}
}
return ok && number && letter;
}
int find_account_number(int numb) {
int len = us.size();
for (int i = 0; i < len; i ++) {
if (us[i].ID == numb) {
return i;
}
}
return -1;
}
void backstage() { // 管理员专属后台,可以对用户账号进行操作
while (1) {
system("cls");
cout << "\n**********************************************************************************************\n";
cout << "$ 尊贵的管理员,您已经进入用户账号管理后台(时间:" << get_now_time() << ") $\n";
cout << "$ [101] 输出用户列表(ADMIN) $\n";
cout << "$ [102] 改变用户权限(ADMIN) $\n";
cout << "$ [103] 按照账号批量删除用户(ADMIN) $\n";
cout << "$ [-1] 退出用户账号管理后台(ADMIN) $\n";
cout << "**********************************************************************************************\n";
cout << "请输入您的选择(101~103。不能含有多余空格):\n";
string line; getline(cin, line);
int choice = is_integer(line);
int wrong_numb = 0;
switch (choice) {
case 101:
cout << "你选择了[101] 输出用户列表\n";
get_all_users();
break;
case 102:
cout << "你选择了[102] 改变某个用户权限\n";
change_user_rights();
break;
case 103:
cout << "你选择了[103] 按照账号批量删除用户\n";
delete_in_id_users();
break;
case -1:
system("cls");
cout << "用户账号管理后台已经退出\n";
return;
default:
printf("请输入正确的数字\n");
wrong_numb = 1;
break;
}
save_user_id();
if (wrong_numb == 0) {
int retn = 0;
while (retn == 0) {
cout << "若要返回用户后台菜单,请输入[r]:\n";
string op; getline(cin, op);
if (op == "r") {
retn = 1;
}
}
}
}
}
void print_in_idx_user(int idx) {
auto [id, pw, ad, mbwt, mbda] = us[idx];
cout << left << setw(12) << id << left << setw(20) << pw << left << setw(12) << ad;
cout << left << setw(50) << mbwt << mbda << "\n";
}
void get_all_users() {
cout << "\n$**************************************************************************************";
cout << "**************************$\n";
cout << left << setw(12) << "账号" << left << setw(20) << "密码" << left << setw(12) << "管理员权限";
cout << left << setw(50) << "密保问题" << "密保答案" << "\n";
int len = us.size();
for (int i = 0; i < len; i ++) {
print_in_idx_user(i);
}
cout << "$****************************************************************************************";
cout << "************************$\n\n";
}
void change_user_rights() { // 改变某个用户的权限
while (1) {
cout << "请输入你要改变权限的用户的账号(6~10位正整数,输入[-1]退出操作):";
int id = line_number();
if (id == -1) {
cout << "[改变用户权限]操作即将退出\n";
return;
} else if (id >= 100000 && id <= 9999999999) {
int idx = find_account_number(id);
if (idx == -1) {
cout << "该账号不存在\n";
} else {
us[idx].admin ^= 1;
if (us[idx].admin) {
cout << "已赋予账号[" << id << "]管理员权限^_^\n";
} else {
cout << "已取消账号[" << id << "]管理员权限QAQ\n";
}
return;
}
} else {
cout << "你输入的账号是负数,或长度过长、过短QAQ\n";
}
}
}
void delete_in_id_users() { // 按照账号批量删除用户
printf("请依次输入要删除的用户的账号,以[回车]隔开。输入[-1]结束。\n");
while (1) {
int id_delete = line_number();
if (id_delete == -1) {
printf("信息删除系统即将退出\n");
return;
}
int idx = find_account_number(id_delete);
if (idx != -1) {
us.erase(us.begin() + idx);
cout << "账号[" << id_delete << "[已删除\n";
return;
} else {
cout << "系统中不存在账号为[" << id_delete << "]的账号\n";
}
}
}
string hide_password() {
string password;
char ch;
while (ch = getch(), ch != '\r') { // 当用户按下回车键时停止循环
if (ch == '\b') { // 如果是退格符,则删除最后一个字符
if (password.size() > 0) {
password.pop_back();
cout << "\b \b";
// “退格”并没有删除字符功能,只是改变了光标的位置。中间的' '是为了覆盖最后一个字符。
}
} else { // 否则输出 * 字符并将字符添加到密码字符串中
password.push_back(ch);
cout << '*';
}
}
cout << "\n";
return password;
}