从零开始的学生信息管理系统(标准C)(超全)

从零开始的学生管理系统

主要功能

学生能够登陆系统查询语文、数学、英语三科成绩,及三科的平均分、总分、排名
教师能够管理学生、录入学生考试成绩。
管理员能够管理教师,超级管理员有且只有一个,只为管理普通管理员。
除超级管理员外,所有用户连续登陆三次帐号被锁定,需要上级用户才能解锁。
除超级管理员外,所有用户id要求有序且唯一。
除超级管理员外,所有用户登陆必须修改密码。

学生功能

学生信息包括:学号、密码、姓名、性别、年龄、语文、数学、英语、平均、总分、
排名
登陆后显示姓名、语文、数据、英语、平均分、总分
可选择查看单科成绩排名、总分成绩排名
修改登陆密码

教师功能

教师信息包括:工号、密码、姓名、性别、年龄、工龄
学生信息管理:
添加学生,单个添加或批量添加
删除学生,删除后的学生记作退学学生
修改学生基本信息
重置学生密码
解锁学生帐号
根据姓名查询学生基本信息
显示所有在读学生
显示所有退学学生
学生成绩管理:
录入学生成绩,单个录入或指导入
修改学生成绩
根据学号或姓名查询学生成绩
前言
主要功能:
学生功能:
教师功能:
按各科分数和部分排序
修改登陆密码

管理员功能

添加教师,单个添加或批量添加
删除教师,删除后的老师记作离职
修改教师基本信息
重置教师密码
解锁教师帐号
根据姓名查询教师基本信息
显示所有在职教师
显示所有离职教师
修改登陆密码

超级管理员系统

添加管理员
删除管理员
重置管理员密码
解锁管理员帐号
显示所有管理员

Makefile

#source file
SRC     :=$(wildcard *.c)
OBJ     :=$(patsubst %.c,%.o,$(SRC))

#target you can change test to what you want
TARGET	:=sams

#compile and lib parameter
CC		:=gcc
STD		:=-std=c99
CFLAGS	:=-g -Wall -03

all:obj
	$(CC) $(OBJ) -o $(TARGET)

obj:
	$(CC) $(STD) -c $(SRC) $(STD)

clean:
	rm -fr *.o

sams.h

#ifndef SAMS_H
#define SAMS_H

#include "tools.h"

#define ID_PATH "data/id.bin"

// 申请内存加载数据 
void sams_init (void);
// 开始运行管理系统
void sams_start (void);
// 保存数据释放内存
void sams_exit (void);

extern uint32_t* id_a;

#endif//SAMS_H

status.h

#ifndef STATUS_H
#define STATUS_H

typedef enum 
{
    EXCEP =  1, // 执行异常
    RIGHT =  0, // 执行成功
    ERROR = -1, // 执行错误
    PRNIL = -2, // 参数为空
    SPILL = -3, // 参数过界
    IDERR = -4, // 帐号错误
    PDERR = -5  // 密码错误
}Status;

#define nil (0)

#endif//STATUS_H

tool.h

#ifndef TOOLS_H
#define TOOLS_H

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <time.h>
#include "get_keyboard.h"

#define pf  printf
#define sf  scanf

// 获取当前年份
uint16_t get_current_year(void);
// 清理屏幕
void clear_src(void);
// 任意键继续
void anykey_continue(void);
// 显示提示信息
void show_msg(const char* msg,time_t t);
// 从键盘获取指令
char get_cmd(char begin_cmd,char end_cmd);
// 获取性别
char get_sex(void);
// 获取年份
uint16_t get_year(void);
// 获取成绩
bool get_score(float* score_p);
// 从键盘获取密码
char* get_passwd(char* pd,size_t hope_len,bool is_show);
// 从键盘获取字符串
char* get_str(char* str,size_t hope_len);
// 从文件加载数据
int load_data(const char* path,void* ptr,size_t node_size);
// 保存数据到文件
int save_data(const char* path,const void* ptr,size_t node_size,size_t num);

#endif//TOOLS_H

student.h

#ifndef STUDENT_H
#define STUDENT_H

#include "tools.h"

#define S_DATA_PATH     "data/s_data.bin"
#define SD_DATA_PATH    "data/sd_data.bin"
#define STU_MAX         50

typedef struct Student
{
    uint32_t    id;        // 学号
    uint32_t    pd;        // 密码
    char        name[20];  // 姓名
    char        sex;       // 性别
    uint16_t    age;       // 年龄
    float       score_c;   // 语文
    float       score_m;   // 数学
    float       score_e;   // 英语
    float       score_s;   // 总分
    float       score_a;   // 平均
    int8_t      rank;      // 排名
    bool        is_stop;   // 是否禁用
}Student;

// 学生数组指针
extern Student* stu_a;
// 学生数组使用量
extern size_t stu_n;

// 学生登陆
int stu_login(const char* id_p,const char* pd_p);
// 进入学生子系统
void stu_enter(Student* stu_p);
// 显示学生信息
void stu_show(Student* stu_p);
// 显示学生成绩
void stu_show_score(Student* stu_p);
// 语文成绩排名
void stu_rank_c(void);
// 数学成绩排名
void stu_rank_m(void);
// 英语成绩排名
void stu_rank_e(void);
// 总分成绩排名
void stu_rank_s(void);

#endif//STUDENT_H

teacher.h

#ifndef TEACHER_H
#define TEACHER_H

#include "tools.h"

#define T_DATA_PATH     "data/t_data.bin"
#define TD_DATA_PATH    "data/td_data.bin"
#define TCH_MAX         10

typedef struct Teacher
{
    uint32_t    id;         // 工号
    uint32_t    pd;         // 密码
    char        name[20];   // 姓名
    char        sex;        // 性别
    uint16_t    age;        // 年龄
    uint16_t    age_w;      // 工龄
    bool        is_stop;    // 是否停用
}Teacher;

extern Teacher* tch_a;
extern size_t tch_n;

// 教师登陆
int tch_login(const char* id_p,const char* pd_p);

// 进入教师子系统
void tch_enter(Teacher* tch_p);

// 显示老师基本信息
void tch_show(Teacher* tch_p);

#endif//TEACHER_H

manager.h

#ifndef MANAGER_H
#define MANAGER_H

#include "tools.h"

#define M_DATA_PATH     "data/m_data.bin"
#define MD_DATA_PATH    "data/md_data.bin"
#define MGR_MAX     5

typedef struct Manager
{
    uint32_t    id;         // 帐号
    uint32_t    pd;         // 密码
    bool        is_stop;    // 是否停用
}Manager;

// 管理员数组指针
extern Manager* mgr_a;
// 管理员数组使用量
extern size_t mgr_n;

// 管理员登陆
int mgr_login(const char* id_p,const char* pd_p);
// 进行管理员子系统
void mgr_enter(Manager* mgr_p);
// 显示管理员
void mgr_show(Manager* mgr_p);
#endif//MANAGER_H

admin.h

#ifndef ADMIN_H
#define ADMIN_H

// 登陆超级管理员
int admin_login (const char* id,const char* pd);

// 进入超级管理员子系统
void admin_enter (void);

#endif//ADMIN_H

admin.c

#include "admin.h"
#include "sams.h"
#include "manager.h"
#include "tools.h"
#include "status.h"


// 根据帐号查找管理员对象的下标
int admin_find_mgr(uint32_t id)
{
    for(int i=0; i<mgr_n; i++)
    {
        if(id == mgr_a[i].id) return i;
    }
    
    return ERROR;
}

// 添加管理员
static void admin_add_mgr (void)
{
    if(mgr_n >= MGR_MAX)
    {
        show_msg("*** 管理员已满,无法添加! ***",1);
        return;
    }
    
    mgr_a[mgr_n].id = id_a[0]++;
    mgr_a[mgr_n].pd = 111111;
    mgr_a[mgr_n].is_stop = false;
    pf("*** 管理员:%u 添加成功! ***",mgr_a[mgr_n].id);
    show_msg("",1);
    mgr_n++;
    
}

// 删除管理员
static void admin_del_mgr (void)
{
    if(0 >= mgr_n)
    {
        show_msg("*** 系统内无管理员! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要删除的管理员帐号:");
    sf("%u",&id);
    
    int index = admin_find_mgr(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    
    pf("请再次输入要删除的管理员帐号:");
    sf("%u",&id);
    if(id != mgr_a[index].id)
    {
        show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
        return;
    }
    
    memcpy(mgr_a+index,mgr_a+index+1,(mgr_n-index-1)*sizeof(Manager));
    show_msg("*** 删除帐号成功! ***",1);     
    mgr_n--;
}

// 解锁管理员
static void admin_unlock_mgr (void)
{
    if(0 >= mgr_n)
    {
        show_msg("*** 系统内无管理员! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要解锁的管理员帐号:");
    sf("%u",&id);
    
    int index = admin_find_mgr(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    
    if(!mgr_a[index].is_stop)
    {
        show_msg("*** 此帐号未被锁! ***",1);
        return;
    }
    
    mgr_a[index].is_stop = false;
    show_msg("*** 解锁帐号成功! ***",1); 
}

// 重置管理员密码
static void admin_reset_mgr (void)
{
    if(0 >= mgr_n)
    {
        show_msg("*** 系统内无管理员! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要重置的管理员帐号:");
    sf("%u",&id);
    int index = admin_find_mgr(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    pf("请再次输入要重置的管理员帐号:");
    sf("%u",&id);
    if(id != mgr_a[index].id)
    {
        show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
        return;
    }
    
    mgr_a[index].pd = 111111;
    show_msg("*** 重置密码成功! ***",1); 
}

// 列出所有管理员
static void admin_list_mgr (void)
{
    clear_src();
    puts("******显示所有管理员******");
    for(int i=0; i<mgr_n; i++)
    {
        mgr_show(mgr_a+i);        
    }
    anykey_continue();
}

// 登陆超级管理员
int admin_login(const char* id,const char* pd)
{
    if(NULL == id || NULL == pd) return PRNIL;

    if(strcmp(id,"zhizhen")) return IDERR;

    if(strcmp(pd,"zzxxwyz")) return PDERR;

    admin_enter ();
    return RIGHT;
}


// 进入超级管理员子系统
void admin_enter (void)
{
    while(true)
    {
        clear_src();
        puts("***超级管理员子系统***");
        puts("   0.添加管理员");
        puts("   1.删除管理员");
        puts("   2.重置管理员密码");
        puts("   3.解锁管理员");
        puts("   4.列出所有管理员");
        puts("   5.退出超级管理员");
        puts("---------------------");

        switch(get_cmd('0','5'))
        {
            case '0': admin_add_mgr(); break;
            case '1': admin_del_mgr(); break;
            case '2': admin_reset_mgr(); break;
            case '3': admin_unlock_mgr(); break;
            case '4': admin_list_mgr(); break;
            case '5': return;
        }
    }
}

manager.c

#include <strings.h>
#include "manager.h"
#include "teacher.h"
#include "sams.h"
#include "status.h"
#include "tools.h"

// 管理员数组指针
Manager* mgr_a;
// 管理员数组使用量
size_t mgr_n;

int mgr_find_tch(uint32_t id)
{
    for(int i=0; i<tch_n; i++)
    {
        if(id == tch_a[i].id) return i;
    }
    
    return ERROR;
}

// 添加一个教师
void mgr_add_one_tch(void)
{
    bzero(tch_a+tch_n,sizeof(Teacher));

    pf("请输入教师姓名:");
    get_str(tch_a[tch_n].name,20);
    pf("请输入教师性别:");
    tch_a[tch_n].sex = get_sex();
    pf("请输入教师出生年份:");
    tch_a[tch_n].age = get_year();
    pf("请输入教师入职年份:");
    tch_a[tch_n].age_w = get_year();
    
    tch_a[tch_n].id = id_a[1]++;
    tch_a[tch_n].pd = 222222;
    tch_n++;
    
    show_msg("*** 添加教师成功! ***",1);
}

// 批量添加教师
void mgr_add_multi_tch(void)
{
    char path[30] = {};
    pf("请输入要导入的文件名:");
    get_str(path,30);
    FILE* frp = fopen(path,"r");
    if(NULL == frp)
    {
        show_msg("*** 输入的路径有误! ***",1);
    }
    
    Teacher* tch_p = tch_a+tch_n;
    size_t num_r = 0;
    size_t num_s = 0;
    while(tch_n<TCH_MAX)
    {
        bzero(tch_p,sizeof(Teacher));
        if(!fscanf(frp,"%s %c %hu %hu\n",
            tch_p->name,&tch_p->sex,&tch_p->age,&tch_p->age_w))
            break;
            
        num_r++;
        if('f' != tch_p->sex && 'm' != tch_p->sex) continue;
        if(1950 > tch_p->age || tch_p->age > get_current_year()-18) continue;
        if(tch_p->age+18 > tch_p->age_w  || 
           tch_p->age_w > get_current_year()) continue;
           
        tch_p->id = id_a[1]++;
        tch_p->pd = 222222;
        tch_p->is_stop = false;
        
        tch_show(tch_p);
        tch_n++;
        tch_p++;
        num_s++;
    }
    printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
    anykey_continue();  
}

// 添加教师
void mgr_add_tch(void)
{
    if(tch_n >= TCH_MAX)
    {
        show_msg("*** 教师已满,无法添加! ***",1);
        return;
    }
    
    clear_src();
    puts("***添加教师***");
    puts("   0.单个添加");
    puts("   1.批量添加");
    puts("-------------");
    switch(get_cmd('0','1'))
    {
        case '0': mgr_add_one_tch(); break;
        case '1': mgr_add_multi_tch(); break;
    }    
}

// 删除教师
void mgr_del_tch(void)
{
    if(0 >= tch_n)
    {
        show_msg("*** 系统内无教师! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要删除的教师帐号:");
    sf("%u",&id);
    
    int index = mgr_find_tch(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    
    pf("请再次输入要删除的管理员帐号:");
    sf("%u",&id);
    if(id != tch_a[index].id)
    {
        show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
        return;
    }
    
    FILE* fap = fopen(TD_DATA_PATH,"a");
    fwrite(tch_a+index,sizeof(Teacher),1,fap);
    fclose(fap);
        
    memcpy(tch_a+index,tch_a+index+1,(tch_n-index-1)*sizeof(Teacher));
    show_msg("*** 删除帐号成功! ***",1);     
    tch_n--;
}

// 修改教师信息
void mgr_mod_tch(void)
{
    uint32_t id;
    pf("请输入要修改的教师帐号:");
    sf("%u",&id);
    int index = mgr_find_tch(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    while(true)
    {
        clear_src();
        tch_show(tch_a+index);
        puts("***请选择要修改的教师信息***");
        puts("   0.修改教师姓名");
        puts("   1.修改教师性别");
        puts("   2.修改教师出生年份");
        puts("   3.修改教师入职年份");
        puts("   4.返回上一级");
        puts("-------------------------");
        switch(get_cmd('0','4'))
        {
            case '0': 
                pf("请输入教师姓名:");
                get_str(tch_a[index].name,20); break;
            case '1':
                pf("请输入教师性别:");
                tch_a[index].sex = get_sex(); break;
            case '2': 
                pf("请输入教师出生年份:");
                tch_a[index].age = get_year(); break;
            case '3':
                pf("请输入教师入职年份:");
                tch_a[index].age_w = get_year(); break;
            case '4': return;
        }
        show_msg("*** 修改成功! ***",1);
    }
}

// 重置教师密码
void mgr_reset_tch(void)
{
    if(0 >= mgr_n)
    {
        show_msg("*** 系统内无教师! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要重置的教师帐号:");
    sf("%u",&id);
    int index = mgr_find_tch(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    pf("请再次输入要重置的教师帐号:");
    sf("%u",&id);
    if(id != tch_a[index].id)
    {
        show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
        return;
    }
    
    tch_a[index].pd = 222222;
    show_msg("*** 重置密码成功! ***",1);
}

// 解锁教师帐号
void mgr_nulock_tch(void)
{
    if(0 >= tch_n)
    {
        show_msg("*** 系统内无教师! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要解锁的教师帐号:");
    sf("%u",&id);
    int index = mgr_find_tch(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }if(!tch_a[index].is_stop)
    {
        show_msg("*** 此帐号未被锁! ***",1);
        return;
    }
    tch_a[index].is_stop = false;
    show_msg("*** 解锁帐号成功! ***",1); 
}

// 查询教师基本信息
void mgr_query_tch(void)
{
    char name[20] = {};
    pf("请输入要查询的老师姓名:");
    get_str(name,20);
    
    bool flag = true;
    for(int i=0; i<tch_n; i++)
    {
        if(!strcmp(name,tch_a[i].name))
        {
            tch_show(tch_a+i);
            flag = false;
        }
    }
    
    flag ? show_msg("*** 查无此人! ***",1) : anykey_continue(); 
}

// 显示所有在职教师
void mgr_job_tch(void)
{
    clear_src();
    puts("******所有在职教师******");
    for(int i=0; i<tch_n; i++)
    {
        tch_show(tch_a+i);
    }
    anykey_continue();
}

// 显示所有离职教师
void mgr_quit_tch(void)
{
    FILE* frp = fopen(TD_DATA_PATH,"r");
    if(NULL == frp)
    {
        show_msg("*** 斩无离职教师! ***",1);
        return;
    }
    
    clear_src();
    puts("******所有离职教师******");
    Teacher tch;
    while(fread(&tch,sizeof(tch),1,frp)) tch_show(&tch);
    fclose(frp);
    
    anykey_continue();
}

// 修改管理员登陆密码
void mgr_mod_pd(Manager* mgr_p)
{
    pf("请输入新密码:");
    char pd[20] = {};
    get_passwd(pd,20,true);
    char re_pd[20] = {};
    pf("请再次输入新密码:");
    get_passwd(re_pd,20,true);
    if(strcmp(pd,re_pd))
    {
        show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
        return;
    }
    
    mgr_p->pd = atoi(pd);
    show_msg("*** 修改密码成功! ***",1);
}

// 管理员登陆
int mgr_login(const char* id_p,const char* pd_p)
{
    if(NULL == id_p || NULL == pd_p) return PRNIL;
    
    uint32_t id = atoi(id_p);
    uint32_t pd = atoi(pd_p);
    
    int i = 0;
    for(; i<mgr_n; i++)
    {
        if(id == mgr_a[i].id) break;
    }
    
    if(i == mgr_n) return IDERR;
    
    if(mgr_a[i].is_stop)
    {
        show_msg("***此帐号被锁,请联系超级管理员解锁!***",1);
        return RIGHT;
    }
    
    if(pd != mgr_a[i].pd) return PDERR;
    
    mgr_enter(mgr_a+i);
    return RIGHT;
}

// 进行管理员子系统
void mgr_enter(Manager* mgr_p)
{
    while(true)
    {
        clear_src();
        pf("管理员:%u\n",mgr_p->id);
        puts("***进入管理员子系统***");
        puts("   0.添加教师");
        puts("   1.删除教师");
        puts("   2.修改教师信息");
        puts("   3.重置教师密码");
        puts("   4.解锁教师帐号");
        puts("   5.查询教师基本信息");
        puts("   6.显示所有在职教师");
        puts("   7.显示所有离职教师");
        puts("   8.修改管理员密码");
        puts("   9.退出管理员子系统");
        puts("---------------------");
        
        switch(get_cmd('0','9'))
        {
            case '0': mgr_add_tch(); break;
            case '1': mgr_del_tch(); break;
            case '2': mgr_mod_tch(); break;
            case '3': mgr_reset_tch(); break;
            case '4': mgr_nulock_tch(); break;
            case '5': mgr_query_tch(); break;
            case '6': mgr_job_tch(); break;
            case '7': mgr_quit_tch(); break;
            case '8': mgr_mod_pd(mgr_p); break;
            case '9': return;
        }
    }
}

// 显示管理员
void mgr_show(Manager* mgr_p)
{
	pf("帐号:%u  状态:%s\n",mgr_p->id,mgr_p->is_stop?"锁定":"正常");
}
    

teacher.c

#include <strings.h>
#include "sams.h"
#include "teacher.h"
#include "student.h"
#include "status.h"

Teacher* tch_a;
size_t tch_n;

int tch_find_stu(uint32_t id)
{
    for(int i=0; i<stu_n; i++)
    {
        if(id == stu_a[i].id) return i;
    }
    
    return ERROR;
}

// 单个添加学生
void tch_add_one_stu()
{
    bzero(stu_a+stu_n,sizeof(Student));
    
    pf("请输入学生姓名:");
    get_str(stu_a[stu_n].name,20);
    pf("请输入学生性别:");
    stu_a[stu_n].sex = get_sex();
    pf("请输入学生出生年份:");
    stu_a[stu_n].age = get_year();
    
    stu_a[stu_n].id = id_a[2]++;
    stu_a[stu_n].pd = 222222;
    stu_n++;
    
    show_msg("*** 添加学生成功! ***",1);
}

// 批量添加学生
void tch_add_multi_stu()
{
    char path[30] = {};
    pf("请输入要导入的文件名:");
    get_str(path,30);
    FILE* frp = fopen(path,"r");
    if(NULL == frp)
    {
        show_msg("*** 输入的路径有误! ***",1);
    }
    
    Student* stu_p = stu_a+stu_n;
    size_t num_r = 0;
    size_t num_s = 0;
    while(stu_n<STU_MAX)
    {
        bzero(stu_p,sizeof(Student));
        if(!fscanf(frp,"%s %c %hu\n",
            stu_p->name,&stu_p->sex,&stu_p->age))
            break;
            
        num_r++;
        if('f' != stu_p->sex && 'm' != stu_p->sex) continue;
        if(1950 > stu_p->age || stu_p->age > get_current_year()-5) continue;
           
        stu_p->id = id_a[1]++;
        stu_p->pd = 333333;
        
        stu_show(stu_p);
        stu_n++;
        stu_p++;
        num_s++;
    }
    printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
    anykey_continue();  
}

// 添加学生
void tch_add_stu(void)
{
    if(stu_n >= STU_MAX)
    {
        show_msg("*** 学生已满,无法添加! ***",1);
        return;
    }
    
    clear_src();
    puts("***添加学生***");
    puts("   0.单个添加");
    puts("   1.批量添加");
    puts("-------------");
    switch(get_cmd('0','1'))
    {
        case '0': tch_add_one_stu(); break;
        case '1': tch_add_multi_stu(); break;
    } 
}

// 删除学生
void tch_del_stu(void)
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要删除的学生帐号:");
    sf("%u",&id);
    
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    
    pf("请再次输入要删除的管理员帐号:");
    sf("%u",&id);
    if(id != stu_a[index].id)
    {
        show_msg("*** 两次输入的帐号不符,删除失败! ***",1);
        return;
    }
    
    FILE* fap = fopen(SD_DATA_PATH,"a");
    fwrite(stu_a+index,sizeof(Student),1,fap);
    fclose(fap);
        
    memcpy(stu_a+index,stu_a+index+1,(stu_n-index-1)*sizeof(Student));
    show_msg("*** 删除帐号成功! ***",1);     
    stu_n--;
}

// 修改学生信息
void tch_mod_stu(void)
{
    uint32_t id;
    pf("请输入要修改的学生帐号:");
    sf("%u",&id);
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    while(true)
    {
        clear_src();
        stu_show(stu_a+index);
        puts("***请选择要修改的学生信息***");
        puts("   0.修改学生姓名");
        puts("   1.修改学生性别");
        puts("   2.修改学生出生年份");
        puts("   3.返回上一级");
        puts("-------------------------");
        switch(get_cmd('0','4'))
        {
            case '0': 
                pf("请输入学生姓名:");
                get_str(stu_a[index].name,20); break;
            case '1':
                pf("请输入学生性别:");
                stu_a[index].sex = get_sex(); break;
            case '2': 
                pf("请输入学生出生年份:");
                stu_a[index].age = get_year(); break;
            case '3': return;
        }
        show_msg("*** 修改成功! ***",1);
    }
}

// 重置学生密码
void tch_reset_stu(void)
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要重置的学生帐号:");
    sf("%u",&id);
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    pf("请再次输入要重置的教师帐号:");
    sf("%u",&id);
    if(id != stu_a[index].id)
    {
        show_msg("*** 两人些输入的帐号不符,重置失败! ***",1);
        return;
    }
    
    stu_a[index].pd = 333333;
    show_msg("*** 重置密码成功! ***",1);
}

// 解锁学生帐号
void tch_nulock_stu(void)
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要解锁的学生帐号:");
    sf("%u",&id);
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    if(!stu_a[index].is_stop)
    {
        show_msg("*** 此帐号未被锁! ***",1);
        return;
    }
    stu_a[index].is_stop = false;
    show_msg("*** 解锁帐号成功! ***",1); 
}

// 查询学生信息
void tch_query_stu(void)
{
    char name[20] = {};
    pf("请输入要查询的学生姓名:");
    get_str(name,20);
    
    bool flag = true;
    for(int i=0; i<stu_n; i++)
    {
        if(!strcmp(name,stu_a[i].name))
        {
            stu_show(stu_a+i);
            flag = false;
        }
    }
    
    flag ? show_msg("*** 查无此人! ***",1) : anykey_continue();
}

// 显示在读学生
void tch_inshl_stu(void)
{

    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }

    clear_src();
    puts("******在读学生******");
    for(int i=0; i<stu_n; i++)
    {
        stu_show(stu_a+i);
    }
    anykey_continue();
}

// 显示退学学生
void tch_drop_stu(void)
{
    FILE* frp = fopen(SD_DATA_PATH,"r");
    if(NULL == frp)
    {
        show_msg("*** 斩无退学学生! ***",1);
        return;
    }
    
    clear_src();
    puts("******所有退学学生******");
    Student stu;
    while(fread(&stu,sizeof(stu),1,frp)) stu_show(&stu);
    fclose(frp);
    
    anykey_continue();
}

// 录入单个学生的成绩
void tch_input_one_stu()
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要修改成绩的学生帐号:");
    sf("%u",&id);
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }
    
    
    pf("请输入语文,数学,英语成绩:");
    float sc = 0 , sm = 0 , se = 0;
    sf("%f%f%f",&sc,&sm,&se);
    if(sc < 0 || sc > 100 || sm < 0 || sm > 100 || se < 0 || se > 100)
    {
        show_msg("*** 输入的成绩有误! ***",1);
        return;
    }
    stu_a[index].score_c = sc;
    stu_a[index].score_m = sm;
    stu_a[index].score_e = se;
    stu_a[index].score_s = sc + sm + se;
    stu_a[index].score_a = stu_a[index].score_s /3;
    stu_show_score(stu_a+index);
    show_msg("*** 录入成功! ***",1);
}

void tch_input_multi_stu()
{
    char path[30] = {};
    pf("请输入要导入的文件名:");
    get_str(path,30);
    FILE* frp = fopen(path,"r");
    if(NULL == frp)
    {
        show_msg("*** 输入的路径有误! ***",1);
    }
    
    size_t num_r = 0;
    size_t num_s = 0;
    uint32_t id = 0;
    int index = 0;
    float sc = 0 , sm = 0 , se = 0;
    while(fscanf(frp,"%u %f %f %f\n",&id,&sc,&sm,&se))
    {      
        num_r++;
         
        if(ERROR == (index = tch_find_stu(id))) continue;
        if(sc < 0 || sc > 100 || sm < 0 || sm > 100 || se < 0 || se > 100)
            continue;
        stu_a[index].score_c = sc;
        stu_a[index].score_m = sm;
        stu_a[index].score_e = se;
        stu_a[index].score_s = sc + sm + se;
        stu_a[index].score_a = stu_a[index].score_s /3;
        stu_show_score(stu_a+index);
        num_s++;
    }
    printf("*** 共读取到%u条数据,成功添加%u位教师! ***",num_r,num_s);
    anykey_continue();  
}

// 录入学生成绩
void tch_input_scr(void)
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    clear_src();
    puts("***添加学生***");
    puts("   0.单个录入");
    puts("   1.批量录入");
    puts("-------------");
    switch(get_cmd('0','1'))
    {
        case '0': tch_input_one_stu(); break;
        case '1': tch_input_multi_stu(); break;
    } 
}

// 修改学生成绩
void tch_mod_scr(void)
{
    if(0 >= stu_n)
    {
        show_msg("*** 系统内无学生! ***",1);
        return;
    }
    
    uint32_t id = 0;
    pf("请输入要修改成绩的学生帐号:");
    sf("%u",&id);
    int index = tch_find_stu(id);
    if(ERROR == index)
    {
        show_msg("*** 不存在此帐号! ***",1);
        return;
    }

    while(true)
    {
        clear_src();
        stu_show_score(stu_a+index);
        puts("***请选择要修改的成绩的科目**");
        puts("   0.修改语文成绩");
        puts("   1.修改数学成绩");
        puts("   2.修改英语成绩");
        puts("   3.返回上一级");
        puts("-------------------------");
        switch(get_cmd('0','3'))
        {
            case '0': 
                pf("请输入语文成绩:");
                if(!get_score(&stu_a[index].score_c)) continue;
                break;
            case '1':
                pf("请输入数学成绩:");
                if(!get_score(&stu_a[index].score_m)) continue;
                break;
            case '2': 
                pf("请输入英语成绩:");
                if(!get_score(&stu_a[index].score_e)) continue;
                break;
            case '3': return;
        }
        stu_a[index].score_s = stu_a[index].score_c + 
            stu_a[index].score_m + stu_a[index].score_e;
        stu_a[index].score_a = stu_a[index].score_s /3;  
        show_msg("*** 修改成功! ***",1);
    } 
}

// 查询学生成绩
void tch_query_scr(void)
{
    char name[20] = {};
    pf("请输入要查询的学生姓名:");
    get_str(name,20);
    
    bool flag = true;
    for(int i=0; i<stu_n; i++)
    {
        if(!strcmp(name,stu_a[i].name))
        {
            stu_show_score(stu_a+i);
            flag = false;
        }
    }
    
    flag ? show_msg("*** 查无此人! ***",1) : anykey_continue();
}

// 各科成绩排名
void tch_rank_scr(void)
{
    while(true)
    {
        clear_src();
        puts("***查看各科成绩排名***");
        puts("   0.语文成绩排名");
        puts("   1.数学成绩排名");
        puts("   2.英语成绩排名");
        puts("   3.总分成绩排名");
        puts("   4.退出");
        puts("------------------");
        switch(get_cmd('0','4'))
        {
            case '0': stu_rank_c(); break;
            case '1': stu_rank_m(); break;
            case '2': stu_rank_e(); break;
            case '3': stu_rank_s(); break;
            case '4': return;
        }
        for(int i=0; i<stu_n; i++)
        {
            stu_show_score(stu_a+i);
        }
        anykey_continue();
    }
}

// 修改登陆密码
void tch_mod_pd(Teacher* tch_p)
{
    pf("请输入新密码:");
    char pd[20] = {};
    get_passwd(pd,20,true);
    char re_pd[20] = {};
    pf("请再次输入新密码:");
    get_passwd(re_pd,20,true);
    if(strcmp(pd,re_pd))
    {
        show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
        return;
    }
    
    tch_p->pd = atoi(pd);
    show_msg("*** 修改密码成功! ***",1);
}

// 教师登陆
int tch_login(const char* id_p,const char* pd_p)
{
    uint32_t id = atoi(id_p);
    uint32_t pd = atoi(pd_p);
    
    int i = 0;
    for(; i<tch_n; i++)
    {
        if(id == tch_a[i].id) break;
    }
    
    if(i == tch_n) return IDERR;
    
    if(tch_a[i].is_stop)
    {
        show_msg("***此帐号被锁,请联系管理员解锁!***",1);
        return RIGHT;
    }
    
    if(pd != tch_a[i].pd) return PDERR;
    
    tch_enter(tch_a+i);
    return RIGHT;
}



// 进入教师子系统
void tch_enter(Teacher* tch_p)
{
    while(true)
    {
        clear_src();
        pf("教师:%u  姓名:%s\n",tch_p->id,tch_p->name);
        puts("***进入教师子系统***");
        puts("   0.添加学生");
        puts("   1.删除学生");
        puts("   2.修改学生信息");
        puts("   3.重置学生密码");
        puts("   4.解锁学生帐号");
        puts("   5.查询学生信息");
        puts("   6.显示在读学生");
        puts("   7.显示退学学生");
        puts("   8.录入学生成绩");
        puts("   9.修改学生成绩");
        puts("   a.查询学生成绩");
        puts("   b.各科成绩排名");
        puts("   c.修改登陆密码");
        puts("   d.退出教师子系统");
        puts("------------------");
        switch(get_cmd('0','d'))
        {
            case '0': tch_add_stu(); break;
            case '1': tch_del_stu(); break;
            case '2': tch_mod_stu(); break;
            case '3': tch_reset_stu(); break;
            case '4': tch_nulock_stu(); break;
            case '5': tch_query_stu(); break;
            case '6': tch_inshl_stu(); break;
            case '7': tch_drop_stu(); break;
            case '8': tch_input_scr(); break;
            case '9': tch_mod_scr(); break;
            case 'a': tch_query_scr(); break;
            case 'b': tch_rank_scr(); break;
            case 'c': tch_mod_pd(tch_p); break;
            case 'd': return;
        }
    }
}

// 显示老师基本信息
void tch_show(Teacher* tch_p)
{
    pf("帐号:%u 姓名:%s 性别:%s 年龄:%hhu 工龄:%hhu 状态:%s\n",
        tch_p->id,tch_p->name,'m' == tch_p->sex ? "男" : "女",
        get_current_year() - tch_p->age,get_current_year() - tch_p->age_w,
        tch_p->is_stop ? "锁定" : "正常");
}

student.c

#include "student.h"
#include "status.h"

// 学生数组指针
Student* stu_a;
// 学生数组使用量
size_t stu_n;

// 语言成绩比较
int stu_cmp_c(const void* stu_p1,const void* stu_p2)
{
    return ((Student*)stu_p1)->score_c < ((Student*)stu_p2)->score_c;
}

// 数学成绩比较
int stu_cmp_m(const void* stu_p1,const void* stu_p2)
{
    return ((Student*)stu_p1)->score_m < ((Student*)stu_p2)->score_m;
}

// 英语成绩比较
int stu_cmp_e(const void* stu_p1,const void* stu_p2)
{
    return ((Student*)stu_p1)->score_e < ((Student*)stu_p2)->score_e;
}

// 总分成绩比较
int stu_cmp_s(const void* stu_p1,const void* stu_p2)
{
    return ((Student*)stu_p1)->score_s < ((Student*)stu_p2)->score_s;
}

// 学生登陆
int stu_login(const char* id_p,const char* pd_p)
{
    uint32_t id = atoi(id_p);
    uint32_t pd = atoi(pd_p);
    
    int i = 0;
    for(; i<stu_n; i++)
    {
        if(id == stu_a[i].id) break;
    }
   
    if(i == stu_n) return IDERR;
    
    if(stu_a[i].is_stop)
    {
        show_msg("***此帐号被锁,请联系教师解锁!***",1);
        return RIGHT;
    }
    
    if(pd != stu_a[i].pd) return PDERR;
    
    stu_enter(stu_a+i);
    return RIGHT;
}

// 语文成绩排名
void stu_rank_c(void)
{
    qsort(stu_a,stu_n,sizeof(Student),stu_cmp_c);
    for(int i=0; i<stu_n; i++)
        stu_a[i].rank = i+1;
}

// 数学成绩排名
void stu_rank_m(void)
{
    qsort(stu_a,stu_n,sizeof(Student),stu_cmp_m);
    for(int i=0; i<stu_n; i++)
        stu_a[i].rank = i+1;
}

// 英语成绩排名
void stu_rank_e(void)
{
    qsort(stu_a,stu_n,sizeof(Student),stu_cmp_e);
    for(int i=0; i<stu_n; i++)
        stu_a[i].rank = i+1;
}

// 总分成绩排名
void stu_rank_s(void)
{
    qsort(stu_a,stu_n,sizeof(Student),stu_cmp_s);
    for(int i=0; i<stu_n; i++)
        stu_a[i].rank = i+1;
}

// 修改登陆密码
void stu_mod_pd(Student* stu_p)
{
    pf("请输入新密码:");
    char pd[20] = {};
    get_passwd(pd,20,true);
    char re_pd[20] = {};
    pf("请再次输入新密码:");
    get_passwd(re_pd,20,true);
    if(strcmp(pd,re_pd))
    {
        show_msg("*** 两次输入密码不一致,修改密码失败! ***",1);
        return;
    }
    
    stu_p->pd = atoi(pd);
    show_msg("*** 修改密码成功! ***",1);
}

// 进入学生子系统
void stu_enter(Student* stu_p)
{
    while(true)
    {
        clear_src();
        puts("***进入学生子系统***");
        puts("   0.语文成绩排名");
        puts("   1.数学成绩排名");
        puts("   2.英语成绩排名");
        puts("   3.总分成绩排名");
        puts("   4.修改登陆密码");
        puts("   5.退出学生子系统");
        puts("------------------");
        switch(get_cmd('0','5'))
        {
            case '0': 
                stu_rank_c(); 
                pf("语文成绩:%g",stu_p->score_c); 
                break;
            case '1': 
                stu_rank_m(); 
                pf("数学成绩:%g",stu_p->score_m); 
                break;
            case '2': 
                stu_rank_e(); 
                pf("英语成绩:%g",stu_p->score_e); 
                break;
            case '3': 
                stu_rank_s(); 
                pf("总分成绩:%g",stu_p->score_s); 
                break;
            case '4': stu_mod_pd(stu_p); continue;
            case '5': return;
        }
        pf(" 排名第%u \n",stu_p->rank);
        anykey_continue();
    }
}

// 显示学生信息
void stu_show(Student* stu_p)
{
    pf("学号:%u 姓名:%s 性别:%s 年龄:%hu\n",stu_p->id,stu_p->name,
        'm' == stu_p->sex ? "男" : "女",get_current_year() - stu_p->age);
}

// 显示学生成绩
void stu_show_score(Student* stu_p)
{
    pf("学号:%u 姓名:%s 语文:%g 数学%g 英语:%g 平均%g 总分%g\n",
        stu_p->id,stu_p->name,stu_p->score_c,stu_p->score_m,
        stu_p->score_e,stu_p->score_a,stu_p->score_s);
}

tools.c

#include <get_keyboard.h>

#include "tools.h"
#include "status.h"

// 获取当前年份
uint16_t get_current_year(void)
{
    time_t sec = time(NULL);
    struct tm* gmt = gmtime(&sec);
    return 1900 + gmt->tm_year;

}
// 清理输入缓冲区
static void clear_stdin(void)
{
    stdin->_IO_read_ptr = stdin->_IO_read_end;
}

// 清理屏幕
void clear_src(void)
{
    system("clear");
}

// 任意键继续
void anykey_continue(void)
{
    pf("按任意键继续...");
    get_keyboard();
    pf("\n");
}

// 显示提示信息
void show_msg(const char* msg,time_t t)
{
    pf("%s\n",msg);
    sleep(t);
}

// 获取性别
char get_sex(void)
{
    while(true)
    {
        char sex = get_keyboard();
        if('f' == sex || 'm' == sex) 
        {
            pf("%c\n",sex);
            return sex;
        }
    }
}

// 获取年份
uint16_t get_year(void)
{
    while(true)
    {
        uint16_t year = 0;
        for(int i=0; i<4; i++)
        {
            year *= 10;
            char ch = get_keyboard();
            pf("%c",ch);
            year += ch-'0';
        }
        
        if(year > 1950 && year < get_current_year()) 
        {
            pf("\n");
            return year;
        }
        pf("\b\b\b\b    \b\b\b\b");
    }
}

// 获取成绩
bool get_score(float* score_p)
{
    float score = 0;
    sf("%f",&score);
    if(score < 0 || score > 100)
    {
        show_msg("*** 输入的数据有误,请重新输入! ***",1);
        return false;
    }
    
    *score_p = score;
    return true;
}

// 从键盘获取密码
char* get_passwd(char* pd,size_t hope_len,bool is_show)
{
    if(NULL == pd) return NULL;

    size_t index = 0;
    while(index < hope_len-1)
    {
        int32_t key_val = get_keyboard();
        if(KEY_BACKSPACE == key_val)
        {
            if(index > 0)
            {
                index--;
                is_show ? pf("\b \b") : nil;
            }
        }
        else if(KEY_ENTER == key_val)
        {
            break;
        }
        else
        {
            pd[index++] = key_val;
            is_show ? pf("*") : nil;
        }
    }

    pd[index] = '\0';

    pf("\n");

    clear_stdin();

    return pd;
}

// 从键盘获取指令
char get_cmd(char begin_cmd,char end_cmd)
{
    if( begin_cmd > end_cmd) return SPILL;

    pf("   请输入指令:");
    while(true)
    {
        char key_val = get_keyboard() ;
        if(key_val >= begin_cmd && key_val <= end_cmd)
        {
            pf("%c\n",key_val);
            return key_val;
        }
    }
}

// 从键盘获取字符串
char* get_str(char* str,size_t hope_len)
{
    if(NULL == str || 0 == hope_len) return NULL;

    size_t index = 0;
    while(index < hope_len-1)
    {
        int8_t key_val = get_keyboard();
        if(KEY_ESC == key_val) return NULL;
        if(KEY_ENTER == key_val) break;
        if(KEY_BACKSPACE == key_val)
        {
            if(index > 0)
            {
                pf("\b \b");
                index--;
            }
            continue;
        }
        pf("%c",key_val);
        str[index++] = key_val;
    }
    
    str[index] = '\0';
    
    pf("\n");

    clear_stdin();

    return str;
}

// 从文件加载数据
int load_data (const char* path,void* ptr,size_t node_size)
{
    if(NULL == path || NULL == ptr) return PRNIL;

    FILE* frp = fopen (path,"r");
    if(NULL == frp) return ERROR;

    size_t cnt = 0,num = 0;
    while ((cnt = fread(ptr+num*node_size,node_size,1,frp))) num += cnt;

    fclose(frp);
    return num;
}

// 保存数据到文件
int save_data (const char* path,const void* ptr,size_t node_size,size_t num)
{
    if(NULL == path || NULL == ptr) return PRNIL;

    FILE* fwp = fopen(path,"w");
    if(NULL == fwp) return ERROR;

    size_t cnt = fwrite(ptr,node_size,num,fwp);

    fclose(fwp);
    return cnt;
}

sams_main.c

#include "sams.h"

int main(void)
{
	// 申请内存加载数据 
	sams_init ();
	
	// 开始运行管理系统
	sams_start ();
	
	// 保存数据释放内存
	sams_exit ();
}

sams.c

#include <malloc.h>
#include "admin.h"
#include "manager.h"
#include "teacher.h"
#include "student.h"
#include "sams.h"
#include "tools.h"
#include "status.h"

uint32_t* id_a;

static int sams_login(const char* id,const char* pd)
{
    Status ret = admin_login(id,pd);
    if(RIGHT == ret) return RIGHT;
    if(PDERR == ret) return IDERR;
    
    ret = mgr_login(id,pd);
    if(IDERR != ret) return ret;
    
    ret = tch_login(id,pd);
    if(IDERR != ret) return ret;

    ret = stu_login(id,pd);
    return ret;
}

// 锁定帐号
static void sams_lock(const char* id_p)
{
    uint32_t id = atoi(id_p);
    for(int i=0; i<mgr_n; i++)
    {
        if(id == mgr_a[i].id)
        {
            pf("---------------\n");
            mgr_a[i].is_stop = true;
            return;
        }
    }
    
    for(int i=0; i<tch_n; i++)
    {
        if(id == tch_a[i].id)
        {
            tch_a[i].is_stop = true;
            return;
        }
    }
    
    for(int i=0; i<stu_n; i++)
    {
        if(id == stu_a[i].id)
        {
            stu_a[i].is_stop = true;
            return;
        }
    }
}


// 申请内存加载数据 
void sams_init(void)
{
    mgr_a = malloc(sizeof(Manager)*MGR_MAX);
    mgr_n = load_data(M_DATA_PATH,mgr_a,sizeof(Manager)); 

    tch_a = malloc(sizeof(Teacher)*TCH_MAX);
    tch_n = load_data(T_DATA_PATH,tch_a,sizeof(Teacher));

    stu_a = malloc(sizeof(Student)*STU_MAX);
    stu_n = load_data(S_DATA_PATH,stu_a,sizeof(Student));
    
    id_a = malloc(sizeof(uint32_t)*3);
    load_data(ID_PATH,id_a,sizeof(uint32_t));
}

// 开始运行管理系统
void sams_start(void)
{
    char id[20] = {};
    char pd[20] = {};
    char prev_id[20] = {};
    size_t login_num = 3;

    while(true)
    {
        clear_src();
        pf("***欢迎使用指针成绩管理系统***\n");
       
        pf("请输入帐号:");
        if(NULL == get_str(id,20)) break;

		pf("请输入密码:");
		get_passwd(pd,20,true);

        login_num--;
        switch(sams_login(id,pd))
        {
            case RIGHT: 
                login_num = 3; break;
            case IDERR: 
                show_msg("*** 帐号或密码错误,请重新登陆! ***",1);
                break;
            case PDERR:
                if(0 == login_num) 
                {
                    sams_lock(id); 
                    login_num = 3;
                    show_msg("*** 此帐号被锁,请联系上级解锁! ***",1);
                    break;
                }
                if(strcmp(id,prev_id))
                {
                    strcpy(prev_id,id);
                    login_num = 2;
                }
                pf("密码错误,你还有%d次机会",login_num);
                show_msg("",1);
        }        
    }
}

// 保存数据释放内存
void sams_exit(void)
{
    pf("\n已退出管理系统\n");
    save_data(M_DATA_PATH,mgr_a,sizeof(Manager),mgr_n);
    free(mgr_a);
    save_data(T_DATA_PATH,tch_a,sizeof(Teacher),tch_n);
    free(tch_a);
    save_data(S_DATA_PATH,stu_a,sizeof(Student),stu_n);
    free(stu_a);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值