C++学生信息和考试成绩管理系统(一)

C++学生信息和考试成绩管理系统

第一章 工程介绍

第二章 用户登陆准备和登陆

第三章 用户的增删查改

第四章 考试创建&成绩的增改

第五章 成绩查询



前言

  理论上,这篇文章会很长,因为代码相对课程设计来讲是有点多,值得注意的是,这个工程有个很严重的BUG——内存泄漏,当然也是自我感觉,为什么呢,因为我写的时候很多时候是从一个函数进入另一个函数,出来的时候就容易忘记了释放,所以如果你只是写个毕设、课设什么的参考下就好了,不要太当真。还有就是因为没用多线程,处理数据杠杠的,慢。一千个学生数据处理大概要5s这样。

  为什么不用智能指针?那就顺带说一下,刚开始我的想法是直接用C来写,嗯,是的没错是用C,但写着写着发现不对劲,好多东西很不方便,比如类对象,我用结构体指针来搞,可搞着搞着越来越麻烦,后来索性换成了类对象或者模板,类似的还有很多,比如std::vector,也比如有时候用char* str有时候是std::string。所以也可以看到绝大多数时候我会保留C的写法,尽可能使用char* str,为什么,因为喜欢。

   C++代码我已经放在Github上,Python代码也在里面(这个代码是用来批量生成数据的),但我觉得写得还不好,有点随意,不过勉强能用,传送门:C-plus-plus-Student-Examination-Manage-System,当然我也可能上传到优快云,这个不确定,因为就像我这种人也很穷,没有C币的,有时候想要下个资源就很麻烦(DdDd)。当然,最简单的,把这文章里所有代码收集起来也会得到近乎完整工程。另外,如果觉得这篇文章合适你就看,不然就是浪费时间。



版权说明:
   C++工程为原创内容,大可使用在毕设、课设等方面,不用标注来源,每个模块可以拆分使用,就当成是自己的代码就行。但转载文章这种,还是标注来源比较好。
   Python工程为原创内容,名字资源来源于网上,具体已经标注,除了资源,其他的如代码这种的用途同上。转载请标明来源,其他用途任意。


一、实验结果/功能

   为啥一上来就是实验结果?因为,万一你想要的功能和我写的不一样那你不就白打开网页了么,所以先比较下,功能适不适合你,适合就下滑,不适合就Ctrl + W

  功能对应三种用户,管理员用户,懂的都懂;标准用户,就当老师账户吧,也不一定,反正是有部分管理权限的;只读用户,就当学生用户吧。其实这些功能可以随意组合,我也没啥需求,所以就靠感觉来写了,相对费时的是管理员功能,因为写的过程中需要封装各种函数,封装完了,另外两个用户也很好写了。

(一)功能


管理员功能

  1. 创建用户
  2. 删除用户
  3. 创建班级
  4. 删除班级
  5. 创建考试
  6. 更改成绩

标准用户功能

  1. 更改学号
  2. 更改班级
  3. 查看成绩
  4. 更改成绩

只读用户功能

  1. 更改用户名
  2. 更改密码
  3. 统计考试情况

(二)结果

管理员界面

管理员用户界面

标准用户界面

标准用户界面

只读用户界面

只读用户界面

如果你觉得看了上面的内容并且觉得很适合,那就继续往下滑。


二、工程环境

系统环境:Windows 10 1909
开发软件:Microsoft Visual Studio Professional 2019 v16.6.0
编译器要求:MSVC且支持C++11
其他:工程用到Windows库,原工程无法跨平台。


三、工程树

  如下图,主函数是入口,主要分为三大类,模板对象类、输入输出类、内容处理类,分别对应Info、IO、Manage,还有一个Template归为模板对象类,共三大类。

  下面具体来说一下这些文件有什么用吧,自上而下。


class_info.h  班级信息类对象,包含行政班级号管理员年级专业班级。(其实没怎么用)


exam_info.h  考试类对象,包含考试日期创建者考生人数考试科目平均分考生成绩记录等。


exam_record.h  考生成绩类对象,包含考生排名考生姓名考生班级考生学号考生均分每科分数


menu.h  用户界面菜单内容,全在这里头了,就是那些你能在屏幕上直接看到的菜单。


student_info.h  学生类对象,包含用户名密码权限学生名学号班级号性别


format_input.h  封装了与输入相关的东西,包括日期输入、选项输入、选择输入、内容输入等。


format_print.h  封装了与输出相关的东西,包括菜单输出、休眠输出、等待输出。


process_file.h  和文件最近距离的封装,封装了一大堆与文件操作相关处理的函数。


manage_admin.h  管理员的界面,负责前端(输出屏幕)和后端(菜单读取、交互处理)内容的交互。


manage_read.h  只读用户的界面,负责前端(输出屏幕)和后端(菜单读取、交互处理)内容的交互。


manage_standard.h  标准用户的界面,负责前端(输出屏幕)和后端(菜单读取、交互处理)内容的交互。


template_free_pointer.h  模板类,销毁任意类型指针、对象(前提如果能销毁的话)。


template_operation_info.h  模板类,封装了标志、字符串地址、数值、容器、对象。传递类对象基本靠它。


main.h  主函数,登陆验证处理,还有一个判断字符串是否为数字类型(不怎么用,其实可以用正则表达式)。


喏,就是这样子,整个过程就是入口读取配置文件,然后再验证用户,调用输入函数将得到的内容拿去遍历文件,匹配后进入用户界面,读取菜单类内容并通过输出菜单函数展示到屏幕,根据输入内容查找或修改内容,最后写回文件,将结果显示在屏幕上并等待用户下一步输入。

代码思路


四、代码讲解

  以登陆管理员用户为例,按操作顺序进行代码说明。因为太多了,放上来太碍眼,如果你自信能看懂的话,也可以跳到最后,直接复制代码。

C++的代码都在后续文章中,这里放的是Python工程,创建适合本工程的伪数据。为什么要大批量创造这些呢,当然是为了方便调试,你总不会想着要把成绩和姓名一个个想好,然后输入进去吧!

(一)主函数:main.py

# -*- coding:utf-8 -*-
# ===============================================
# @Author       HDM
# @Copyright    HDM
# @blogs        https://blog.youkuaiyun.com/qq_43634664
# @Version      0.0.1
# @Time         2021/2/9 14:26
# @FileName     main.py
# @Description  None
# ===============================================

from generate_user_info import generate_user
from generate_exam import generate_exam

K_PATH_FOLDER_DATA = r"C:/Users/THDMI/source/repos/sks853/C-plus-plus-Student-Examination-Manage-System/NoUi_Student_Manage_System/data"

k_PATH_FOLDER_CONFIG = K_PATH_FOLDER_DATA + r"/config"
K_PATH_FOLDER_INFO_ACCOUNT = K_PATH_FOLDER_DATA + r"/info/account"
K_PATH_FOLDER_INFO_CLASS = K_PATH_FOLDER_DATA + r"/info/class"
K_PATH_FOLDER_INFO_RECORD = K_PATH_FOLDER_DATA + r"/record"

K_PATH_FILE_PROPERTIES = k_PATH_FOLDER_CONFIG + r"/init.ini"
K_PATH_FILE_LOG = k_PATH_FOLDER_CONFIG + r"/log.log"

g_ls_path_file_account = []
g_ls_path_file_class = []
g_ls_path_file_record = []


def init_properties():
    with open(K_PATH_FILE_PROPERTIES, "r+", encoding='GB2312') as f:
        ls_properties = []
        flag_properties = 0
        for line in f:
            ls = line.split()
            for ele in ls:
                ls_properties.append(ele.replace(r"./data", K_PATH_FOLDER_DATA))
        for ele in ls_properties:
            if "[account]" == ele:
                flag_properties = 1
                continue
            if "[class]" == ele:
                flag_properties = 2
                continue
            if "[record]" == ele:
                flag_properties = 3
                continue
            if 1 == flag_properties:
                g_ls_path_file_account.append(ele)
            elif 2 == flag_properties:
                g_ls_path_file_class.append(ele)
            elif 3 == flag_properties:
                g_ls_path_file_record.append(ele)


def append_account():
    global g_ls_path_file_account
    global g_ls_path_file_class
    global g_ls_path_file_record
    for index in range(len(g_ls_path_file_account)):
        g_ls_path_file_account[index] = g_ls_path_file_account[index].replace(K_PATH_FOLDER_DATA, r"./data")
    for index in range(len(g_ls_path_file_class)):
        g_ls_path_file_class[index] = g_ls_path_file_class[index].replace(K_PATH_FOLDER_DATA, r"./data")
    for index in range(len(g_ls_path_file_record)):
        g_ls_path_file_record[index] = g_ls_path_file_record[index].replace(K_PATH_FOLDER_DATA, r"./data")

    with open(K_PATH_FILE_PROPERTIES, "w+", encoding="gb2312", newline='') as f:
        f.write("[account]\n")
        for ele_account in g_ls_path_file_account:
            f.write(ele_account + "\n")
        f.write("[class]\n")
        for ele_class in g_ls_path_file_class:
            f.write(ele_class + "\n")
        f.write("[record]\n")
        for ele_record in g_ls_path_file_record:
            f.write(ele_record + "\n")


if __name__ == '__main__':
    """ main """
    init_properties()
    user_info = generate_user(K_PATH_FOLDER_INFO_ACCOUNT + r"/account_1.csv")
    exam = generate_exam(K_PATH_FOLDER_INFO_RECORD, user_info.generate_account())
    exam.store_exam()
    for element in exam.path:
        g_ls_path_file_record.append(element)
    append_account()

(二)根据性别批量生成姓名:generate_chinese_names.py

# -*- coding:utf-8 -*-
# ===============================================
# @Author       HDM
# @Copyright    HDM
# @blogs        https://blog.youkuaiyun.com/qq_43634664
# @Version      0.0.1
# @Time         2021/2/9 12:47
# @FileName     generate_chinese_names.py
# @Description  资源参考博客:https://www.jianshu.com/p/94be1c4ebf82 和 https://www.jianshu.com/p/d23e3ac18481
# ===============================================

import random

name = "陈,林,黄,张,李,王,吴,刘,蔡,杨,许,郑,谢,洪,郭,邱,曾,廖,赖,徐,周,叶,苏,庄,吕,江,何,萧,罗,高,周,叶,苏,庄,吕,江,何,萧,罗," \
       "高,潘,简,朱,彭,游,詹,胡,施,沈,余,卢,梁,赵,颜,柯,翁,魏,孙,戴,范,方,宋,邓,杜,傅,侯,曹,薛,丁,卓,马,阮,董,唐,温,蓝,蒋," \
       "石,古,纪,姚,连,冯,欧,程,汤,田,康,姜,汪,白,邹,尤,巫,钟,黎,涂,龚,严,韩,袁,金,童,陆,夏,柳,邵,"

male = "辰,士,以,建,家,致,树,炎,德,行,时,泰,盛,雄,琛,钧,冠,策,铭,腾,伟,刚,勇,毅,俊,峰,强,军,平,保,东,文,辉,力,明,永,健,世,广," \
       "志,义,兴,良,海,山,仁,波,宁,贵,福,生,龙,元,全,国,胜,学,祥,才,发,成,康,星,光,天,达,安,岩,中,茂,武,新,利,清,飞,彬,富,顺," \
       "信,子,杰,楠,榕,风,航,弘,鼎"

female = "嘉,琼,桂,娣,叶,璧,璐,娅,琦,晶,妍,茜,秋,珊,莎,锦,黛,青,倩,婷,姣,婉,娴,瑾,颖,露,瑶,怡,婵,雁,蓓,纨,仪,荷,丹,蓉,眉,君," \
         "琴,蕊,薇,菁,梦,岚,苑,婕,馨,瑗,琰,韵,融,园,艺,咏,卿,聪,澜,纯,毓,悦,昭,冰,爽,琬,茗,羽,希,宁,欣,飘,育,滢,馥,筠,柔,竹," \
         "霭,凝,晓,欢,霄,枫,芸,菲,寒,伊,亚,宜,可,姬,舒,影,荔,枝,思,丽,秀,娟,英,华,慧,巧,美,娜,静,淑,惠,珠,翠,雅,芝,玉,萍,红," \
         "娥,玲,芬,芳,燕,彩,春,菊,勤,珍,贞,莉,兰,凤,洁,梅,琳,素,云,莲,真,环,雪,荣,爱,妹,霞,香,月,莺,媛,艳,瑞,凡,佳"

ls_name_last = [
    '赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨', '朱', '秦', '尤', '许',
    '何', '吕', '施', '张', '孔', '曹', '严', '华', '金', '魏', '陶', '姜', '戚', '谢', '邹', '喻', '柏', '水', '窦', '章',
    '云', '苏', '潘', '葛', '奚', '范', '彭', '郎', '鲁', '韦', '昌', '马', '苗', '凤', '花', '方', '俞', '任', '袁', '柳',
    '酆', '鲍', '史', '唐', '费', '廉', '岑', '薛', '雷', '贺', '倪', '汤', '滕', '殷', '罗', '毕', '郝', '邬', '安', '常',
    '乐', '于', '时', '傅', '皮', '卞', '齐', '康', '伍', '余', '元', '卜', '顾', '孟', '平', '黄', '和', '穆', '萧', '尹',
    '姚', '邵', '堪', '汪', '祁', '毛', '禹', '狄', '米', '贝', '明', '臧', '计', '伏', '成', '戴', '谈', '宋', '茅', '庞',
    '熊', '纪', '舒', '屈', '项', '祝', '董', '梁'
]
ls_name_first_male = male.split(',')
ls_name_first_female = female.split(',')


def generate_name(gender):
    name_length = random.choice((2, 3))
    if gender == 0:
        if name_length == 2:
            return random.choice(ls_name_last) + random.choice(ls_name_first_female)
        if name_length == 3:
            return random.choice(ls_name_last) + random.choice(ls_name_first_female) + \
                   random.choice(ls_name_first_female)
    if gender == 1:
        if name_length == 2:
            return random.choice(ls_name_last) + random.choice(ls_name_first_male)
        if name_length == 3:
            return random.choice(ls_name_last) + random.choice(ls_name_first_male) + \
                   random.choice(ls_name_first_male)

    return None

(三)批量生成ID相关信息:generate_id.py

# -*- coding:utf-8 -*-
# ===============================================
# @Author       HDM
# @Copyright    HDM
# @blogs        https://blog.youkuaiyun.com/qq_43634664
# @Version      0.0.1
# @Time         2021/2/9 14:03
# @FileName     generate_id.py
# @Description  None
# ===============================================

import string
import random


def generate_uuid(length):
    uuid = ""
    for i in range(length):
        uuid += random.choice(string.ascii_letters + string.digits)
    return uuid


def generate_class_id(length):
    class_id = ""
    for i in range(length):
        class_id += random.choice(string.digits)
    return class_id


def generate_student_id(class_id):
    student_id = ""

    student_id += str(random.randint(2018, 2024))

    academy = random.randint(1, 12)
    if academy < 10:
        student_id += '0' + str(academy)
    else:
        student_id += str(academy)

    major = random.randint(1, 125)
    if major < 10:
        student_id += '00' + str(major)
    elif major < 100:
        student_id += '0' + str(major)
    else:
        student_id += str(major)

    student_id += class_id[-2:]

    last_id = random.randint(1, 75)
    if last_id < 10:
        student_id += '0' + str(last_id)
    else:
        student_id += str(last_id)

    return student_id

(四)批量生成用户信息:generate_user_info.py

# -*- coding:utf-8 -*-
# ===============================================
# @Author       HDM
# @Copyright    HDM
# @blogs        https://blog.youkuaiyun.com/qq_43634664
# @Version      0.0.1
# @Time         2021/2/9 14:26
# @FileName     generate_user_info.py
# @Description  None
# ===============================================

import csv
import random

from generate_chinese_names import generate_name
from generate_id import generate_uuid
from generate_id import generate_student_id
from generate_id import generate_class_id


class generate_user:
    def __init__(self, path):
        self.path = path

    def generate_account(self):
        ls = []
        tmp_ls = []
        for i in range(1000):
            user_name = generate_uuid(4)
            user_password = generate_uuid(6)
            privilege = random.choice(('1', '2'))
            student_gender = random.choice(('0', '1'))
            student_name = generate_name(gender=eval(student_gender))
            student_class = generate_class_id(6)
            student_id = generate_student_id(student_class)
            tmp_ls.append(
                (user_name, user_password, privilege, student_name, student_id, student_class, student_gender))
        tmp_ls_name = []
        tmp_ls_id = []
        count = 0
        for ele in tmp_ls:
            if not ele[0] in tmp_ls_name and not ele[4] in tmp_ls_id:
                count += 1
                ls.append(ele)
                tmp_ls_name.append(ele[0])
                tmp_ls_id.append(ele[4])
        ls = sorted(ls, key=lambda x: x[4])

        for i in ls:
            print(i)
        print("成功生成数据个数:", count)

        try:
            with open(self.path, "w", encoding='GB2312', newline='') as f:
                writer = csv.writer(f, delimiter=",")
                for i in ls:
                    writer.writerow(i)
        except Exception as e:
            print(e)

        return ls

(五)批量生成考试记录:generate_exam.py

# -*- coding:utf-8 -*-
# ===============================================
# @Author       HDM
# @Copyright    HDM
# @blogs        https://blog.youkuaiyun.com/qq_43634664
# @Version      0.0.1
# @Time         2021/2/9 15:41
# @FileName     generate_exam.py
# @Description  None
# ===============================================

import csv
import string
import random



AMOUNT_EXAM = 20


class generate_exam:
    def __init__(self, folder_path, student_info):
        self.folder_path = folder_path
        self.student_info = student_info
        self.datetime = ""
        self.admin = "root"
        self.count_student = len(student_info)
        self.count_major = random.randint(2, 10)
        self.average = 0.0
        self.major = []
        self.major_score = []
        self.ls_record = []
        self.path = []

    def store_exam(self):
        for index in range(AMOUNT_EXAM):
            self.create_exam()
            file_path = self.folder_path + r"/exam_" + str(index) + r".csv"
            base = (self.datetime, self.admin, self.count_student, self.average, self.count_major)
            ls = [base, self.major, self.major_score]
            for ele in self.ls_record:
                ls.append(ele)
            with open(file_path, "w", encoding="gb2312", newline='') as f:
                writer = csv.writer(f, delimiter=",")
                for i in ls:
                    writer.writerow(i)
            self.path.append(file_path)
            self.clean_exam()

    def clean_exam(self):
        self.datetime = ""
        self.count_major = random.randint(2, 10)
        self.average = 0.0
        self.major.clear()
        self.major_score.clear()
        self.ls_record.clear()

    def create_exam(self):
        self.create_exam_datetime()
        self.create_exam_major_serial_num()
        self.create_exam_student_record()
        self.statistics_exam()

    def print_exam(self):
        base = [self.datetime, self.admin, self.count_student, self.average, self.count_major]
        print(base)
        print(self.major)
        print(self.major_score)
        for ele in self.ls_record:
            print(ele)

    def statistics_exam(self):
        self.average = round(self.average / self.count_student, 1)
        for index in range(self.count_major):
            self.major_score[index] = round(self.major_score[index] / self.count_student, 1)

    def create_exam_student_record(self):
        for i in range(self.count_student):
            rank = 0
            student_name = self.student_info[i][3]
            student_class = self.student_info[i][5]
            student_id = self.student_info[i][4]
            student_score_major = []
            for index in range(self.count_major):
                major_score = round(random.uniform(45, 95), 1)
                student_score_major.append(major_score)
                if 0 == i:
                    self.major_score.append(major_score)
                else:
                    self.major_score[index] += major_score
            student_score_average = round(sum(student_score_major) / self.count_major, 1)
            self.average += student_score_average
            student = [rank, student_name, student_class, student_id, student_score_average]
            for element in student_score_major:
                student.append(element)
            self.ls_record.append(student)
        self.ls_record = sorted(self.ls_record, key=lambda x: x[4], reverse=True)
        for index in range(self.count_student):
            self.ls_record[index][0] = index + 1

    def create_exam_major_serial_num(self):
        for i in range(self.count_major):
            major = ""
            for index in range(5):
                major += random.choice(string.ascii_letters + string.digits)
            self.major.append(major)

    def create_exam_datetime(self):
        datetime = ""
        datetime += str(random.randint(2018, 2024))
        month = random.randint(1, 12)
        if month < 10:
            datetime += '0' + str(month)
        else:
            datetime += str(month)
        day = random.randint(1, 31)
        if month < 10:
            datetime += "0" + str(day)
        else:
            datetime += str(day)
        hour = random.randint(1, 23)
        if hour < 10:
            datetime += "0" + str(hour)
        else:
            datetime += str(hour)
        minute = random.randint(1, 59)
        if minute < 10:
            datetime += "0" + str(minute)
        else:
            datetime += str(minute)
        self.datetime = datetime

(六)生成结果

生成数据

这些代码有点懒得说了,懂的都懂,用途就是创造适合本工程的大批数据,不多,也就1000个学生、20个考试记录。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值