C课程设计-驾校考试模拟系统

C课程设计-驾校考试模拟系统

基本设计要求:

采用链表(系统中可以设定任意数目的记录,但难度较大)或者结构体数组(只能限定一定数目的记录)完成系统。系统要求设计一个驾校考试模拟系统, 可以进行考试,成绩记录等操作。

基本系统功能

课程要求最低完成以下任务
» 注册用户
» 考试,可以多次考试
从文件中读取题目(选择题),随机抽取N题,不重复
» 自动阅卷
根据输入的答案自动判断对错并记录下分数
» 记录用户成绩
将最新的成绩添加到注册用户的信息中(覆盖掉原有成绩)
» 查找用户考试信息
根据用户名查找用户的考试成绩
» 退出系统

团队3人合作一周的结果,在程序健壮性上下了很多功夫,但仍有许多值得完善的地方,仅供相同设计课题的同学参考。

程序中使用的文件:
user.txt(考生档案文件,必须先在文件夹中手动新建,否则第一次运行时程序提示无法打开考生档案文件)
text.txt(试题文件,必须先在文件夹中手动新建,否则运行时程序提示无法打开试题文件)
information.txt(考生信息文件,无需手动新建,注册时程序自动新建写入内容保存)
score.txt(记录考生历次考试成绩的文件,无需手动创建,考完试自动新建写入成绩保存)

几点重要说明

  1. 试题文件即题库必须按以下方式保存:

对发生道路交通事故需要收集证据的事故车,交通警察可以依法扣留。T
年龄在50周岁以上的机动车驾驶人,应当每年进行一次身体检查,并向公安机关交通管理部门申报身体条件情况。T
下面哪种做法能帮助您避免被其他车辆从后方追撞?
a、在任何时候都打开转向灯
b、在转弯前提前打开相应的转向灯
c、一直打开双闪
d、转弯前鸣笛示意B
实习期驾驶人驾驶机动车上高速公路行驶,以下做法正确的是什么?
a、任何情况下都不允许上高速
b、不需要其他人员陪同
c、需要持有相应或者更高准驾车型驾驶证三年以上的驾驶人陪同
d、需要持有相应或者更高准驾车型驾驶证、同在实习期内的驾驶人陪同C

因为代码实现读题时已经设定好读取答案的形式,即在题目的末尾,若要修改,修改源代码即可。同时要先存判断题,再存单选题,同理,读题时已经设定好读取题目的形式,单选题比判断题多占四行。

2.程序用了较多的fgetc,fputc,因此后续用fread,fwrite,fscanf,fprintf优化效率会更高。
3.采用动态链表会比采用结构体数组好很多,内存的开销也占的少。
4.可以再开发一个管理员系统,可以浏览任意用户的所有成绩,实现对注册用户的管理等等功能。
5.有些地方可能未注意到’\0’的写入。
6.界面的优化可以做的更出色。

主函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "windows.h"

void register_now();
void login_now();
void exit_now();
void search_now();

int main()
{
    char choice[2] = {'0'};/*将choice定义成一个二维数组,而不是char型变量,以防止用户输入aab时,char choice仍然得到的是'a'*/
Rechoice:
    do
    {
        system("color f0");//背景换为白色
        printf("T———————————————————————T\n");
        printf("|----------欢迎进入驾校考试模拟系统!-------------|\n");
        printf("|---------------------------------------------|\n");
        printf("|-----|A.立即登录|------------|B.立即注册|-------|\n");
        printf("|---------------------------------------------|\n");
        printf("|-----|C.查询成绩|------------|D.立即退出|-------|\n");
        printf("|_____________________________________________|\n");
        printf("请选择您需要的功能:");
        gets(choice);
        fflush(stdin);
        system("cls");
        if(strlen(choice) == 1 && (choice[0] == 'A' || choice[0] == 'B' || choice[0] == 'C' || choice[0] == 'D' ||
                                   choice[0] == 'a' || choice[0] == 'b' || choice[0]== 'c' || choice[0] == 'd'))//杜绝非法输入
        {
            switch(choice[0])
            {
            case 'A':
            case 'a':
                login_now();
                break;
            case 'B':
            case 'b':
                register_now();
                break;
            case 'C':
            case 'c':
                search_now();
                break;
            case 'D':
            case 'd':
                exit_now();
                break;
            }
        }
        else
        {
            printf("输入无效!\n");
            fflush(stdin);
            system("pause");
            system("cls");
            goto Rechoice;
        }

    }
    while(1);

}

login_now()函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "conio.h"
#define M 1000
#define N 1000

typedef struct a//定义结构体,text存题目,answer存答案
{
    char text[M][N];
    char answer[M];

} text_answer;

typedef struct date//定义结构体,分别存放年月日
{
    int year;
    int month;
    int day;

} DATE;

typedef struct user//定义结构体,包括用户名,密码,性别等
{
    char username[20];
    char password[20];//最大二十位密码
    char gender;
    DATE birthday;
} USER;

typedef struct judge//判断用户名及密码是否存在的数组
{
    char username[20];
    char password[20];

} JUDGE;


int judge_user(char account[], char password[]);
void login_now_menu();
void test_now(char account[]);
int valid_username(char *p);
void update_password(char account[]);
void study_text();
void hidden_password(char password[]);


void login_now()
{
    char choice[2];
    char account[15];
    char password[20];
    int flag = -1, i, k;
    char ch;
    char ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8;
    FILE *fp;
    USER users[N];
Restart1:
    fflush(stdin);
    printf("请输入您的用户名:");
    gets(account);
    if(strlen(account) > 20 || strlen(account) < 1 || !valid_username(account))
    {
        printf("您输入的用户名不合法,请重新输入!\n");
        goto Restart1;

    }
    fflush(stdin);
    printf("请输入您的密码:");
    hidden_password(password);
    fflush(stdin);
    if(judge_user(account, password))
    {
        if((fp = fopen("information.txt","r")) == NULL )//判断文件是否打开成功
        {
            printf("考生信息文件打开失败!");
            return;
        }
        for(i = 0, k = 0; ch != EOF; k++)
        {
            ch = fgetc(fp);
            if(ch  == '\n')
            {
                i++;
                k = -1;
            }
            else
            {
                if(ch == '|')
                {
                    users[i].username[k] = '\0';
                    users[i].gender = fgetc(fp);
                    ch = fgetc(fp);
                    if(ch == '|')//因为在注册函数中,不同类信息间用|分隔
                    {
                        ch1 = fgetc(fp);
                        ch2 = fgetc(fp);
                        ch3 = fgetc(fp);
                        ch4 = fgetc(fp);
                        users[i].birthday.year = ((int)ch1 - 48) * 1000 + ((int)ch2 - 48) * 100 + ((int)ch3 - 48) * 10 + ((int)ch4 - 48);//将字符转为其表示的值
                        if((ch = fgetc(fp)) == '|')
                        {
                            ch5 = fgetc(fp);
                            ch6 = fgetc(fp);
                            users[i].birthday.month = ((int)ch5 - 48) * 10 + ((int)ch6 - 48);
                            if((ch = fgetc(fp)) == '|')
                            {
                                ch7 = fgetc(fp);
                                ch8 = fgetc(fp);
                                users[i].birthday.day = ((int)ch7 - 48) * 10 + ((int)ch8 - 48);
                            }
                        }

                    }
                }
                else
                    users[i].username[k] = ch;
            }
        }

        for(i = 0; i < N; i++)
        {
            if(strcmp(users[i].username, account) == 0)
                flag = i;
        }
        printf("登录成功!\n");
        printf("请核对您的身份!\n");
        printf("您的用户名:%s\n",users[flag].username);
        printf("您的性别:%c\n",users[flag].gender);
        printf("您的生日是:%d/%d/%d\n",users[flag].birthday.year,users[flag].birthday.month,users[flag].birthday.day);
        system("pause");
        system("cls");
        do
        {
Restart2:
            login_now_menu();
            printf("请选择您需要的功能:");
            fflush(stdin);
            gets(choice);
            if(strlen(choice) == 1 && (choice[0] == 'A' || choice[0] == 'B' || choice[0] == 'C' || choice[0] == 'D' || choice[0] == 'a' || choice[0] == 'b' || choice[0]== 'c' || choice[0] == 'd'))
            {
                switch(choice[0])
                {
                case 'A':
                case 'a':
                    test_now(account);
                    break;
                case 'B':
                case 'b':
                    study_text();
                    break;
                case 'C':
                case 'c':
                    update_password(account);
                    break;
                default:
                    system("cls");
                    return;
                    break;

                }
            }
            else
            {
                printf("输入无效!\n");
                fflush(stdin);
                system("pause");
                system("cls");
                goto Restart2;
            }
        }
        while(1);
    }
    else
    {
        printf("登陆失败!您的用户名或密码有错!\n");
        system("pause");
        system("cls");
    }
}

login_now()函数中调用的函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "conio.h"
#define M 1000
#define N 1000

typedef struct a
{
    char text[M][N];
    char answer[M];

} text_answer;

typedef struct date
{
    int year;
    int month;
    int day;

} DATE;

typedef struct user
{
    char username[20];
    char password[20];
    char gender;
    DATE birthday;
} USER;

typedef struct judge
{
    char username[20];
    char password[20];

} JUDGE;

typedef struct score
{
    char username[20];
    int score1;
    int score2;
    int score3;

} SCORE;



int valid_password(char *p);


int judge_user(char account[], char password[])
{
    int i = 0, j = 0, k = 0;
    int flag = 0;
    JUDGE judge[N];
    char ch;
    FILE *fp;
    if((fp = fopen("user.txt","r")) == NULL )//判断文件是否打开成功
    {
        printf("考生档案文件打开失败!");
        exit(0);
    }
    else
    {
        for(i = 0, k = 0; ch != EOF; k++)
        {
            ch = fgetc(fp);
            if(ch == '|')
                for(j = 0; (ch = fgetc(fp)) != '\n'; j++)
                    judge[i].password[j] = ch;
            if(ch  == '\n')
            {
                i++;
                k = -1;
            }
            else
                judge[i].username[k] = ch;

        }

    }
    for(i = 0; i < N; i++)
    {
        if(strcmp(judge[i].username, account) == 0 && strcmp(judge[i].password, password) == 0)
            flag = 1;//这边可以直接写成return 1;
    }
    switch(flag)
    {
    case '1':
        return 1;
        break;
    case '2':
        return 0;
        break;
    }
}

void login_now_menu()
{
    printf("T———————————————————————T\n");
    printf("|----------欢迎登入驾校考试模拟系统!----------|\n");
    printf("|----------------------------------------------|\n");
    printf("|-----|A.立即考试|------------|B.查看题库|-----|\n");
    printf("|----------------------------------------------|\n");
    printf("|-----|C.修改密码|------------|D.注销登录|-----|\n");
    printf("|______________________________________________|\n");
}

void product_random(int x, int a[])//函数功能:利用指针,将产生的随机数存在传进函数的a数组里,且随机数不重复。
{
    srand(time(0));
    int i, j, temp;
    for(i = 0; i < x; i++)
    {
        temp = rand() % x;
        for(j = 0; j < i; j++)
        {
            if(temp == *(a + j))//如果重复,生成一个新随机数
            {
                i--;
                break;
            }
            else
                *(a + i) = temp;
        }
    }
}

void test_now(char account[])
{
    int i = 0, j = 0, k = 0;
    int count1 = 0, count2 = 0;
    int flag = 0, record1 = 0, record2 = 0;
    int m = 10, n = 0;
    int random[M] = {0};
    text_answer a;
    SCORE scores;
    char choice1, choice2, ch1;
    FILE *fp, *fp1;
    system("cls");
Restart:
    fflush(stdin);
    printf("您确定立即开始考试?\n");
    printf("Y.开始\tN.结束,你选择:");
    scanf("%c", &choice1);
    ///以下为判断题
    switch(choice1)
    {
    case 'Y':
    case 'y'://不区分大小写
    {
        system("cls");
        printf("考试正式开始!请注意每题只有一次作答机会!\n");
        if((fp1 = fopen("text.txt","r")) == NULL )//判断文件是否打开成功
        {
            printf("判断题文件打开失败!");
            exit(0);
        }
        else
        {
            while((ch1 = fgetc(fp1)) != EOF)//把题目存到数组中
            {
                if(ch1 == '\n')
                {
                    i++;
                    j = 0;
                    record2 = i;//record2的用处就是标记单选题在二维数组中的一维下标
                }
                if(ch1 == 'T'|| ch1 == 'F')
                {
                    record1 = i;//record1的用处就是标记判断题在二维数组中的一维下标
                }
                if(ch1 <= 0 || (ch1 >= '0' && ch1 <= '9') || (ch1 >= 'a' && ch1 <= 'z') || ch1 == '.')//把题目存到数组里,原理:题目里的汉字在计算机存的码值小于0,不过要注意题目里可能包含数字,要单独考虑。
                {
                    a.text[i][j++] = ch1;
                }
                else if(ch1 >= 'A' && ch1 <= 'Z')//把文件里每个题目后面的答案存到answer数组里
                    a.answer[k++] = ch1;

            }
        }
        fclose(fp1);//关闭文件
    }
    break;
    case 'N':
    case 'n':
    {
        goto End;

    }
    break;
    default:
    {
        printf("无效选择!\n");
        fflush(stdin);
        goto Restart;

    }
    break;

    }
    product_random(record2, random);//将随机数传到random数组中
    getchar();
    printf("第一部分 判断题(5 * 10)\n");
    do
    {
        flag = random[n++];
        if(flag <= record1)//如果随机数在判断题最大题数即record1内
        {
Reanswer1:
            printf("%d.%s\n",11 - m, a.text[flag]);//flag随机抽题
            printf("T.正确\tF.错误,你选择:");
            scanf("%c",&choice2);
            if(a.answer[flag] == choice2 || a.answer[flag] == choice2 - 32)//不区分大小写
                ++count1;
            if(choice2 != 't' && choice2 != 'T' && choice2 != 'f' && choice2 != 'F')
            {
                printf("无效选择!请重新作答!\n");
                fflush(stdin);
                goto Reanswer1;
            }
            fflush(stdin);
        }
        else
        {
            ++m;
            continue;
        }
    }
    while(--m); //十题判断
    n = 0;
    m = 5;
    ///以下为单选题
    system("cls");
    printf("第二部分 单选题(10 * 5)\n");
    do
    {
        flag = random[n++];
        if(flag > record1 && (flag - record1 - 1) % 5 == 0 && flag < record2 - 5)
        //如果随机数在单选题最大题数即record2内
        {
Reanswer2:
            printf("%d.",6 - m);
            puts(a.text[flag + 0]);//依次将题目和选项输出
            puts(a.text[flag + 1]);
            puts(a.text[flag + 2]);
            puts(a.text[flag + 3]);
            puts(a.text[flag + 4]);
            printf("你选择:");
            scanf("%c",&choice2);
            do
            {
                system("cls");
            }
            while(0);
            if(a.answer[record1 + 1 + (flag - record1) / 5] == choice2 || a.answer[record1 + 1 + (flag - record1) / 5] == choice2 - 32)//不区分大小写
                ++count2;//要想让answer数组和text数组一一对应,在单选题这下标必须经过一定的运算
            if(choice2 != 'a' && choice2 != 'b' && choice2 != 'c' && choice2 != 'd' &&
                    choice2 != 'A' && choice2 != 'B' && choice2 != 'C' && choice2 != 'D')
            {
                printf("无效选择!请重新作答!\n");
                fflush(stdin);
                goto Reanswer2;
            }
            fflush(stdin);
        }
        else
        {
            ++m;
            continue;
        }
    }
    while(--m); //五题单选
    strcpy(scores.username, account);
    scores.score1 = count1 * 5 + count2 * 10;
    scores.score2 = count1;
    scores.score3 = count2;
    if((fp=fopen("score.txt","a+"))==NULL)
    {
        printf("打开成绩记录文件失败!\n");
        exit(0);
    }
    fprintf(fp,"%s|%02d|%d|%d",//|分隔
            scores.username,
            scores.score1,
            scores.score2,
            scores.score3);
    fputc('\n',fp);
    fclose(fp);
    printf("考试完毕,您的总分为:%d!\n",count1 * 5 + count2 * 10);
End:
    system("pause");
    system("cls");

}

void study_text()
{

    int i = 0, j = 0, k = 0;
    int record1 = 0, record2 = 0;
    text_answer a;
    char ch1;
    FILE *fp1;
    system("cls");
    if((fp1 = fopen("text.txt","r")) == NULL )//判断文件是否打开成功
    {
        printf("判断题文件打开失败!");
        exit(0);
    }
    else
    {
        while((ch1 = fgetc(fp1)) != EOF)//把题目存到数组中
        {
            if(ch1 == '\n')
            {
                i++;
                j = 0;
                record2 = i;
            }
            if(ch1 == 'T'|| ch1 == 'F')
            {
                record1 = i;
            }
            if(ch1 <= 0 || (ch1 >= '0' && ch1 <= '9') || (ch1 >= 'a' && ch1 <= 'z') || ch1 == '.')
            {
                a.text[i][j++] = ch1;
            }
            else if(ch1 >= 'A' && ch1 <= 'Z')
                a.answer[k++] = ch1;

        }
    }
    fclose(fp1);//关闭文件
    for(i = 0; i < record1; i++)
    {
        printf("判断题:");//与上一函数基本相同,不过这里同时输出题目和答案要格外注意一一对应
        puts(a.text[i]);
        printf("答案:");
        printf("%c\n",a.answer[i]);
    }
    for(i = record1 + 1,j = record1 + 1; i < record2 - 8; i = i + 5,j++)
    {
        printf("选择题:\n");
        puts(a.text[i + 0]);
        puts(a.text[i + 1]);
        puts(a.text[i + 2]);
        puts(a.text[i + 3]);
        puts(a.text[i + 4]);
        printf("答案:");
        printf("%c\n",a.answer[j]);
    }
    system("pause");
    system("cls");

}

void update_password(char account[])//修改密码
{
    char password[15];
    char repassword[15];
    int i = 0, j = 0, k = 0, s = 0;
    int flag = 0;
    JUDGE judge[N];
    char ch;
    FILE *fp;
    if((fp = fopen("user.txt","r")) == NULL )//判断文件是否打开成功
    {
        printf("考生档案文件打开失败!");
        exit(0);
    }
    else
    {
        for(i = 0, k = 0; (ch = fgetc(fp)) != EOF; k++)
        {
            if(ch == '|')
                for(j = 0; (ch = fgetc(fp)) != '\n'; j++)
                    judge[i].password[j] = ch;
            if(ch  == '\n')
            {
                i++;
                s++;
                j = 0;
                k = -1;
            }
            else
                judge[i].username[k] = ch;

        }

    }
    for(i = 0; i < N; i++)
    {
        if(strcmp(judge[i].username, account) == 0)
            flag = i;
    }
    fclose(fp);
    if((fp = fopen("user.txt","w")) == NULL )//判断文件是否打开成功
    {
        printf("考生档案文件打开失败!");
        exit(0);
    }
Restart3:
    fflush(stdin);
    printf("请输入新注册密码(必须包含字母或数字的六至十二位的字母数字组合):");//密码的限定条件
    gets(password);
    printf("请再次输入新注册密码:");
    gets(repassword);
    printf("确定修改密码吗? ENTER确认!");
    getchar();
    fflush(stdin);
    if(strcmp(password,repassword) != 0)
    {
        printf("两次输入的密码不一致,请重新输入!\n");
        goto Restart3;
    }
    if(strlen(password) > 12 || strlen(password) < 6 || !valid_password(password))
    {
        printf("您输入的密码无效,请重新输入!\n");
        goto Restart3;
    }
    else
    {
        strcpy(judge[flag].password,password);
        for(i = 0; i < s; i++)
        {
            fputs(judge[i].username, fp);
            fputc('|', fp);
            fputs(judge[i].password, fp);
            fputc('\n', fp);
        }
    }
    fclose(fp);
    printf("恭喜您!修改密码成功!\n");
    system("pause");
    system("cls");

}

void hidden_password(char password[])//输入密码回显*号
{
    int i = 0, flag = 0;
    char input;
    while(1)
    {
        if((input = getch()) != '\r')
        {
            if(input != '\b')
            {
                *(password + i++) = input;
                printf("*");
                fflush(stdin);
                flag++;
            }
            if(input == '\b' && flag != 0)
            {
                flag--;
                i--;
                printf("\b \b");
            }
        }
        else
        {
            *(password + i) = '\0';
            fflush(stdin);
            printf("\n");
            return;

        }
    }
}

register_now()函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define M 1000
#define N 1000

typedef struct date
{
    int year;
    int month;
    int day;

} DATE;

typedef struct user
{
    char username[20];
    char password[20];
    char gender;
    DATE birthday;
} USER;

typedef struct judge
{
    char username[20];
    char password[20];

} JUDGE;


int valid_username(char *p);
int valid_password(char *p);
int judge_username(char account[]);
void WritetoFile(USER users);

void register_now()
{
    USER users;
    char password[15];
    char repassword[15];
    FILE *fp;
    fflush(stdin);
Restart1:
    printf("请输入您期望的用户名(低于二十位且须字母开头的数字字母组合):");//注册时的相关限制
    scanf("%s",users.username);
    fflush(stdin);
    if(strlen(users.username) > 20 || strlen(users.username) < 1 || !valid_username(users.username))
    {
        printf("您输入的用户名不符规范,请重新输入!\n");
        goto Restart1;

    }
    if(judge_username(users.username) == 1)
    {
        printf("此用户名已经被注册!\n");
        goto Restart1;
    }
    else
    {
        printf("恭喜!此用户名可以注册!\n");
    }
Restart2:
    printf("M.男性\tF.女性,您的性别是:");
    scanf("%c",&users.gender);
    if(users.gender != 'M' && users.gender != 'F' && users.gender != 'm' && users.gender != 'f')
    {
        printf("输入错误!\n");
        getchar();
        goto Restart2;
    }
    fflush(stdin);
    printf("请输入您的出生年份(根据法律规定,18-70岁中国公民可以领取驾照):");
Taget1:
    scanf("%d",&users.birthday.year);
    if(users.birthday.year>2001||users.birthday.year<=1949)
    {
        printf("年份不合规,请重新输入:");
        goto Taget1;
    }
    fflush(stdin);
    printf("请输入您的出生月份:");
Taget2:
    scanf("%d",&users.birthday.month);
    if(users.birthday.month>12||users.birthday.month<1)
    {
        printf("月份不合规,请重新输入:");
        goto Taget2;
    }
    fflush(stdin);
    printf("请输入您的出生日期:");
Taget3:
    scanf("%d",&users.birthday.day);
    if(users.birthday.day>31||users.birthday.day<1)
    {
        printf("日期不合规,请重新输入:");
        goto Taget3;
    }
    if((fp=fopen("information.txt","a+"))==NULL)
    {
        printf("打开信息记录文件失败!\n");
        return;
    }
    fprintf(fp,"%s|%c|%4d|%02d|%02d",
            users.username,
            users.gender,
            users.birthday.year,
            users.birthday.month,
            users.birthday.day);
    fputc('\n',fp);
    fclose(fp);

Restart3:
    getchar();
    fflush(stdin);
    printf("请输入注册密码(必须包含字母或数字的六至十二位的字母数字组合):");
    gets(password);
    printf("请再次输入注册密码:");
    gets(repassword);
    printf("确定注册吗? ENTER确认!");
    getchar();
    fflush(stdin);
    if(strcmp(password,repassword) != 0)
    {
        printf("两次输入的密码不一致,请重新输入!\n");
        goto Restart3;
    }
    if(strlen(password) > 12 || strlen(password) < 6 || !valid_password(password))
    {
        printf("您输入的密码无效,请重新输入!\n");
        goto Restart3;
    }
    else
    {
        strcpy(users.password,password);
    }
    printf("恭喜您!注册成功!\n");
    system("pause");
    system("cls");
    WritetoFile(users);
}

register_now()函数中调用的函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define M 1000
#define N 1000

typedef struct a
{
    char text[M][N];
    char answer[M];

} text_answer;

typedef struct date
{
    int year;
    int month;
    int day;

} DATE;

typedef struct user
{
    char username[20];
    char password[20];
    char gender;
    DATE birthday;
} USER;

typedef struct judge
{
    char username[20];
    char password[20];

} JUDGE;



int valid_username(char *p)
{
    int i=0;
    int len = strlen(p);
    if((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <='Z')) //判断首字符是不是字母
    {
        for(i = 0; i < len; i++)
        {
            if(!(p[i] == '_' || (p[i] >= 'a' && p[i] <= 'z') || (p[i] >= 'A' && p[i] <='Z')
                    ||(p[i] >='0' && p[i] <= '9'))) //判断后面字符是否有效(字母或数字或下划线)
                return 0;
        }
        return 1;
    }
    else
        return 0;
}

int valid_password(char *p)
{
    for(; *p != '\0'; p++)
    {
        if(!( (*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <='Z')
                ||(*p >='0' && *p <= '9'))) //判断字符(只能为数字或字母)是否有效
            return 0;
    }
    return 1;
}

int judge_username(char account[])//判断用户名与密码是否存在且正确
{
    int i = 0, j = 0;
    JUDGE judge[N];
    char ch;
    FILE *fp;
    if((fp = fopen("user.txt","r")) == NULL )//判断文件是否打开成功
    {
        printf("考生档案文件打开失败!");
        exit(0);
    }
    else
    {
        for(i = 0, j = 0; ch != EOF; j++)
        {
            ch = fgetc(fp);
            if(ch  == '|')
            {
                do {}
                while((ch = fgetc(fp)) != '\n');
                i++;
                j = -1;
            }
            else
                judge[i].username[j] = ch;

        }

    }
    for(i = 0; i < N; i++)
    {
        if(strcmp(judge[i].username, account) == 0)
            return 1;
    }

}

void WritetoFile(USER users)//注册后调用,将账户密码写入user.txt
{
    FILE *fp;
    if((fp=fopen("user.txt","a"))==NULL)
    {
        printf("考生档案文件打开失败!\n");
        exit(0);
    }
    fputs(users.username, fp);
    fputc('|', fp);
    fputs(users.password, fp);
    fputc('\n', fp);
    fclose(fp);
}

search_now()函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "conio.h"
#define M 1000
#define N 1000

typedef struct a
{
    char text[M][N];
    char answer[M];

} text_answer;

typedef struct date
{
    int year;
    int month;
    int day;

} DATE;

typedef struct user
{
    char username[20];
    char password[20];
    char gender;
    DATE birthday;
} USER;

typedef struct judge
{
    char username[20];
    char password[20];

} JUDGE;

typedef struct score
{
    char username[20];
    int score1;
    int score2;
    int score3;

} SCORE;


void search_now()
{

    SCORE score[N];
    int i = 0, k = 0;
    int flag = -1;
    char ch;
    char ch1 = '0', ch2;
    char account[15];
    FILE *fp;
    if((fp = fopen("score.txt","r")) == NULL )//判断文件是否打开成功
    {
        printf("考生成绩文件打开失败!");
        exit(0);
    }
    printf("请输入您想查找的用户名:");
    gets(account);
    for(i = 0, k = 0; ch != EOF; k++)
    {
        ch = fgetc(fp);
        if(ch == '|')
        {
            ch1 = fgetc(fp);
            ch2 = fgetc(fp);
            ch = fgetc(fp);
            score[i].score1 = (ch1 - 48) * 10 + (ch2 - 48);
            if(ch == '|')
            {
                for(; (ch = fgetc(fp)) != '|';)
                {
                    score[i].score2 = (int)ch - 48;//注意转换
                }
                if(ch == '|')
                    for(; (ch = fgetc(fp)) != '\n';)
                    {
                        score[i].score3 = (int)ch - 48;
                    }

            }
        }
        if(ch  == '\n')
        {
            i++;
            k = -1;
        }
        else
            score[i].username[k] = ch;
    }
    for(i = 0; i < N; i++)//本质上是在数组里查找
    {
        if(strcmp(score[i].username, account) == 0)
            flag = i;
    }
    if(flag == -1)
        printf("查无此人!");
    else
    {
        system("cls");
        printf("%s的最新成绩单:\n",score[flag].username);
        printf("判断题:%d/10, 正确率:%.2f%%\n",score[flag].score2, (float)score[flag].score2 * 10);
        printf("单选题:%d/5, 正确率:%.2f%%\n",score[flag].score3, (float)score[flag].score3 / 5 * 100);
        printf("总分:%d\n",score[flag].score1);
    }
    system("pause");
    system("cls");

}

exit_now()函数

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define M 1000
#define N 1000

void exit_now()
{
    printf("任意键退出系统!");
    exit(0);
}

功能的部分截图:
一级菜单
在这里插入图片描述
登录时
在这里插入图片描述
登陆成功后
在这里插入图片描述
判断题考试
在这里插入图片描述
查看题库
在这里插入图片描述
不定期更新博客,记录学习编程的思考与感悟。
以上 2019/12/26

猜你喜欢

转载自blog.csdn.net/qq_45888298/article/details/103718240
今日推荐