----------------------------------------------------- 2019/07/14 -----------------------------------------------------
添加自我上传题目功能,输入表达等式即可.
修复若干 Bug
----------------------------------------------------- 2019/07/13 -----------------------------------------------------
用户登录、注册功能.
我要刷题
错题重刷
刷题记录
AC 过的题
WA 过的题
管理员特用功能(第一名注册者默认管理员)
{
删除账号
取消管理员
设置管理员
}
只需修改开头宏定义 Root 路径即可.
#include <io.h>
#include <ctime>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <windows.h>
#include <bits/stdc++.h>
#define eps 1e-2
#define Root "这里填地址\\User\\"
using namespace std;
struct User
{
char id[10], password[20];
bool flag;
};
struct Equation
{
double num1, num2;
char sym[3];
double ans;
};
struct date
{
int num;
int year, month, day;
int hour, minute, second;
};
char User_txt[100];
char Assist_txt[100];
char Wronged_txt[100];
char Id_Road_txt[100];
char Accepted_txt[100];
char Recorder_txt[100];
char Attempted_txt[100];
void Compose(char tmp[], char s1[], char s2[])
{
strcpy(tmp, s1);
strcat(tmp, s2);
}
void User_inf_init(char id[])
{
char tmp[100];
Compose(tmp, id, "\\");
Compose(Id_Road_txt, Root, tmp);
Compose(Assist_txt, Id_Road_txt, "Assist.txt");
Compose(Wronged_txt, Id_Road_txt, "Wronged.txt");
Compose(Accepted_txt, Id_Road_txt, "Accepted.txt");
Compose(Recorder_txt, Id_Road_txt, "Recorder.txt");
Compose(Attempted_txt, Id_Road_txt, "Attempted.txt");
}
void Save(char name[], struct Equation equ)
{
FILE *fp;
fp = fopen(name, "ab");
fwrite(&equ, sizeof(equ), 1, fp);
fclose(fp);
}
void Print_Equ(struct Equation equ)
{
printf("%.2f %s %.2f = ", equ.num1, equ.sym, equ.num2);
}
bool Check(struct Equation equ, int &Total, int &Accpted)
{
Print_Equ(equ);
double ans;
scanf("%lf", &ans);
Total++;
if(fabs(ans - equ.ans) < 2.0 * eps)
{
Accpted++;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_GREEN);
printf("Yes\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN);
return 1;
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_RED);
printf("No\n");
printf("正确答案:%f\n", equ.ans);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN);
return 0;
}
}
Equation Create_Equ(int Max)
{
struct Equation equ;
equ.num1 = fmod(int(rand() * 2.71828 * 100.0) / 100.0, Max);
equ.num2 = fmod(int(rand() * 2.71828 * 100.0) / 100.0, Max);
if(equ.num1 < equ.num2)
swap(equ.num1, equ.num2);
int sym = rand() % 4;
switch(sym)
{
case 0:
strcpy(equ.sym, "+"), equ.ans = equ.num1 + equ.num2;
break;
case 1:
strcpy(equ.sym, "-"), equ.ans = equ.num1 - equ.num2;
break;
case 2:
strcpy(equ.sym, "×"), equ.ans = equ.num1 * equ.num2;
break;
case 3:
strcpy(equ.sym, "÷"), equ.ans = equ.num1 / equ.num2;
break;
}
equ.ans = (int)(equ.ans * 100) / 100.0;
return equ;
}
int First_Test()
{
int Max;
printf("请输入最大值:");
scanf("%d", &Max);
char ch;
int Total = 0;
int Accepted = 0;
while((ch = getchar()) != 'E')
{
system("cls");
struct Equation equ = Create_Equ(Max);
if(!Check(equ, Total, Accepted))
{
Save(Attempted_txt, equ);
Save(Wronged_txt, equ);
}
else
Save(Accepted_txt, equ);
getchar();
}
printf("\n总题数:%d\n正确数:%d\n正确率:%.2f%\n", Total, Accepted, 100.0 * Accepted / Total);
return Accepted;
}
int Second_Test()
{
int Total = 0;
int Accepted = 0;
struct Equation equ;
FILE *fp1 = fopen(Attempted_txt, "rb");
FILE *fp2 = fopen(Assist_txt, "wb");
FILE *fp3 = fopen(Accepted_txt, "ab");
char ch;
while(!feof(fp1) && (ch = getchar()) != 'E')
{
system("cls");
fread(&equ, sizeof(equ), 1, fp1);
if(!feof(fp1))
{
if(!Check(equ, Total, Accepted))
fwrite(&equ, sizeof(equ), 1, fp2);
else
fwrite(&equ, sizeof(equ), 1, fp3);
getchar();
}
}
while(!feof(fp1))
{
fread(&equ, sizeof(equ), 1, fp1);
if(!feof(fp1))
fwrite(&equ, sizeof(equ), 1, fp2);
}
fclose(fp1);
fclose(fp2);
fclose(fp3);
remove(Attempted_txt);
rename(Assist_txt, Attempted_txt);
printf("\n总题数:%d\n正确数:%d\n正确率:%.2f%\n", Total, Accepted, 100.0 * Accepted / Total);
getchar();
return Accepted;
}
int Lasted_Recorder(bool flag)
{
struct date t;
FILE *fp = fopen(Recorder_txt, "rb");
if(flag)
printf("刷题数\t\t日期\n\n");
while(!feof(fp))
{
fread(&t, sizeof(t), 1, fp);
if(!feof(fp) && flag)
{
printf(" %d\t%d/", t.num, t.year);
if((int)(log10(t.month) + 1) != 2)
printf("0");
printf("%d/", t.month);
if((int)(log10(t.day) + 1) != 2)
printf("0");
printf("%d ", t.day);
if((int)(log10(t.hour) + 1) != 2)
printf("0");
printf("%d:", t.hour);
if((int)(log10(t.minute) + 1) != 2)
printf("0");
printf("%d:", t.minute);
if((int)(log10(t.second) + 1) != 2)
printf("0");
printf("%d\n", t.second);
}
}
fclose(fp);
if(flag)
getchar(), getchar();
system("cls");
return t.num;
}
void Update_Recorder(int num, bool flag)
{
time_t timep;
struct tm *p;
time (&timep);
p = gmtime(&timep);
struct date t;
t.year = 1900 + p->tm_year;
t.month = 1 + p->tm_mon;
t.day = p->tm_mday;
t.hour = 8 + p->tm_hour;
t.minute = p->tm_min;
t.second = p->tm_sec;
FILE *fp = fopen(Recorder_txt, "ab");
t.num = flag ? num + Lasted_Recorder(0) : 0;
fwrite(&t, sizeof(t), 1, fp);
fclose(fp);
}
Equation Equ_input()
{
struct Equation equ;
char s[100];
scanf("%s", s);
int len = strlen(s);
int integer, decimal;
integer = decimal = 0;
bool dot = 0;
int flag = 0;
for(int i = 0; i < len; ++i)
{
if(!isdigit(s[i]) && s[i] != '.' && s[i] != '=')
{
switch(s[i])
{
case '+':
strcpy(equ.sym, "+");
break;
case '-':
strcpy(equ.sym, "-");
break;
case '*':
strcpy(equ.sym, "×");
break;
case '/':
strcpy(equ.sym, "÷");
break;
}
s[i] = ' ';
}
else if(s[i] == '=')
s[i] = ' ';
}
int pos = 0;
stringstream ss;
ss << s;
double num;
while(ss >> num)
{
switch(pos)
{
case 0:
equ.num1 = num;
break;
case 1:
equ.num2 = num;
break;
case 2:
equ.ans = num;
break;
}
pos++;
}
return equ;
}
int Third_Test()
{
char ch;
int Total, Accepted;
Total = Accepted = 0;
while((ch = getchar()) != 'E')
{
system("cls");
printf("自我检测\n\n");
struct Equation equ = Equ_input();
double ans;
if(!strcmp(equ.sym, "+"))
ans = equ.num1 + equ.num2;
else if(!strcmp(equ.sym, "-"))
ans = equ.num1 - equ.num2;
else if(!strcmp(equ.sym, "×"))
ans = equ.num1 * equ.num2;
else if(!strcmp(equ.sym, "÷"))
ans = equ.num1 / equ.num2;
swap(ans, equ.ans);
if(fabs(ans - equ.ans) < 2.0 * eps)
{
Accepted++;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_GREEN);
printf("Yes\n");
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN);
Save(Accepted_txt, equ);
}
else
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_RED);
printf("No\n");
printf("正确答案:%f\n", equ.ans);
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN);
Save(Attempted_txt, equ);
Save(Wronged_txt, equ);
}
getchar();
}
Update_Recorder(Accepted, 1);
}
bool Print_User_Windows(char id[], bool flag)
{
system("cls");
printf("[%s]\n\n", id);
printf("1.我要刷题\n");
printf("2.错题重刷\n");
printf("3.自我检测\n");
printf("4.刷题记录\n");
printf("5.Accepted\n");
printf("6.Wrong Answer\n");
printf("7.注销账号\n");
if(flag)
{
printf("8.删除账号\n");
printf("9.取消管理员\n");
printf("10.设置管理员\n");
}
return 1;
}
void Show(char name[])
{
if(!strcmp(name, Accepted_txt))
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_GREEN);
else if(!strcmp(name, Wronged_txt))
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY |FOREGROUND_RED);
FILE *fp = fopen(name, "rb");
int cnt = 1;
struct Equation equ;
while(!feof(fp))
{
fread(&equ, sizeof(equ), 1, fp);
if(!feof(fp))
printf("%d. %.2f %s %.2f = %.2f\n", cnt++, equ.num1, equ.sym, equ.num2, equ.ans);
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
getchar();
getchar();
}
void Delete_User()
{
FILE *fp1 = fopen(User_txt, "rb");
struct User user;
while(!feof(fp1))
{
fread(&user, sizeof(user), 1, fp1);
if(!feof(fp1))
printf("%s\t%s\t%s\n", user.id, user.password, user.flag ? "管理员" : "非管理员");
}
fclose(fp1);
char User_Assist_txt[100];
Compose(User_Assist_txt, Root, "User_Assist.txt");
fp1 = fopen(User_txt, "rb");
FILE *fp2 = fopen(User_Assist_txt, "wb");
printf("请输入删除 ID:");
char D_id[100];
scanf("%s", D_id);
while(!feof(fp1))
{
fread(&user, sizeof(user), 1, fp1);
if(!feof(fp1) && strcmp(D_id, user.id))
fwrite(&user, sizeof(user), 1, fp2);
}
fclose(fp1);
fclose(fp2);
remove(User_txt);
rename(User_Assist_txt, User_txt);
User_inf_init(D_id);
remove(Accepted_txt);
remove(Wronged_txt);
remove(Attempted_txt);
remove(Recorder_txt);
Compose(User_Assist_txt, Root, D_id);
rmdir(User_Assist_txt);
}
void Update_Adm(bool flag)
{
FILE *fp1 = fopen(User_txt, "rb");
struct User user;
while(!feof(fp1))
{
fread(&user, sizeof(user), 1, fp1);
if(!feof(fp1))
printf("%s\t%s\t%s\n", user.id, user.password, user.flag ? "管理员" : "非管理员");
}
fclose(fp1);
printf("请输入所%s管理员的Id:", flag ? "设置" : "取消");
char Id[100];
scanf("%s", Id);
char User_Assist_txt[100];
Compose(User_Assist_txt, Root, "User_Assist.txt");
fp1 = fopen(User_txt, "rb");
FILE *fp2 = fopen(User_Assist_txt, "wb");
while(!feof(fp1))
{
fread(&user, sizeof(user), 1, fp1);
if(!feof(fp1))
{
if(!strcmp(Id, user.id))
user.flag = flag;
fwrite(&user, sizeof(user), 1, fp2);
}
}
fclose(fp1);
fclose(fp2);
remove(User_txt);
rename(User_Assist_txt, User_txt);
}
void User_Windows(char id[], bool flag)
{
User_inf_init(id);
while(Print_User_Windows(id, flag))
{
int dir;
scanf("%d", &dir);
if(dir == 1)
Update_Recorder(First_Test(), 1);
else if(dir == 2)
Update_Recorder(Second_Test(), 1);
else if(dir == 3)
Update_Recorder(Third_Test(), 1);
else if(dir == 4)
Lasted_Recorder(1);
else if(dir == 5)
Show(Accepted_txt);
else if(dir == 6)
Show(Wronged_txt);
else if(dir == 7)
return;
else if(flag)
{
if(dir == 8)
{
Delete_User();
User_inf_init(id);
}
else if(dir == 9)
Update_Adm(0);
else if(dir == 10)
Update_Adm(1);
}
else
{
printf("输入非法\n");
getchar();
getchar();
}
}
}
void Login()
{
system("cls");
char id[10];
char pw[10];
printf("请输入账号:");
scanf("%s", id);
printf("请输入密码:");
scanf("%s", pw);
FILE *fp = fopen(User_txt, "rb");
int flag = 0;
struct User tmp;
while(!feof(fp))
{
fread(&tmp, sizeof(tmp), 1, fp);
if(!feof(fp) && !strcmp(tmp.id, id))
{
if(!strcmp(tmp.password, pw))
flag = 1;
else
flag = 2;
break;
}
}
fclose(fp);
switch(flag)
{
case 0:
printf("\n账号不存在\n"), getchar(), getchar();
break;
case 1:
User_Windows(tmp.id, tmp.flag);
break;
case 2:
printf("\n密码错误\n"), getchar(), getchar();
break;
}
}
void Create_User_inf(char name[])
{
FILE *fp = fopen(name, "wb");
fclose(fp);
}
void Create_User(struct User tmp)
{
User_inf_init(tmp.id);
if(!tmp.flag)
tmp.flag = 0;
FILE *fp = fopen(User_txt, "ab");
fwrite(&tmp, sizeof(tmp), 1, fp);
fclose(fp);
_mkdir(Id_Road_txt);
Create_User_inf(Accepted_txt);
Create_User_inf(Wronged_txt);
Create_User_inf(Attempted_txt);
Create_User_inf(Recorder_txt);
Update_Recorder(0, 0);
}
void Register()
{
system("cls");
User tmp;
char id[10], pw[20];
printf("请输入用户名:");
scanf("%s", id);
printf("请输入密码:");
scanf("%s", pw);
bool tmp_flag;
if(access(Root, 0))
{
_mkdir(Root);
tmp_flag = 1;
}
else
tmp_flag = 0;
FILE *fp = fopen(User_txt, "rb");
if(!fp)
{
fclose(fp);
fp = fopen(User_txt, "wb");
fclose(fp);
fp = fopen(User_txt, "rb");
}
bool flag = 0;
while(!feof(fp))
{
fread(&tmp, sizeof(tmp), 1, fp);
if(!feof(fp))
{
if(!strcmp(tmp.id, id))
{
flag = 1;
break;
}
}
}
fclose(fp);
if(flag)
{
printf("该用户名已注册\n");
getchar();
getchar();
}
else
{
strcpy(tmp.id, id);
strcpy(tmp.password, pw);
tmp.flag = tmp_flag;
Create_User(tmp);
}
}
bool Main_Windows()
{
printf("1.登录\n");
printf("2.注册\n");
printf("3.退出\n");
return 1;
}
void Main()
{
Compose(User_txt, Root, "User.txt");
while(Main_Windows())
{
int dir;
scanf("%d", &dir);
if(dir == 1)
Login();
else if(dir == 2)
Register();
else if(dir == 3)
exit(0);
else
{
printf("输入非法\n");
getchar();
getchar();
}
system("cls");
}
}
int main()
{
srand(time(NULL));
Main();
return 0;
}