zoukankan      html  css  js  c++  java
  • 课程管理系统设计(windows系统)

    1. 介绍

    本项目使用 C++ 实现一个课程管理系统,这个项目会学习C++的很多特性,同时可以熟悉Linux下的C++语言编译方法及简单的Makefile编写(以后会完善)。

    2. 项目需求

    编写一个课程管理程序,程序具备下述基本功能:

    1. 程序运行后可以循环输入操作命令
    2. 操作命令输入0,打印出程序帮助信息,即每个操作命令的作用
    3. 操作命令输入1,打印出程序中存储的所有课程ID和课程名
    4. 输入2,打印出课程数量
    5. 输入3,打印出名字最长的课程信息,如果有多个相同长度的课程名请都打印出
    6. 输入4,删除最后一个课程,如果没有课程需要返回错误信息
    7. 输入5,退出程序

    在上述基本功能之外的附加功能:

    1. 课程包含基础课,项目课,评估课不同的类型
    2. 课程ID唯一,需要自动生成

    需求很简单,我们完全不需要复杂的面向对象也可以实现,但为了尽可能多的应用C++的知识点,会进行“过度设计”,目的是让大家尽可能多的了解C++的知识如何应用到实际的代码场景中。

    一、针对这个项目,我们首先需要知道我们要做什么,要达到什么样的效果。根据项目要求,我们要做的就是输出一系列帮助信息,每一条帮助信息对应一个功能,对于每个功能,我们需要编写函数实现。项目要求:默认输出全部帮助信息,根据帮助信息中显示的命令行,输入相应的命令后,根据命令判断以及相应的函数处理,然后输出对应的操作。这个项目的重点是实现基础课的相关操作,为了能够体现项目的可扩展性和锻炼C++编程的技能,又定义了扩展接口,即项目课和评估课等不同的类型(即为基础课的派生类)。同时由于要求课程id是唯一的,需要将课程id定义为static变量,并在类的外部初始化。

    二、根据项目功能要求,可以进行模块划分,分成两个模块:命令输入及处理和课程存储及管理。既而得出类的划分,分为课程类、课程管理类和命令管理类。课程对象存储每个课程的信息,课程管理对象对课程列表进行维护和管理,命令管理对象对命令进行管理。具体来说:

    1、课程类:类成员需要包括课程Id和课程名称,类成员函数至少包括构造函数(参数为课程名称)、拷贝构造函数、返回和设置课程名称、获得课程id和打印课程信息函数(需要重载operator<<)等。

    2、课程管理类:类成员至少包含课程列表,类成员函数至少包括构造函数(参数为课程对象vector容器)、获取课程数目、添加课程(参数为课程名称或课程对象)、删除课程(删除最新课程、指定id或指定名称)、打印课程列表、打印课程(最长名称、指定id或指定名称)等。

    3、命令管理类:类成员至少需要命令列表和课程管理对象,类成员函数至少包括初始化函数(课程及命令信息初始化)、打印帮助信息和命令处理函数。 现在根据现有的类的划分,每个类都有.cpp和.h,然后在定义一个Cmd.h,其中定义所有支持的命令数字,还需要主函数main.cpp和Makefile文件。说到这里,这个项目的整体架构已经成形,接下来就是如何实现。 这里附上每个类.cpp的具体实现,一句一句敲上的,记录一下。

     1 //------------------------------Course.cpp-------------------------------------
     2 #include<iostream>
     3 #include"Course.h"
     4 using namespace std;
     5 // Course 类成员函数
     6 //初始化静态成员,默认第一个课程Id为1
     7 int Course::currentId = 1;
     8 //课程类构造函数
     9 Course::Course()
    10 {
    11     //将currentId当前值赋值给id,再将currentId自增
    12     id = currentId++;
    13     //默认课程名称为空字符串
    14     name = "";
    15 }
    16 //课程类拷贝构造函数
    17 Course::Course(const Course& course)
    18 {
    19     id = course.GetId();
    20     name = course.GetName();
    21 }
    22 //打印课程信息
    23 void Course::PrintInfo() const{
    24     cout<<"Course: "<< id <<" : "<< name << endl;
    25 }
    26 //友元函数:读取输入创建新的课程
    27 void read(istream& is, Course& item){
    28     is >> item.name;
    29 }
    30 //友元函数:操作符<<重载函数,当cout<<输出课程信息时使用
    31 ostream& operator<<(ostream& os, const Course& course)
    32 {
    33     os << "Course: "<< course.id <<" : " << course.name;
    34     return os;
    35 }
    36 //ProjectCourse 类成员函数
    37 //打印课程信息
    38 void ProjectCourse::PrintInfo() const{
    39     cout<<"ProjectCourse: "<< id <<" : "<<name<<" : "<<tag<< endl;
    40 }
    41 //JudgeCourse 类成员函数
    42 //打印课程信息
    43 void JudgeCourse::PrintInfo() const{
    44     cout<<"JudgeCourse: "<< id <<" : "<<name<<" : "<<time<<endl;
    45 }
      1 //---------------------------------------CourseManager.cpp--------------------------
      2 #include<stdexcept>
      3 #include<iostream>
      4 #include "CourseManager.h"
      5 
      6 using namespace std;
      7 
      8 //构造函数,参数为课程vector
      9 CourseManager::CourseManager(const vector<Course>& course){
     10     for(auto curs = course.begin();curs!=course.end();curs++)
     11         courseList.push_back(*curs);
     12 }
     13 //添加课程函数(参数为课程名称)
     14 void CourseManager::AddCourse(const string& courseName){
     15     Course course(courseName);
     16     courseList.push_back(course);
     17 }
     18 //添加课程函数(参数为课程对象)
     19 void CourseManager::AddCourse(const Course& course){
     20     courseList.push_back(course);
     21 }
     22 
     23 //删除最后一个课程
     24 void CourseManager::RemoveLast(){
     25     try
     26     {
     27         //如果课程非空,则删除最后一门课程
     28         if(!courseList.empty()){
     29             courseList.pop_back();
     30             cout<<"Deleted successfully!"<<endl;
     31         }
     32         //如果课程为空,则抛出异常被catch捕获
     33         else{
     34             throw runtime_error("Deleted error, there is no course!");
     35         }
     36     }
     37     catch(runtime_error err){
     38         cout<<err.what()<<endl;
     39     }
     40 }
     41 //删除课程:删除指定id的课程
     42 void CourseManager::RemoveById(int id){
     43     int index = FindCourse(id);
     44     if(index>0)
     45         courseList.erase(courseList.begin()+index);
     46     else
     47         cout<<"NOT FOUND"<<endl;
     48 }
     49 //删除课程:删除指定名称的课程
     50 void CourseManager::RemoveByName(const string& name){
     51     int index = FindCourse(name);
     52     if(index>0)
     53         courseList.erase(courseList.begin()+index);
     54     else
     55         cout<<"NOT FOUND"<<endl;
     56 }
     57 //打印课程列表
     58 void CourseManager::PrintAllCourse(){
     59     cout<<"CourseList: "<<endl;
     60     //遍历courseList,打印出所有course信息
     61     for(auto curs = courseList.begin();curs!=courseList.end();curs++)
     62         cout<<*curs<<endl;
     63 }
     64 //打印指定课程(指定id)
     65 void CourseManager::PrintCourse(int id){
     66     int index = FindCourse(id);
     67     if(index > 0)
     68         cout<<courseList[index]<<endl;
     69     else
     70         cout<<"NOT FOUND"<<endl;
     71 }
     72 //打印指定课程(指定名称)
     73 void CourseManager::PrintCourse(const string& name){
     74     int index = FindCourse(name);
     75     if(index>0)
     76         cout<<courseList[index]<<endl;
     77     else
     78         cout<<"NOT FOUND"<<endl;
     79 }
     80 //打印最长名称课程函数
     81 void CourseManager::PrintLongName(){
     82     int maxLen = 0;
     83     //遍历courseList,查找最长名称
     84     for(auto curs = courseList.begin();curs!=courseList.end();curs++){
     85         int currentLen = curs->GetName().size();
     86         if(currentLen>maxLen)
     87             maxLen = currentLen;
     88     }
     89     //遍历courseList,打印最长名称课程
     90     for(auto curs = courseList.begin();curs!=courseList.end();curs++){
     91         if(curs->GetName().size()==maxLen)
     92             cout<<*curs<<endl;
     93     }
     94 }
     95 //根据id查找课程,返回课程在vector的索引
     96 int CourseManager::FindCourse(int id){
     97     for(int i=0;i<courseList.size();i++){
     98         if(courseList[i].GetId()==id)
     99             return i;
    100     }
    101     return -1;
    102 }
    103 //根据名称查找课程,返回课程在vector的索引
    104 int CourseManager::FindCourse(const string& name){
    105     for(int i=0;i<courseList.size();i++){
    106         if(courseList[i].GetName()==name)
    107             return i;
    108     }
    109     return -1;
    110 }
     1 //------------------------------------CmdManager.cpp-----------------------------
     2 #include<iostream>
     3 #include "CmdManager.h"
     4 
     5 using namespace std;
     6 
     7 //初始化函数
     8 void CmdManager::Init(){
     9     //初始化课程列表
    10     manager.AddCourse("Linux");
    11     manager.AddCourse("NodeJS");
    12     manager.AddCourse("C++");
    13     manager.AddCourse("Python");
    14     manager.AddCourse("Spark");
    15     manager.AddCourse("Hadoop");
    16     manager.AddCourse("Ruby");
    17     manager.AddCourse("Java");
    18     //初始化命令列表
    19     cmdMap.insert(pair<CourseCmd,string>(Cmd_PrintHelp,"Help Info"));
    20     cmdMap.insert(pair<CourseCmd,string>(Cmd_PrintCourse,"Course List"));
    21     cmdMap.insert(pair<CourseCmd,string>(Cmd_PrintCourseNum,"Course Number"));
    22     cmdMap.insert(pair<CourseCmd,string>(Cmd_PrintLongName,"Longest Course Name"));
    23     cmdMap.insert(pair<CourseCmd,string>(Cmd_RemoveLastCourse,"Remove Last Course"));
    24     cmdMap.insert(pair<CourseCmd,string>(Cmd_exit,"Exit"));
    25 }
    26 //打印帮助信息
    27 void CmdManager::PrintAllHelp() const{
    28     cout<<"Cmd List: "<<endl;
    29     for(auto iter = cmdMap.begin();iter!=cmdMap.end();iter++)
    30         cout<<iter->first<<":"<<iter->second<<endl;
    31 }
    32 //根据命令查询帮助信息
    33 void CmdManager::PrintCmdHelp(const CourseCmd cmd) const{
    34     auto iter = cmdMap.find(cmd);
    35     if(iter != cmdMap.end())
    36         cout<<iter->first<<":"<<iter->second<<endl;
    37     else
    38         cout<<"NOT FOUND"<<endl;
    39 }
    40 //处理命令操作,如果返回false则表示退出程序,其他情况返回true
    41 bool CmdManager::HandleCmd(const CourseCmd cmd){
    42     auto iter = cmdMap.find(cmd);
    43     if(iter == cmdMap.end()){
    44         cout<<"NOT FOUND"<<endl;
    45         return true;
    46     }
    47     switch(cmd){
    48         case Cmd_PrintHelp: PrintAllHelp();break;
    49         case Cmd_PrintCourse: manager.PrintAllCourse();break;
    50         case Cmd_PrintCourseNum: cout<<manager.GetCourseNum()<<endl;break;
    51         case Cmd_PrintLongName: manager.PrintLongName();break;
    52         case Cmd_RemoveLastCourse: manager.RemoveLast();break;
    53         case Cmd_exit:return false;
    54         default: return true;
    55     }
    56     return true;
    57 }
     1 //-----------------------------------------main.cpp---------------------------------
     2 #include "CmdManager.h"
     3 using namespace std;
     4 
     5 int main()
     6 {
     7     //输入的命令
     8     int cmd;
     9     //创建命令管理对象
    10     CmdManager cmdManager;
    11     cmdManager.Init();
    12     //打印帮助信息
    13     cmdManager.PrintAllHelp();
    14     cout<<"New Command: ";
    15     //进入主循环并处理输入信息
    16     while(cin>>cmd){
    17         if(cin.good()){
    18             bool exitCode = cmdManager.HandleCmd((CourseCmd)cmd);
    19             if(!exitCode)
    20                 return 0;
    21         }
    22         cout<<"---------------------------------"<<endl;
    23         cout<<"New Command: ";
    24 
    25         //清理输入流,避免刚才流中的字符影响后续输入
    26         cin.clear();
    27         cin.ignore();
    28     }
    29     return 0;
    30 }

    这里需要说明几点:

    (1)在CourseManager类中需要存储课程列表,即包含一个Course容器,这里使用的vector容器,因为我们需要根据id和名称查找课程,并且需要删除最后的课程操作,顺序容器是最好的选择。

    (2)在CmdManager类中包含课程管理对象和命令行列表,在这里优先选择关联容器map,因为map中存储的对象既是key又是value,并且不允许有重复的key,map存储的对象是必须具有可排序性的,默认采用less排序行为。这里使用map既要存储命令值又要存储相应的提示信息。

    转载请注明出处: C++博客园:godfrey_88 http://www.cnblogs.com/gaobaoru-articles/
  • 相关阅读:
    MYSQL视图的学习笔记
    MYSQL常用操作函数的封装
    table表格边框样式
    用于防SQL注入的几个函数
    Html中版权符号的字体选择问题(如何让版权符号更美观)
    拿出“请勿打扰”的态度来
    editplus批量删除html代码空行
    解决&nbsp在IE与firefox宽度不一致的问题
    解决IE6下DIV无法实现1px高度问题
    处理落后员工
  • 原文地址:https://www.cnblogs.com/gaobaoru-articles/p/5273983.html
Copyright © 2011-2022 走看看