zoukankan      html  css  js  c++  java
  • C项目实践--图书管理系统(3)

    接下来将要实现用户管理模块的相关功能,用户管理模块的主要功能包括增加用户,查找用户以及保存用户等功能,查找用户时,如果查找成功,充许对查找到用户进行更新或删除操作。如果查找不成功,则给出相应的提示信息。

    打开user.c文件, 首先包含要用到的头文件,同时还需要定义一个常量用来表示存储用户信息的文件,定义一个单链表的头节点,并初试化为空。具体实现如下:

    #pragma warning(disable:4996)
     
    //Header Info
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h> //使用memset函数 memset是字符串处理函数
    #include <conio.h> //使用kbhit()函数 来星号显示密码
    #include "user.h"
    #include <assert.h>
     
    #define USER_FILE "user.dat" //表示用来存储用户信息的文件
    user* first_user = NULL;  //定义一个头节点, 初始化为NULL

    下面来实现主要的处理函数:

    1.新增用户

    函数名称:add_user

    函数功能:新增一个用户信息,在管理员操作菜单中,选择6调用本函数,由于用户名不充许重复,所以用户输入用户名和密码后,需要在用户链表中查询用户名是否重复。

    处理流程:1创建一个用户节点new_user. 2初始化new_user. 3.调用函数input_user(), 提示用户输入用户信息,为new_user赋值。4.调用函数find_user(),查找用户名是否存在,如果新增用户名不存在,则增加该用户,否则提示相应的信息。具体实现如下:

    //新增用户信息
    void add_user()
    {
        char try_again = 'Y';
        user* p = NULL;
        user* new_user= (user*)malloc(sizeof(user));
        assert(new_user != NULL);
        while(try_again == 'Y' || try_again == 'y')
        {
            memset(new_user,0,sizeof(user));
            printf(">增加用户信息...
    ");
            input_user(&(new_user->ui));
            //对比用户名是否已存在
            p = find_user(new_user->ui.username);
            if(NULL == p)
            {
                p = get_last_user();
                p->next = new_user;
                break;
            }
     
            printf(">用户[ %s ]已存在.重新输入?(y or n ):",new_user->ui.username);
            fflush(stdin);
            try_again = getchar();
            if(try_again !='y' && try_again !='Y')
            {
                free(new_user);
            }
        }
    }

    2.查找用户

    函数名称:search_user

    函数功能:查找用户信息,在管理员操作菜单中选择7调用本函数,提示用户输入要查询的用户名,在用户链表中进行查找,如果查找成功,显示该用户信息,并提示按d/D键删除该用户信息,按u/U键更新该用户信息。如果查找不成功,则给出提示信息。

    处理流程:1提示用户输入要查询的用户名,根据用户名进行查找。2调用函数find_user()查找输入的用户名信息,若存在,则将用户信息赋值给节点p。3如果没有找到,则给出提示信息,如果找到了则调用show_user()函数,显示该用户信息,并提示用户可以对该用户信息进行删除或更新操作。具体实现如下:

    void search_user()
    {
        char input_char = 'Y';
        char username[MAX_USERNAME] = {0};
        user* p = NULL;
        while(input_char == 'Y' || input_char == 'y')
        {
            printf(">查找用户信息...
    ");
            printf(">请输入用户名(最大长度为 %d):",MAX_USERNAME);
            fflush(stdin);
            scanf("%s",username);
            p = find_user(username);
            if(p == NULL)
            {
                printf(">未找到用户:%s的信息.继续查找?(y or n)",username);
                fflush(stdin);
                input_char = getchar();
                continue;
            }
            show_user(&(p->ui));
            printf(">查找成功!按d/D键删除该用户,按u/U键更新该用户信息,按其它键返回!");
            fflush(stdin);
            input_char = getchar();
            if(input_char == 'd'||input_char == 'D')
            {
                delete_user(p);
            }else if(input_char =='U' || input_char == 'u')
            {
                update_user(p);
            }
            printf(">继续查找其它用户吗?(y or n):");
            fflush(stdin);
            input_char = getchar();
        }
    }

    3.删除用户信息

    函数名称:delete_user

    函数功能:管理员在查找到用户成功时,充许对其找到的用户信息进行删除操作。

    处理流程:提示用户是否确认要删除该用户信息,如果输入"y"或"Y", 则删除该用户信息,否则继续查找。具体实现如下:

    void delete_user(user* p)
    {
        char input_char = 'N';
        user* previous = NULL;
        printf(">确认要删除用户 [%s] 吗?(y or n):",p->ui.username);
        fflush(stdin);
        input_char = getchar();
        if(input_char == 'y' || input_char == 'Y')
        {
            previous = get_previous_user(p);
            previous->next = p->next;
            free(p);
            p = NULL;
        }
    }

    4.更新用户信息

    函数名称:update_user

    函数功能:管理员在查找到用户成功时,充许对找到的用户信息进行更新操作。

    处理流程:1创建一个用户信息new_p, 2调用函数input_user()往new_p中输入用户信息。3在用户链表中查找该用户是否存在,如果输入的用户名已存在,并且这个用户名不是原来的p,系统给出相关提示信息,等待下一步操作,否则进行更新操作。具体实现如下:

    //更新用户信息
    void update_user(user* p)
    {
        char input = 'y';
        user* exist_p = NULL;
        user_info* new_p = (user_info*)malloc(sizeof(user_info));
        assert(new_p != NULL);
        while(input == 'y'|| input == 'Y')
        {
            memset(new_p,0,sizeof(user_info));
            input_user(new_p);
            //查找当前更新时输入的用户名是否已经存在
            exist_p = find_user(new_p->username);
            //如果单链表中存在这个用户名,且新更新的用户名和刚才被更新的用户名不相等
            //则表示不能进行更新
            if(exist_p != NULL && exist_p != p)
            {
                printf(">用户[%s] 已存在.请选用其它用户名.
    ",exist_p->ui.username);
                printf(">重新输入?(y or n):");
                fflush(stdin);
                input = getchar();
            }else{
                strcpy(p->ui.username,new_p->username);
                strcpy(p->ui.password,new_p->password);
                p->ui.user_type = new_p->user_type;
                break;
            }
        }
        free(new_p);
    }

    5.保存用户信息

    1.函数名称:save_users

    函数功能:管理员操作菜单中选择8调用本函数,用来保存用户信息,函数中通过调用save_users_to_file()函数将用户信息保存到文件中,并给出提示信息,具体实现如下:

    void save_users()
    {
        save_users_to_file();
        printf(">保存成功!按任意键返回...");
        fflush(stdin);
        getchar();
    }
    2.保存用户信息到文件
    函数名称:save_users_to_file
    函数功能:将用户信息保存到文件。具体实现如下:
    void save_users_to_file()
    {
        FILE* fp = fopen(USER_FILE,"wb");
        user* p = first_user;
        while(p != NULL)
        {
            fwrite(&(p->ui),sizeof(user_info),1,fp);
            fseek(fp,0,SEEK_END);
            p = p->next;
        }
     
        fclose(fp);
    }

    上面完成了用户管理模块的主要功能函数,但是还需要一些辅助函数才能完整的实现用户管理模块的功能,这些辅助函数实现如下:

    1.用户模块初始化

    函数名称:init_user

    函数功能:设定默认的用户名为admin, 密码为123,权限为管理员,如果存储用户信息的文件不存在则创建一个,如果创建失败则给出提示信息。具体实现如下:

    void init_user()
    {
        FILE* fp = NULL;
        user_info default_admin;
        strcpy(default_admin.username,"admin");
        strcpy(default_admin.password,"123");
        default_admin.user_type = ADMIN;
        fp = fopen(USER_FILE,"r");
        if(NULL == fp)
        {
            fp = fopen(USER_FILE, "wb");
            fwrite(&default_admin,sizeof(user_info),1,fp);
        }
        fclose(fp);
    }

    2.加载用户信息

    函数名称:load_users

    函数功能:从用户文件中将用户信息加载到用户链表中。具体实现如下:

    void load_users()
    {
        user* u = NULL;
        user* last = NULL;
        FILE* fp = NULL;
        int count = 0; 
        u = (user*)malloc(sizeof(user));
        memset(u,0,sizeof(user));
        u->next = NULL;
        //以只读方式打开二进制文件USER_FILE
        fp = fopen(USER_FILE , "rb");
        //将文件指针置为文件开始处
        fseek(fp,0,SEEK_SET);
        //从文件中逐个读取用户信息,并把它们存放到用户链表中
        while(fread(&(u->ui),sizeof(user_info),1,fp) == 1)
        {
            if(first_user == NULL)
            {
                first_user = u;
            }else{
                last = get_last_user();
                last->next = u;
            }
            count++;
            //以user_info长度为单位相对文件开始位置
            //偏移文件指针的位置
            fseek(fp,count*sizeof(user_info),SEEK_SET);
            u = (user*)malloc(sizeof(user));
            memset(u,0,sizeof(user));
            u->next = NULL;
        }
        free(u);
        u = NULL;
        fclose(fp);
    }

    3.判断用户类型

    函数名称:login

    函数功能:用户登录功能,如果输入正确,返回用户类型。

    处理流程:1.提示输入登录名和密码,2.在用户链表中查找是否存在该登录名,若不存在,则给出提示信息,否则继续判断密码是否匹配,如果匹配成功,则返回用户权限类型,否则给出提示信息。具体实现如下:

    USER_TYPE login()
    {
        char username[MAX_USERNAME] = {0};
        char password[MAX_PASSWORD] = {0};
        int j = 0;
        char try_again = 'Y';
        user* p = NULL;
        while(try_again == 'y' || try_again == 'Y')
        {
            printf("请输入用户名:");
            fflush(stdin);
            scanf("%s",username);
            printf("  请输入密码:");
            fflush(stdin);
            //scanf("%s",password);
            //密码输入处理:输入一个字符,回显一个星号
            getLine(password,MAX_PASSWORD);
            //printf("
    ");
            p = find_user(username);
            if(p == NULL)
            {
                printf("
    用户名输入有误.请重试!
    ");
            }else if(strcmp(p->ui.password,password) != 0)
            {
                printf("
    密码输入有误.请重试!按任意键继续...
    ");
            }else{
                return p->ui.user_type;
            }
            printf(">重新输入吗?按其它键退出系统(y or Y 继续):");
            fflush(stdin);
            try_again = getchar();
        }
        exit(0);
    }
     
    //密码输入处理,输入一个字符就回显一个星号
    char *getLine(char *buf,int len)
    {
        int i = 0;
        char ch;
        
        fflush(stdin);
        /*while(i<len-1 && '
    ' !=(ch = kbhit()))*/
        while(i<len-1)
        {
            //ch 第一次接收到一个字符之后, 以后一直存在这个字符,所以输入失效
            /*if('' != ch){*/
            if(0 != kbhit()){
                //kbhit()只能检测到键盘是否有键位按下,如果有则返回非零值,否则返回零
                //返回的这个非零值并非代码键位的ASCII值,所以返回值不能用
                //getchar()用来接收输入的字符串,输入一个就回显一个直到遇到空格或回车
                //才停止接收输入
                //ch = getchar();
                ch = getch();
                //c中 
     才是代表 回车符
                if(ch == '
    ') break;
                putchar('*');
                buf[i] = ch;
                ++i;
            }
        }
        buf[i] = '';
        return buf;
    }

    4.清除用户链表

    函数名称:clear_users

    函数功能:从内存中清除用户链表中的内容。具体实现如下:

    void clear_users()
    {
        user* p = NULL;
        //从头节点往后一个个清空
        while(first_user != NULL)
        {    
            if(first_user->next != NULL)
            {
                p = first_user;
                first_user = first_user->next;
                free(p);
                p = NULL;
            }else{
                free(first_user);
                first_user = NULL;
            }
        }
    }

    5.取用户链表中的最后一个节点

    函数名称:get_last_user

    函数功能:取得用户链表中的最后一个节点并返回该节点指针。具体实现如下:

    user* get_last_user()
    {
        user* p = first_user;
        while((NULL != p) &&(p->next != NULL))
        {
            p = p->next;
        }
        return p;
    }

    6.取某节点的前驱节点

    函数名称:get_previous_user

    函数功能:取得节点p的前驱节点并返回该节点的指针。具体实现如下:

    user* get_previous_user(user* p)
    {
        user* previous = first_user;
        while(previous != NULL)
        {
            if(previous->next == p)
            {
                break;
            }
            previous = previous->next;
        }
        return previous;
    }

    7.显示用户信息

    函数名称:show_user

    函数功能:显示用户信息。具体实现如下:

    void show_user(user_info* info)
    {
        printf("------------------------------------------
    ");
        printf("  用户名:%s
    ",info->username);
        printf("    密码:%s
    ",info->password);
        printf("用户类型:%s
    ",info->user_type == ADMIN ? "admin" : "user");
        printf("
    ");
    }

    8.输入用户信息

    函数名称:input_user

    函数功能:提示用户输入用户相关信息,具体实现如下:

    void input_user(user_info* info)
    {
        printf(">请输入用户名(最大长度为 %d):",MAX_USERNAME);
        fflush(stdin);
        scanf("%s",info->username);
        printf(">请输入密码(最大长度为 %d):",MAX_PASSWORD);
        fflush(stdin);
        scanf("%s",info->password);
        printf(">请输入用户类型(%d 是管理员,%d 是普通用户):",ADMIN,USER);
        fflush(stdin);
        scanf("%d",&(info->user_type));
    }

    9查找一个用户

    函数名称:find_user

    函数功能:从用户链表中查找指定的用户名是否存在,若存在则返回该用户节点指针,否则返回NULL。具体实现如下:

    user* find_user(char* name)
    {
        user* p = first_user;
        int is_found = 0;
        while(p != NULL)
        {
            //字段比对,如果相同则strcmp返回0
            if(strcmp(p->ui.username,name) == 0)
            {
                is_found = 1;
                break;
            }
            p = p->next;
        }
        if(is_found)
        {
            return p;
        }
        return NULL;
    }

    到此为止,图书管理系统的三大功能模块:登录管理模块,图书信息管理模块和用户信息管理模块已基本实现完毕,接下来是系统操作过程分析,具体情况请转入:<< C项目实践--图书管理系统(4)>>

  • 相关阅读:
    Oracle求连续的年份
    关于Extjs MVC模式上传文件的简单方式
    后进先出 stack、 先进先出Queue
    python的文件操作
    C#的接口
    C#的访问级别
    C#的继承
    SQL查询语句 常用示例
    SQL Server数据库常用函数
    数据库建立和连接
  • 原文地址:https://www.cnblogs.com/AI-Algorithms/p/3395613.html
Copyright © 2011-2022 走看看