02_简易评分系统(DOS界面)(小钱版)[2011-08-01]

 

 引言

(一)程序名称

简易评分系统V1.0(DOS界面)(小钱版)

 

(二)开发环境

电脑型号:        惠普 HP Pavilion g4 Notebook PC 笔记本电脑

操作系统:        Microsoft Windows 7 旗舰版 (6.1.7601 Service Pack 1)

处理器:            英特尔 Core i3 M 390 @ 2.67GHz 双核笔记本处理器

主板:                惠普 1667 (英特尔 HM55 芯片组)

内存:                4 GB ( 尔必达 DDR3 1333MHz / 金士顿 DDR3 1333MHz )

主硬盘:            希捷 ST9640320AS ( 640 GB / 5400 转/分 )

显卡:                ATI Radeon HD 6470M  ( 1 GB / 惠普 )

编译调试软件:Microsoft Visual Studio 2005

 

(三)主要功能

1. 整个系统菜单选项中可以返回界面,注销,退出系统三个功能

2. 在登陆界面中有账号登陆管理(参赛者、评委、管理员);

3. 在查询界面中参赛者可以查询成绩;

4. 在评分界面中评委可以给各参赛者评分,全部评分工作结束后,系统将自动评分各参赛者的各科平均分,总平均分,总分,名次;可以按以下三种方式查询全部学生的成绩;

① 按全部参赛者显示;

② 按平均分范围显示;

③ 按名次范围显示。

     5. 在管理界面中管理员,可以实现以下三种功能

① 保存:参赛者分数;

② 查询:按全部参赛者显示,按平均分范围显示,按名次范围显示;

③ 用户管理:查询、添加、删除参赛者、评委及管理员用户;

④ 评分项目管理:查询、添加、删除评分项目。

   6. 未开发功能:成绩排序显示,程序退出自动保存,进入程序自动读取等。

(四)程序说明

1. 运行环境

Windows NT / 2000 / XP / VISTA / 7

 

2. 文件说明

① 程序运行文件: 01_可直接执行exe_简易评分系统V1.0(DOS界面)(小钱版).exe② 程序说明书:  02_说明书_简易评分系统DOS版V1.0(小钱版)说明书.pdf

③ 源程序文件夹: 03_项目文件_简易评分系统V1.0(DOS界面)(小钱版)

④  程序制作相关:  04_项目相关_简易评分系统V1.0(DOS界面)(小钱版)

 

3. 参考资料

① 《C++ Primer Plus(第五版)》 Stephen Prata著 孙建春、韦强译

② 《C++ Primer(中文版)(第四版)》 Stanley B.Lippman Josee Lajoie 著

③     《数据结构与算法分析(C++描述版)(第二版)》 Clifford A.Shaffer 著 张铭等译

 

☞  程序结构

#include <iostream>       // 包括cin, cout等函数

#include <string>            // 包括append() 等函数

#include <vector>     // 包括push_back() 等函数

#include <fstream>         // files output

#include <cstdlib>          // system("cls")

#include <cstddef>         // size_t

#include <conio.h>         // _getch()

#include "users.h"           // 用户类

#include "subject.h"        // 评分项目类

#include "player.h"          // 参赛者类

#include "Syndic.h"        // 评委类

#include "admins.h"        // 管理员类


☞  程序流程图



☞  程序源程序模块设计说明

(一)模块1:用户类

※  数据成员:

Users类中包含了字符串型的① UsersName,② UsersPassword和整型的 ③ UsersType三个容器,分别存储用户名,密码和用户类型,设定为向量类的原因是打算发挥向量可以任意调节类中数量的优点(它相当于一个链表,可以任意调节长度)。在用户类型的设计中,设定1为参赛者,2为评委,3为管理员以区分开不同的用户类型,在这三个向量中,它们每一个用户名的位置的相关资料都会一一对应,如当UsersName[6]的时候,它相对应的密码是UsersPassword[6]。

users类中还包含用于记录用户数目的 ④ UsersNumber和用于定位的 ⑤ PositionUsers,这里我所定义的定位,是指能在这个users类中知道UsersName的位置如:PositionUsers = 1时,UsersName[1],UsersPassword[1],UsersType[1]。这样做的话可以达到之前提到的“一一对应”要求,让实现各功能时写法更加简便。

※  成员函数:

①   bool users::GetTwoNumbers(int &pln, int &ggn)     // 用于获取参赛者及评委数目

{……

size_t = UsersType.size();

    for (i = 0; i < t; i++)

    {

        if (1 == UsersType[i])

        {

             ++pln;

        }

    }

……}

简单地使用了for嵌套if语句,判断当用户类型中的值是1时,则实现参赛者数目的递增。类中GetOneNumbers(int & adn)等函数用的是同样的原理,这里就不作解释了。

  

bool users::DelUsers(const std::string& du)                      // 删除用户

{……

switch (m)

    {

        case 1:  { j--;   break; }

        case 2:  { k--;   break; }

        case 3:  { i--;   break; }

        default: break;

    }

    if(0 == i || 0 == j || 0 == k)

    {

        cout << "\n\n 对不起,不能删除仅剩一个用户的用户组。";

        return false;

    }

删除操作中,定义i, j, k三个变量和GetType(m),switch (m)主要是用以判断同组用户名是否仅剩一个,分别用i, j, k获取三个类型的数目,再用switch选择它是哪一种类型,对其类型数量减1,从而可以用if语句判断出结果。

 

...... bool l = FindName(du);......

if(l)

{......

        UsersName.erase(UsersName.begin() + PositionUsers);

        UsersPassword.erase(UsersPassword.begin() + PositionUsers);

        UsersType.erase(UsersType.begin() + PositionUsers);

        UsersNumber--;

......}

删除操作中,还将FindName()结合使用,先用FindName()函数看是否能找出用户名,然后再对其进行删除,删除的时候需要注意的一点是用户数目需要减1。

 

② void users::PrintAll()                                                   // 打印全部用户

{......

cout << "\n\n-----  参赛者  -----\n\n";

    int i;

    for(i = 0; i < UsersNumber; i++)

    {

        if (1 == UsersType[i])

        {

             cout << UsersName[i] << endl;

        }

    }

......

}

通过建立局部变量i,判断出用户类型,再分出类型打印到屏幕上,使其更美观。

 

③ void CopyNewUsers(vector<player>& p, vector<Syndic>& s, subject &ss)

这是在使用管理员权限时运用的一个功能,当执行添加和删除科目时,都将原来的用户向量清空,重建向量,以防对以后的评分工作造成影响(该程序并没有实现总分能随科目的数目改变而改变的功能)。

{......

   p.clear();                                // 先清空了原容器

   player *pl;                                    // 使用new不断地新建变量存放

   std::vector<subject> ts(UsersNumber);

   for (i = 0; i < UsersNumber; ++i)

   {

        ts[i].getSubject (&ss);

        if (1 == UsersType[i])

        {

            pl = new player(UsersName[i], ts[i]);

            p.push_back(*pl);

            delete pl;

        }

        ......

   }

   return;

}

由于不能在for语句中新建自动存储变量,于是,想到了使用new在for中建临时建立变量,放在自由存储区域中,然后再将其数据保存到p向量中。

 

(二) 模块2:项目类

※  继承类:

   subject类中新定义了一个继承类:node,由于subject类的设计是单链表,所以就新建了一个结点类,它主要是用于存放每一项目的信息,包括单个科目的名称以及该科目的分数,这个科目的分数可以是参赛者的,也可以是评委的,主要实现是看如何调用,node类中,还包含了一个node* next,用于指向下一指针。 node的构造函数可以给它输入科目名称以及下一结点的地址。

※  数据成员:

subject类中包含了① int num用于记录参赛者的数目,以达到可以当评委将num个分数放进score里面的目的,然后 ② node * fence,③ node * tail,④ node * head,分别是阑珊,尾结点,头指针用于实现一些链表的简单添删功能,⑤int subnum用于记录科目数目,即链表长度,集合了这些数据成员,基本上subject类要满足的功能就能实现了。

※  成员函数:

①   bool subject::AppendSubject(const std::string & newname)   // 在尾部追加元素

{

   if (0 == subnum)

   {

       head = fence = tail = new node(newname, NULL);

   }

   else

   {

       tail -> next = new node( newname, NULL);

   }

if (tail -> next == NULL) return false; // 创建失败,没空间

......}

之前考虑到如果subject为空的情况下,那就重新创建头指针放入数据,此处还是运用new,创建链表的结点,并将数据通过构造函数放入。

 

②   bool subject::DelSubject(const std::string & oldname) // 删除fence指针的函数

{

     if(Find(oldname))

   {

       if (fence == head)                   // 假如仅是头结点

       {

            if (tail == fence)               // 假如即是头结点,又是尾结点

            {......}

            else

            {......}

    }

       node * t = fence;                    // 假如在中间或尾结点

       for (fence = head; fence -> next != t; fence = fence -> next){}

       if (t == tail)                            // 假如是尾结点       

       {......}

       else                                 // 是在中间

       {......}

   ......}

在删除指针结点的时候,这里面要考虑的情况比较多,先找到了要删除的项目,得出它的结点位置,假如它是头结点,就可以让这个结点指向下一科目,假如它即是头,又是尾,即,可以清空了这个链表了,假如它是在中间的话,还要考虑它是不是尾结点,如果是在中间或者尾结点的话,由于不是双链表,就要遍历一次链表,找出它前结点的位置,指这个前结点指向下下一个结点,从而达到删除的目的。

 

③ bool subject::EnterSubject()                 // 给全部科目评(N个学生或学生)分

{.....

   for ( fence = head, j = 1; fence != NULL; fence = fence -> next, ++j)

   {......

       for (i = 0; i < num; i++)                 // 给num个参赛者评同一项目的分数

     {

            cout << "\n    请评出第 " << i+1 << " 位参赛者的成绩: ";

            ......

            (fence -> score).push_back(t);

            ......}

   在评分的时候,评委要考虑到的是项目数,参赛者数,那么,可以用n的二次方,for循环,这里采用的是以同一项目为先,让评委打分,一个项目中评多个参赛者,评完以后使用.push_back()将其放入vector。

 

④ bool subject::PrintSubject()   // 打印全部科目名称                               

{

   using std::cout;

   if (head == NULL) return false;

   int i;

   for (fence = head, i = 1; fence != NULL; fence = fence -> next, ++i)

   {

       cout << ' ' <<  i << " : "  << (fence -> SubjectName).c_str() << '\n';

   }

   cout << "\n ------- 显示完毕 ------- \n";

   return true;

}

这里遍历了链表,用上了string .c_str(),估计是编译器的问题,不能直接输出string,于是只好把它转换成*char了。

 

(三) 模块3:参赛者类

※  继承类:

  player 类公有继承了subject类,要使用其中的Mprint(),ResetNum()等函数,需要用subject单链表来记录该参赛者的信息。

※  数据成员:

player类中只设计了四个数据成员用 ① pname记录参赛者名称,② avscore记录参赛者总平均分, ③ totscore记录参赛者总分 ④ mingci 记录名次,用这三个数据记录主要要实现的查询分数,记录总分,得出名次等功能。

※  成员函数:

① bool player::PerIn(int n, std::vector<double>&t)        // 放入第N科的成绩

{

    if (NULL == head) return false;

    int i;

    for (fence = head, i = 1; i < n; fence = fence -> next, ++i);    // 定位至第N科

    fence -> PutScores (t);

    return true;

}

此处的for语句可能写得有点奇怪,不过,这里面的for语句,要实现的功能是“定位”,通过外部的输入n,让它不断执行fence = fence -> next, 直到n的时候,停止执行,这样,执行了n次,fence也指到了第n位了,执行完这句以后,就可以用fence指向里面的成员,对其成员进行操作了。

 

②    bool AllAccount(int synum)    // 计算各科平均分(放入容器的最后),总平均分,总分

{......

    for (fence = head; fence != NULL; fence = fence -> next)

    {

         tempscore = 0;

         temppingju = 0;

         for (i = 0; i < (fence -> score).size(); i++)

         {

             totscore += (fence -> score)[i];

             tempscore += (fence -> score)[i];

             if((fence -> score).size() > 3)  // 评分人数大于三时,记录单科最高最低成绩

             {

                  if (max < (fence -> score)[i])

                  {

                       max = (fence -> score)[i];

                  }

                  if (min > (fence -> score)[i])

                  {

                       min = (fence -> score[i]);

                  }

                  k = 2;

             }

         }

         temppingju =(tempscore - max - min) /(synum – k);

         (fence -> score).push_back(temppingju);   // 将单科平均分放在该科目的最后一位

         avscore += temppingju;

    }......}

  这个函数里面,主要是算法的问题,在这里,建立了两个临时变量,用以存储计算临时的平均成绩,tempscore是用来计算临时单科的总分,temppingju减去了最高分和最低分后,再除以它的数目,当评委数大于三,可以除去最高分和最低分,即算平均分的时候要减去二,因此加上了一个K变量(加K变量就不用多一个if语句用作判断了)。再将计算出的单科平均分放在科目链表中的结点中的最后一项,这样,参赛者就可以读出自己的每科平均分了。至于总分,只需要每次执行for循环的时候使用 += 符号相加就可以了。

 

(四)模块4:评委类

※  继承类:

  Syndic 类公有继承了subject类,要使用其中的Mprint(),ResetNum()等函数,需要用subject单链表来记录该参赛者的信息。

※  数据成员:

player类中只需要用到一个数据成员sname用以记录参赛者名称。

※  成员函数:

这个类里面的成员函数也比较少,只有三个,实现的是提取姓名,评分,计总分功能。

①    bool Syndic::Syn(std::vector<player> & p, std::vector<double> &tempScoreAll)    

   {......

       if(EnterSubject())

       {

            ReadAll(tempScoreAll);

       }

       else

       {

            cout << "请使用管理员登陆并输入相关评分项目...";

       }

       return true;

   }

这里面都用了subject类中的函数实现评分功能,如果用EnterSubject()输入成功,那么就将全部输入成功的数据用ReadAll()函数放入到tempScoreAll中保存,用作当全部评委评完分以后,再从tempScoreAll向量中提取出来进行计算。

 

②     void Syndic::Syn2(int sunum, int plnum, int synum, std::vector<double>& tscore, std::vector<player> & p, std::vector<Syndic> &s)

{

   // tempscore的存放顺序是:评委,参赛者,科目

   // 此函数获得:总分,总平均分,每科平均分,名次

   using namespace std;

   int i;

   int j;

   int k;

   int temppushnum;

   vector <double> singleScore;

 

   for ( j = 1; j<= plnum; ++j)

   {    // j个参赛者

       for ( k = 1; k <= sunum; ++k)

       {    // k个科目

            temppushnum = 0;

            for ( i = 1; i <= synum; i++)

            {    // 先读取一个参赛者一个科目的全部分数

                 // 将全部评委的同一参赛者同一科目成绩放入每一个参赛者每一科目中

                 temppushnum = j + ( ( (k - 1) + (sunum * ( i - 1) ) ) * plnum) - 1;

                 singleScore.push_back (tscore[temppushnum]);

            }

       p[j - 1].PerIn(k, singleScore);

       singleScore.clear();

       }

   }

(中途断开程序,解释:)这里使用了一个singleScore用于临时存储提取出来的每一个参赛者每一个项目的全部成绩,然后再将其放进每一个参赛者相对应的科目中,每次放入后再将 vector清空,重新下一次数据的放入。这段程序中,最主要要知道如何从顺序表中精确地找出想要的数据对其位置进行提取,用temppushnum计算出位置。

 

   for (i = 0; i < plnum; ++i)                    // 全部学生取得各自的总分,平均值

   {

       p[i].AllAccount(synum);

   }

   // 计算名次

   vector <double> tmici;                         // 临时存放提取的平均分

   vector <int> rmici(plnum);                     // 按顺序储放名次

   double dt;

   double tempmax = 0;

   for (i = 0; i < plnum; i++)                    // 提取平均分放入数组

   {

       p[i].GetAc(dt);

       tmici.push_back (dt);

   }

   for (k = 0; k < plnum; k++)

   {

       for (i = 0; i < plnum; i++)      // 找出最大值位置 j

        {  

            if (tempmax < tmici[i])

            {

                 j = i;

                 tempmax = tmici[j];

            }

        }

   rmici[j] = k + 1;                     // 按原数组的顺序存放名次

   tmici[j] = -5000;                    // 令最大值变为最小值,使下一次能作比较

   tempmax = 0;

   }

 

   for ( i = 0; i < plnum; i++)         // 放入名次到类中存放进入学生类中

   {

       p[i].PutMingci(rmici[i]);

   }

   return;

}

这里判断名次主要用了多建一个数组的方法,先判断最大值的位置,当知其位置时,将新数组的相当位置进行名次赋值,赋值完以后,再将原数组中的最大值变为最小值,以下一次循环找到次大值,从而得出所有的排名,最后,再将后数组的值逐步放入参赛者类。

 

(五)模块5:管理员类

※  继承类:

  Admins 类公有继承了subject和users两个类,因为它要同时能使用管理这两个类中的数据的功能,对users中的用户组进行增添删除,对subject中的node进行增添删除。

※  数据成员:

Admins 无数据成员,因为它只需负责管理subject 和users,并不需要新添变量。

※  成员函数:

①   void admins::SaveFile(std::vector<player> & p)   // 保存文本

{ ......

   ofstream fout;

......

   cout << "\n请输入文件名:";

   cin >> name;

   name.append(".txt");

   fout.open(name.c_str());

......}

一般的文件输出过程,这里面用了一个.append函数,为了方便用户输入时要输入.txt之类的扩展名,然后就是fout处理了,另外,在输出格式控制上(未贴代码),都用了cout.width(10)使输出更加美观。

 

②   int admins::InputUser(int itemp2,std::vector<player> &p, std::vector<Syndic> &s, subject *tsub, std::string stemp1)

{

   subject tesu;

   tesu.getSubject (tsub);

   player *xp;

   if (1 == itemp2)

   {

       xp = new player(stemp1, tesu);

       p.push_back(*xp);

       delete xp;

       xp = NULL;

       return 0;

   }

   ......

   return 0;

}

  这一个函数是为了实现新建用户的过程,当新建一个参赛者类或者评委类时,都要将项目的数据同步更新,让新建的用户也有相同的项目数,保证以后评委的计算正常运行,这里从外部调用了一个subject类进来,并且,因为subject传进来时是用指针的,所以,这里会再新建一个局部变量,为了让地址不相同,再将这个局部变量的资料通过创建的new的构造函数传输入总的参赛者或者总的评委的向量中。在放入完毕后,进行收尾工作,将新建空间用delete删除,然后将指针地址置空(使其值为NULL)。

         

③    bool admins::AreaShow(int c, double max, double min,std::vector<player> & p)

{......

   if (1 == c)                 // 查询所有人员的分数

   {

    for (i = 0; i < (p.size()); ++i)

    {

        p[i].getin(n, a, t, m);

        ......

        MakeSure++;

    }  

    cout << " \n\n  (⊙o⊙)…  查询完毕,共查询了 " << MakeSure << " 个学生的总平均成绩。\n";

   return true;      

   }

   if (2 == c)            // 查询平均分数范围内的

   {

    for (i = 0; i < p.size(); ++i)

    {

    p[i].getin(n, a, t, m);

    if ( a >= min && a <= max)

    ............

   if (3 == c)            // 查询名次范围内的

   {

    for (i = 0; i < p.size(); ++i)

    {

    p[i].getin(n, a, t, m);

    if ( m >= min && m <= max)

    ......

    这里一共用了三个if语句,当程序进来开始执行时,先会选择是要执行哪一个if,三个if中都包含了一个循环语句,然后,循环对每一个向量当中的数据进行读取显示,直到读取完整个向量,其中第二个和第三个if多用了一个if语句,就是用于输出限制的,当其满足给定范围内的分数,一定范围内的名次,才会显示。

 

(六)模块6:主函数

※  菜单的设计

在主函数中,对各菜单使用了统一的函数进行输入输出:char AllMenu(void (*menu)(), char minnum, char maxnum);通过用调用函数指针,AllMenu的第一项参数放入要输出的菜单,第二项参数放入选择的最小字符,第三项参数放入选择的最大字符,其返回类型为字符型,可以供switch或者if等判断语句使用,在某些菜单要输入前,还使用了cstdlib类中的system(“cls”)进行清除屏幕的操作,在某些选项需要退出时,用了conio.h类中的_getchar()达到按任意键退出的效果。

   本次共制作了8个菜单,它们分别是WelcomeMenu、LangMenu、PlayerMenu、GradeMenu、AdminMenu、PersonReferMenu、AllReferMenu、SettingMenu()。在一系列的菜单中,主要运用了do-while控制菜单的循环,switch(char)控制菜单的选择,而在控制do-while时,主要是用预先建立的变量作为判断条件,让其可以在任意菜单选项中退出。

 

※  主要的默认用户及变量

该程序中,默认建立了三个用户和一个科目,它们分别是Player1,Syndic1,Admin1和subject1,这三个用户的密码默认为123。

// 默认初始化一个项目和三个用户和一个存放所有分数的容器。

   admins All("subject1", 1, 0);

   All.AppendUser("Player1", "123", 1);

   All.AppendUser("Syndic1", "123", 2);

   All.AppendUser("Admin1", "123", 3);

   vector<double> tempScoreAll;

// 建立subject变量并且从刚刚初始化的用户中提取该变量

   subject tempsub;

   subject *tsub = &tempsub;

   All.getSubject(tempsub);

// 创建 player 及 syndic 容器

   vector <player> p;

   vector <Syndic> s;

// 新建两用户放进这两个容器中。

   player *tpn = new player("Player1", tempsub);

   p.push_back(*tpn);

   Syndic *tsn = new Syndic("Syndic1", tempsub);

   s.push_back(*tsn);

   delete tpn;

   tpn = NULL;

   delete tsn;

    tsn = NULL;

在整个程序中,主要用了一个Admin1管理员对象对一整个程序中的项目,用户进行管理,然后,用了vector类的player建立为p对象,用了vector类的Syndic建立为s对象,这两个对象,贯穿整个程序,让其作为链接各个类,对全部学生数据各种操作的桥梁。

 

☞  程序使用说明

 

――――――――――――――――――――――――――――――――――――――――――――――

系统默认账号: 参赛者:Player1     评委:Syndic1       管理员:Admin1

系统默认密码: 123

系统默认科目: subject1

程序使用注意:  请按照程序提示进行操作! 每次输入后都要按回车确定!

 

――――――――――――――――――――――――――――――――――――――――――――――

欢迎界面   1. 进入登陆界面     2. 退出系统  

 

――――――――――――――――――――――――――――――――――――――――――――――

登陆界面   选中后,按提示输入账号及密码,只允许出现三次错误,当出现三次错误后自动退出系统,

           成功输入正确的账号及密码后,系统将会自动根据所输入账号为你选择进入以下界面:

          1.登陆界面           2. 评分界面         3. 管理界面

 

――――――――――――――――――――――――――――――――――――――――――――――

查询界面   1. 查询个人成绩     2. 注销用户         3. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

评分界面   1. 评分             2. 成绩查询         3. 注销用户             4. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

管理界面   1. 成绩查询         2. 参数设置         3. 文本保存             4. 注销用户

5. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

查询个人成绩功能界面   选中后,系统将会显示你的单科项目平均分,总平均分,总名次等相关信息。

                        显示信息后,将提示选择:   1. 返回登陆界面  2. 注销用户  3. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

集体查询功能界面       1. 普通无序查询

2. 按指定总平均分范围内的成绩人员查询

                        3. 按指定名次范围内的成绩人员查询

 4. 返回上一界面

                        5. 注销用户

                        6. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

设置功能界面          1. 查询系统人员             2. 添加系统人员

3. 删除系统人员             4. 查询评分项目

5. 添加评分项目             6. 删除评分项目

7. 返回管理界面             8. 注销用户

9. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

查询个人成绩功能界面   选中后,系统将会显示你的单科项目平均分,总平均分,总名次等相关信息。

                        显示信息后,将提示选择:   1. 返回登陆界面  2. 注销用户  3. 退出系统

 

――――――――――――――――――――――――――――――――――――――――――――――

评分功能               选中后,系将会显示你需要评分的项目及参赛者,按照提示输入相关的信息后,

系统将会提示按任意键返回上一界面。当所有的评委都评分完毕后,系统将会给出提示信息,此时参赛者可以登陆查询个人分数。

 

――――――――――――――――――――――――――――――――――――――――――――――

参数设置功能          选中后,系统将会进入设置功能界面。

 

――――――――――――――――――――――――――――――――――――――――――――――

文本保存功能            选中后,系统将会提示需要保存的文件的文件名,键入文件名之后,系统将为你自动保存数据并将该文件保存为文本文件,文本保存完成后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

按指定总平均分范围内的成绩人员查询功能      选中后,系统将会提示你需要输入需要查询的成绩最大值,成绩最小值,之后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

按指定名次范围内的成绩人员查询功能          选中后,系统将会提示你需要输入需要查询的名次最大值,成绩最小值,之后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

普通无序查询功能        选中后,系统将会显示全部参赛者的姓名,总平均分,总名次,之后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

查询系统人员功能     选中后,系统将会分用户组来显示现有的用户,之后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

添加系统人员功能      选中后,系统将会提示选择需要添加的用户类型,之后,系统提示输入需要添加的用户名称,之后,显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

删除系统人员功能    选中后,系统将会提示键入需要删除的用户名称,之后,显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

查询评分项目功能      选中后,系统将会显示现有的评分项目,之后,系统显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

添加评分项目功能   选中后,系统将会提示键入需要添加的评分项目,之后,系统提示输入需要添加的评分项目,之后,显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

删除评分项目功能   选中后,系统将会提示键入需要删除的评分项目,之后,系统提示输入需要删除的评分项目,之后,显示提示语句,输入任意键后返回到设置功能界面中。

 

――――――――――――――――――――――――――――――――――――――――――――――

返回上一界面         选中后,程序会显示一段话,要求按任意键后,返回到上一界面中;

 

――――――――――――――――――――――――――――――――――――――――――――――

返回管理界面          选中后,程序会显示一段话,要求按任意键后,返回到管理界面中;

 

――――――――――――――――――――――――――――――――――――――――――――――

注销系统              选中后,程序会显示一段话,要求按任意键后,返回到欢迎界面中;

 

――――――――――――――――――――――――――――――――――――――――――――――

退出系统              选中后,程序会显示一段话,要求按任意键后,按任意键退出程序。

 

――――――――――――――――――――――――――――――――――――――――――――――

 

 

☞  总结

经过了整整(2011.07.21—2011.08.01)十一天的日日夜夜的艰苦奋战,终于完成了这个1876行的代码C++ 程序之简易评分系统V1.0(DOS界面)(小钱版)。

 一个小项目的编写过程,个人,将其概括为四大步骤,写程序需求分析(准备阶段) -> 程序编写(工作阶段) -> 程序调试(检查阶段) -> 程序说明书的拟写(总结阶段)。

在程序需求分析时,要列出所有这个程序预定需要完成的功能,然后,每个功能之间有些什么联系,每个功能需要一些什么数据成员,需要哪些变量,需要建立哪些类函数,可能,这些就是OOP的思想吧,然后,得知道main函数大概需要怎么联系这些所有的函数,最好能画出一个UML图,(我是先画了一个软件流程图,后再画UML图的。)在这个过程中,我花费了两天的时间,一个好的开始是很重要的,没有了这个步骤的话,下面的流程可能就不会这么顺利了,所以我认为,第一个步骤是必须得花时间在上面的。这个步骤里面,比较难做到的是“如何联系”,这个问题是最需要花时间思考的,单个单个的功能的实现并不难,要把它们联系起来就有点困难了。

其中,到了第二阶段,工作阶段,将所画出的UML图,先用伪代码表示,再转化为高级语言来表示,(简单的那些可以直接用高级语言)。这个过程并不算难,只是有时候想要实现一些功能的时候,不是这么容易想到如何用语言来表达,这个得看你语言的基础知识,语言的语法是否掌握得好了。用语言写的这个过程,花了三天的时间完成。

之后,到了第三阶段,检查调试阶段,在这一个阶段中,我写个程序的时候所花费的时间是最长的了,五天的时间,不断地对每个功能重复测试,很多时候,这个阶段,错误最多的一般是算法问题了,日日夜夜地对着程序,但是一直找不到自己的问题错在哪里,是一件相当痛苦的事,痛苦的是不知道自己的问题错在哪,发现的问题错在哪以后,再对问题进行分析,这个问题就好解决了,而这个分析的过程也是痛苦的,因为这个分析是对你之前思维的一种否定,要从自己的正确中找出错误。但是,发现出了自己的这些痛苦以后,知道了自己要面临的是这些问题以后,那全都会变成快乐的了,因为知道了问题所在,就自然会有解决的方法。想起了一句经典对白:“我都吾知道自己错系边度,点改啧,你话我话啦!我错系边啊!”原来戏中是主角是这样的感受的,在第一次做调试工作的时候稍体验到了,而且是对着一部不会说话的电脑,很好的是,在电脑里面有网络,通过网络的交流,才是收益最大的,想了NNN次也想不明白后,才上去群里面问,上去CSDN里面问,若有人稍提点了一下后,忽然灵光一闪,就会有一种恍然大悟的感觉,哈哈!那也可能是一种难得的喜悦感啊!我不是很喜欢问别人问题,与其说不喜欢问别人问题,不如说,不喜欢问一些没有经过自己思考的问题,一个问题,琢磨了N个小时,N天以后,看了很多书也解决不了的话,那么,那个时候才会去问,如果一不懂就去问的话,那样很难得到成长,还有,问人也有技巧的,有时候看见别人的提问,实在无语,在问别人的时候,你得告诉别人你的思路是怎样的,自己的问题具体出在哪里,你用过哪些方法来解决,这才是问题的提问,否则,我只能称作那些是一些不是问题的问题,说着说着,有点偏题了,算法的问题,的确需要解决,当然,从中体会到,数据结构的知识也很重要,因为,在写程序的时候,可以用到了不少的数据结构的知识。

最后一个阶段,写说明书,可以说,这个过程是对自己所写的程序做一次最后的检查吧,告诉别人自己的程序如何去用,有哪些优点,缺点,给别人讲述了一次,重新完整地再看了一次代码,总结了一下自己的思路,不过这一步可以做得很快,我只用了一天完成,因为要思考的东西,在你写程序的时候基本都思考出来了。

最后,就个人感觉,想要做好一个C++,要学好的知识有很多,我暂时定为以下这些:

1.基本语法知识

2.格式(良好的编译习惯)

3.数据结构

4.算法

5. 即学即用的学习方法

这里的格式,我不得不说一下,很多人都不重视自己所写的代码格式,只是自己看得懂就行了,注释也没有几行,该空格空行的地方也没有空格空行,要注意的一点是,程序,除了写给自己看,还是写给自己的BOSS看了,还是写给各位热爱C++的好友看的,格式不好看,别人是根本没有心思去看了,你要想请教别人的时候就必然出现问题,注释没几行,又想别人帮助你,这是比较不好办的,因为,别人要看你的程序的话,就要先进入你的思路去思考,没有注释的话,就意味着要帮助你的人要花上更多的时间去看你的代码,唉~这样想要得到别人的帮助都不好办吧?这同时也是在我帮别人解决C++ 问题时得出的一些感受。

最后,终于,这个程序是完工了,其中,其实还有一些功能可以添加的,如修改密码,这个不难实现,基本上是加一个函数就可以了,然后,还可以成绩显示排序,这个倒要花时间去想想了,因为又汲及到算法的问题,还有,退出系统后,下次打开系统,依然能继续进行,那保存进度的功能,其实这个功能,我也想到一点思绪,可能,可以通过文件的输出读取来实现这个功能的,不过,由于时间的问题,这里就先不做改进了。至于MFC界面,打从一开始就没有打算实现,因为,要想使用MFC的话,现在只能使用一些非常表层的东西,如果原理都不知道的话,就这样使用,就太没有意思了,如果我不是这个专业的话,我还可以接受,但是,对于自己专业的东西,我还是喜欢,知其然,知其所以然。而且,现在用MFC的话,也不是很适合,很少公司都不会用了,所以,先不学了,如果想要学的话,就先学好API,SDK吧!

最最后,想简短地说几句:知识的掌握,知识的累积,很重要,坚持,很重要,耐心,很重要,分享,很重要,交流,很重要,努力,很重要。


 

☞  附:程序调试时遇到的问题及解决方法 (部分)

 

这个程序,假设用一个类存储全部的用户名,将可以在这个类中实现登陆功能。

问题:假如我想再在这个类的基础上(把这个类中的全部用户名作为基类),如何能实现以下的功能呢?

首先,需要有多个评价科目,这里要建一个链表或者数组,假如这里的科目不是问题,那么,如何能实现,单个评委对多个参赛者的多个评价科目评价?数据该往哪儿放呢?这个问题一直想不通,最后还要用这些数据来算出每个参赛者的平均分的,而且平均分还有一个减去最高分和最低分的要求,也就是说,还要从多个评委中,判断是一个科目中哪一个是最高分的哪一个是最低分的。开始打算两个类完成这些全部功能,实现全部数据的存储,不过,后来,还是想不能这些数据该往哪儿放,所以后来就打消了这个念头。

之后,我假设它只加上取得类型与取得姓名的这两个主要功能。那么根据用户的类型,就可以返回选择进入哪一种函数了,打算用vector<type>player(上面说的函数中返回该类型的数目),来完成这个功能,这样的话,就可以达到存储多个不同用户的数据的目的了,而每个评委此时需要存多个科目的多个数据(不同的参赛者),每个参赛者要存多个科目的单个数据(个人单科平均成绩),也就是说,在科目里面,它的成绩的数目的变动的,那么,在这里,我再次使用vector完成这一功能。至于如何计算平均成绩,这个函数该放在哪个类中?想了一下,不能放在评委类或者学生类了,因为,现在定义的评委是一个评委的,而需要的数据是多个评委的,由于之前多个评委的数据都是放在主函数中实现的,所以现在,平均成绩的计算也放在主函数中,并且,计算结果存放回每一个学生的类。

最后,决定了这样定义五个类:用户类,科目类,参赛者类,评委类,管理员类。

--------------------------------------------------------------------------------------- -

 

大家,有个问题想问一下,能在派生类中获取基类吗?

 

class admins: public users, public subject

{

public:

       admins(std::string sub, int np = 0, int ns = 0):subject(sub, np, ns){}

      

       void getSubject(subject & t)

       {

              t = subject;

              return ;

       }

 

};

 

本打算能获取subject, 但是subject又是一个类型,怎样能把admins内的subject变为对象再进行获取呢?

假如我创建了一个对象

admins All;

那么,现在我想提取 All 里面的 subject , 应该怎么做呢?

 

因为还有一个player类,想用subject类的东西,但是subject类又在admins类中。

 

 

再重新描述一下问题:

现在,有三个类

class admins: public player{.......};

class player: public subject{.......};

class subject: public node{.......};

然后,创两个对象

admins ad;

player pl;

最后,

想将ad 中的subject所有元素,放在pl中。

 

假如用:copy

class subject

{...

void copy(subject* pp)

{

  ......

 ......

a=pp->a; b=pp->b;......}

...

}

然后

void getSubject(subject& t)

{

     t.copy(this);//或者是t.copy((subject*)this);

}

但是,现在问题是,当ad 对象创建后 ad里面的node是一个链表,能用copy将整个链表也同时用刚刚那个copy函数复制给pl对象?

 

有什么好方法呢?能在派生类的对象中获取基类的元素放在另一个派生类的对象吗?

 

 

ad 有一个 this

sub 也有一个 this

 

外部的是sub,要想将 sub.copy(this) 的话, 这里面的this是ad 的, 所以写的时候就要 copy (subject * a);

此时的a 是原本有值的ad对象的, (无值) element = (有值) a -> element就对了。

------------------------------------------------------------------------------------ -

 

原:

    for ( j = 0; j < plnum; ++j)

    {   // j个参赛者

        for ( k = 0; k < sunum; ++k)

        {   // k个科目

            for ( i = 0; i < sum * synum; i += sum)

            {   // 先读取一个参赛者一个科目的全部分数

                singleScore.push_back (tscore[i]);

            }

        p[j].PerIn(k + 1, singleScore);

        }

    singleScore.clear();

    }

问题:singleScore.clear()应该是每用完一次后就进行及时的清除的,不然的话,会造成数据的计算异常

改为:

    for ( j = 0; j < plnum; ++j)

    {   // j个参赛者

        for ( k = 0; k < sunum; ++k)

        {   // k个科目

            for ( i = 0; i < sum * synum; i += sum)

            {   // 先读取一个参赛者一个科目的全部分数

                singleScore.push_back (tscore[i]);

            }

        p[j].PerIn(k + 1, singleScore);

        singleScore.clear();

        }

    }

------------------------------------------------------------------------------------------

原:

bool player::PerRefer()                             // 打印每一科成绩(参赛者功能)

{

    using std::cout;

    if (head -> score.size() == NULL) return false;

    for (fence = head; fence != NULL; fence = fence -> next)

    {

        cout.width(15);

        cout << (fence -> SubjectName);

        cout << " : " << (fence -> score[0]);

    }

    return true;

}

问题:显示参赛者成绩的话,要显示的是每个参赛者的平均分,而在其它函数中,平均分是放在容器中的最后一项,所以,应先用.size()测出它的总长度然后再-1就是它的最后一项了。

改为:

bool player::PerRefer()                                 // 打印每一科成绩(参赛者功能)

{

    using std::cout;

    if (head -> score.size() == NULL) return false;

    int i;

    i = head -> score.size()  - 1;

    for (fence = head; fence != NULL; fence = fence -> next)

    {

        cout.width(15);

        cout << (fence -> SubjectName);

        cout << " : " << (fence -> score[i]);

    }

    return true;

}

------------------------------------------------------------------------------------------

改:

bool player::AllAccount(int synum)  // 计算各科平均分(放入容器的最后),总平均分,总分

{

    if ( head == NULL ) return false;

    unsigned i = 0;

    double max = 0;

    double min = 0;

    double tempscore;                                   // 用于临时储存单科总分

    double temppingju;                                  // 临时存单科平均分

    for (fence = head; fence != NULL; fence = fence -> next)

    {

        tempscore = 0;

        temppingju = 0;

        for (i = 0; i < (fence -> score).size(); i++)

        {

            totscore += (fence -> score)[i];

            tempscore += (fence -> score)[i];

            if((fence -> score).size() > 3)     // 评分人数大于三时,记录单科最高最低成绩

            {

            if (max < (fence -> score)[i])

                max = (fence -> score)[i];

            if (min > (fence -> score)[i])

                min = (fence -> score[i]);

            }

        }/有问题。。。。单科平均分应除以平均评委人数而不是科目数,temppingju计算的不正确 再引用一个变量记录评委数。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

        temppingju =(tempscore - max - min) /synum;

        (fence -> score).push_back(temppingju);     // 将单科平均分放在该科目的最后一位

        avscore += temppingju;

    }

    return true;

}

 

------------------------------------------------------------------------------------------

问题:push_back失败

 

bool subject::ReadAll(std::vector<double>& temp)            // 读取全部科目的数据

{

    if(head == NULL && 0 == (head -> score).size()) return false;

    int i;

    double t;

    for ( fence = head; fence != NULL; fence = fence -> next)   // 多个科目

    {

        for (i = 0; i < num; i++)               // 给num个参赛者同一科目的分数按顺序存入

        {

            t = (fence -> score[i]);

            temp.push_back (t);           //    temp.insert(temp.end(),t);

//

        std::cout << "\nReadAll是否有问题 " << fence -> score[i]   << "t " << t << " "

                    << "push_back是否成功." << temp[i];

//

        }

    }

    return true;

}

 

 ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之评分界面 ---- O(∩_∩)O~ -----

 

1. 评分

2. 成绩查询

3. 注销用户

4. 退出系统

-> 我要实现的功能:1

 

------------------------- > Syndic1 评委评分中 < -------------------------

 

 -> 提示信息:共有 3 个项目需要评分:

 

第 1 个项目: subject1

    请评出第 1 位参赛者的成绩: 10

 

检测tempsubject:10(fence -> score).push_back(t)10

 

第 2 个项目: s2

    请评出第 1 位参赛者的成绩: 20

 

检测tempsubject:20(fence -> score).push_back(t)20

 

第 3 个项目: s3

    请评出第 1 位参赛者的成绩: 30

 

检测tempsubject:30(fence -> score).push_back(t)30

 

ReadAll是否有问题 10t 10 push_back是否成功.10

ReadAll是否有问题 20t 20 push_back是否成功.10

ReadAll是否有问题 30t 30 push_back是否成功.10

显示第一次评分工作中的tempscoreAll10

显示第一次评分工作中的tempscoreAll20

显示第一次评分工作中的tempscoreAll30

 o(≧v≦)o~~  恭喜,您的评分工作已完成...

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

 o(≧v≦)o~~  恭喜,全部的评委评分工作已完成了,可以查询全部学生的成绩啦...

 

请按任意键继续...

 

后来发现,原来问题所在是:

<< "push_back是否成功." << temp[i];

因为这个i的值的变化 如果num = 1的话 你每次输出的都是temp[0]的值 

即使这个地方看看你的num的值是不是1 如果是就是问题所在

再用一个变量专门输出temp 用来控制temp的下标

bool subject::ReadAll(std::vector<double>& temp)        // 读取全部科目的数据

{

    using namespace std;

    if(head == NULL && 0 == (head -> score).size()) return false;

    int i;

    int j = 0;

    double t;

    for ( fence = head; fence != NULL; fence = fence -> next)       // 多个科目

    {

        for (i = 0; i < num; i++)               // 给num个参赛者同一科目的分数按顺序存入

        {

            t = (fence -> score[i]);

            temp.push_back(t);

//

            cout << "\nReadAll是否有问题 " << fence -> score[i]    << "t " << t << " "

                    << "push_back是否成功." << temp[j];

            j++;

//

        }

    }

    return true;

}

 

这样检测后就正常了,只是自己的检测方法有问题。

终于弄明白了,原来一直是下标作怪,这里的检测方法有点问题,循环的时候只考虑到一个循环,而没有考虑到另一个循环。

经提点后,多看了几遍,想了几次代码,检测了一下运行结果,果然OK了,原来问题不是出现在push_back里面!

 

------------------------------------------------------------------------------------------

 

下面可能是同样的问题:

原:

// 评分工作-2 放入学生成绩

void Syn2(int sunum, int plnum, int synum, std::vector<double>& tscore, std::vector<player> & p, std::vector<Syndic> &s)

{

    // tempscore的存放顺序是:评委,参赛者,科目

    // 得出第个参赛者,每个科目的平均分

    // 步进数目:评委 +(科目*参赛者)

    // 要求获得:总分,总平均分,每科平均分,名次

    // 将全部评委的同一参赛者同一科目成绩放入每一个参赛者每一科目中

 

    using namespace std;

    vector <double> singleScore;

 

    int i;

    int j;

    int k;

    int sum;

    sum = sunum * plnum;

   

    for ( j = 0; j < plnum; ++j)

    {   // j个参赛者

        for ( k = 0; k < sunum; ++k)

        {   // k个科目

            for ( i = 0; i < sum * synum; i += sum)

            {   // 先读取一个参赛者一个科目的全部分数

                singleScore.push_back (tscore[i]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[i] << endl;

//

            }

        p[j].PerIn(k + 1, singleScore);

        singleScore.clear();

        }

    }

 

    for (i = 0; i < plnum; ++i)                 // 全部学生取得各自的总分,平均值

        p[i].AllAccount(synum);

 

 

改为:

// 评分工作-2 放入学生成绩

void Syn2(int sunum, int plnum, int synum, std::vector<double>& tscore, std::vector<player> & p, std::vector<Syndic> &s)

{

    // tempscore的存放顺序是:评委,参赛者,科目

    // 得出第个参赛者,每个科目的平均分

    // 步进数目:评委 +(科目*参赛者)

    // 要求获得:总分,总平均分,每科平均分,名次

    // 将全部评委的同一参赛者同一科目成绩放入每一个参赛者每一科目中

    using namespace std;

    vector <double> singleScore;

    int i;

    int j;

    int k;

    int sum;

    sum = sunum * plnum;

    int tpush = 0;

   

//

//

    for (; tpush < tscore.size(); tpush++)

            cout << "\nReadAll是否有问题 " << tscore[tpush]    ;

 

//

//

 

    for ( j = 0; j < plnum; ++j)

    {   // j个参赛者

        for ( k = 0; k < sunum; ++k)

        {   // k个科目

            for ( i = 0; i < sum * synum; i += sum)

            {   // 先读取一个参赛者一个科目的全部分数

                singleScore.push_back (tscore[i + k]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[i + k] << endl;

//

            }

        p[j].PerIn(k + 1, singleScore);

        singleScore.clear();

        }

    }

 

哈哈,经这么一改后,输出正常啦!

 

 

 

―――――――――――――――――――――――――――――――――――――――――――

第三项测试:添加用户

 

 ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之评分界面 ---- O(∩_∩)O~ -----

 

1. 评分

2. 成绩查询

3. 注销用户

4. 退出系统

-> 我要实现的功能:1

 

------------------------- > Syndic1 评委评分中 < -------------------------

 

 -> 提示信息:共有 1 个项目需要评分:

 

第 1 个项目: subject1

    请评出第 1 位参赛者的成绩: 10

 

检测tempsubject:10(fence -> score).push_back(t)10    请评出第 2 位参赛者的成绩:

20

 

检测tempsubject:20(fence -> score).push_back(t)20    请评出第 3 位参赛者的成绩:

30

 

检测tempsubject:30(fence -> score).push_back(t)30

 

ReadAll是否有问题 10t 10 push_back是否成功.10

ReadAll是否有问题 20t 20 push_back是否成功.20

ReadAll是否有问题 30t 30 push_back是否成功.30

显示第一次评分工作中的tempscoreAll10

显示第一次评分工作中的tempscoreAll20

显示第一次评分工作中的tempscoreAll30

 o(≧v≦)o~~  恭喜,您的评分工作已完成...

ReadAll是否有问题 10

ReadAll是否有问题 20

ReadAll是否有问题 30

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

 o(≧v≦)o~~  恭喜,全部的评委评分工作已完成了,可以查询全部学生的成绩啦...

 

请按任意键继续...

 

检查问题,估计是在Syn2函数里面。还是这一部分出的问题:

//

//

 

    for ( j = 0; j < plnum; ++j)

    {   // j个参赛者

        for ( k = 0; k < sunum; ++k)

        {   // k个科目

            for ( i = 0; i < sum * synum; i += sum)

            {   // 先读取一个参赛者一个科目的全部分数

                singleScore.push_back (tscore[i + k]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[i + k] << endl;

//

            }

        p[j].PerIn(k + 1, singleScore);

        singleScore.clear();

        }

    }

 

改为:

    for ( j = 1; j =< plnum; ++j)

    {   // j个参赛者

        for ( k = 1; k =< sunum; ++k)

        {   // k个科目

            temppushnum = 0;

            for ( i = 1; i =< synum; i++)

            {   // 先读取一个参赛者一个科目的全部分数

                temppushnum = i * k * j - 1;

                singleScore.push_back (tscore[temppushnum]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[temppushnum] << endl;

//

            }

        p[j - 1].PerIn(k, singleScore);

        singleScore.clear();

        }

    }

 

 

遇到新问题:输入三个选手的单科成绩是: 10 20 30

 ----- O(∩_∩)O~ -- 欢迎来到简易评分系统之查询功能界面 -- O(∩_∩)O~ -----

 

1. 普通无序查询

2. 按指定总平均分范围内的成绩人员查询

3. 按指定名次范围内的成绩人员查询

4. 返回上一界面

5. 注销用户

6. 退出系统

-> 我要实现的功能:1

 

           姓名  总平均分      总分 名次

        Player1        30        30    3

        Player2        60        60    2

        Player3       120       120    1

 

 

  (⊙o⊙)…  查询完毕,共查询了 3 个学生的总平均成绩。

 

请按任意键继续...

 

于是:添加cout 检查Allaccoutn函数

bool player::AllAccount(int synum)      // 计算各科平均分(放入容器的最后),总平均分,总分

{

    if ( head == NULL ) return false;

    unsigned i = 0;

    double max = 0;

    double min = 0;

    double tempscore;                               // 用于临时储存单科总分

    double temppingju;                              // 临时存单科平均分

//

    std::cout << "\nAllAccount开始取平均分\n";

//

    for (fence = head; fence != NULL; fence = fence -> next)

    {

        tempscore = 0;

        temppingju = 0;

        for (i = 0; i < (fence -> score).size(); i++)

        {

            totscore += (fence -> score)[i];

            tempscore += (fence -> score)[i];

//

            std::cout<< "\ni" << i << ": " << "totscore;" << totscore;

            std::cout << "\ni" << i << ": " << "tempscore;" << tempscore;

//

 

            if((fence -> score).size() > 3) // 评分人数大于三时,记录单科最高最低成绩

            {

            if (max < (fence -> score)[i])

                max = (fence -> score)[i];

            if (min > (fence -> score)[i])

                min = (fence -> score[i]);

            }

        }

        temppingju =(tempscore - max - min) /synum;

//

        std::cout << "\ntemppingju:" << temppingju;

//

        (fence -> score).push_back(temppingju);     // 将单科平均分放在该科目的最后一位

 

        avscore += temppingju;

//

        std::cout << "\navscore:" << avscore << "\n";

 

    }

    return true;

}

 

结果:

 ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之评分界面 ---- O(∩_∩)O~ -----

 

1. 评分

2. 成绩查询

3. 注销用户

4. 退出系统

-> 我要实现的功能:1

 

------------------------- > Syndic1 评委评分中 < -------------------------

 

 -> 提示信息:共有 1 个项目需要评分:

 

第 1 个项目: subject1

 

    请评出第 1 位参赛者的成绩: 10

 

检测tempsubject:10(fence -> score).push_back(t)10

    请评出第 2 位参赛者的成绩: 20

 

检测tempsubject:20(fence -> score).push_back(t)20

    请评出第 3 位参赛者的成绩: 30

 

检测tempsubject:30(fence -> score).push_back(t)30

 

ReadAll是否有问题 10t 10 push_back是否成功.10

 

ReadAll是否有问题 20t 20 push_back是否成功.20

 

ReadAll是否有问题 30t 30 push_back是否成功.30

 

显示第一次评分工作中的tempscoreAll10

显示第一次评分工作中的tempscoreAll20

显示第一次评分工作中的tempscoreAll30

 o(≧v≦)o~~  恭喜,您的评分工作已完成...

ReadAll是否有问题 10

ReadAll是否有问题 20

ReadAll是否有问题 30

tscore[i]是否正常 10

第0科的成绩,我输出为: 10

 

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.10

 

tscore[i]是否正常 20

第0科的成绩,我输出为: 20

 

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.20

 

tscore[i]是否正常 30

第0科的成绩,我输出为: 30

 

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.30

 

AllAccount开始取平均分

 

i0: totscore;30

i0: tempscore;30

temppingju:30

avscore:30

 

AllAccount开始取平均分

 

i0: totscore;30

i0: tempscore;30

i1: totscore;60

i1: tempscore;60

temppingju:60

avscore:60

 

AllAccount开始取平均分

 

i0: totscore;30

i0: tempscore;30

i1: totscore;60

i1: tempscore;60

i2: totscore;120

i2: tempscore;120

temppingju:120

avscore:120

 

 o(≧v≦)o~~  恭喜,全部的评委评分工作已完成了,可以查询全部学生的成绩啦...

 

请按任意键继续...

 

由于输出结果。。令我怀疑。。。。于是试图获取fence的地址

 

bool player::PerIn(int n, std::vector<double>&t)                    // 放入第N科的成绩

{

    if (head == NULL) return false;

    int i;

    for (fence = head, i = 1; i < n; fence = fence -> next, ++i);       // 定位至第N科

    fence -> PutScores (t);

//

    std::cout << "fence的地址" << fence;

    std::cout << std::endl;

    for ( i = 0 ; i < t.size(); i++)

    std::cout << "\nPerIn 将 fence -> PutScore(t)扔进去了。\n."

        << "显示第" << i << "项." << t[i] << std::endl

         << "\nPerIn 将 fence -> PutScore(t)扔进去了。\n."

        << "显示score 的第" << i << "项." << fence->score[i] << std::endl;

//

    return true;

}

 

发觉。。。。竟然全部地址相同

 ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之评分界面 ---- O(∩_∩)O~ -----

 

1. 评分

2. 成绩查询

3. 注销用户

4. 退出系统

-> 我要实现的功能:1

 

------------------------- > Syndic1 评委评分中 < -------------------------

 -> 提示信息:共有 1 个项目需要评分:

第 1 个项目: subject1

    请评出第 1 位参赛者的成绩: 10

检测tempsubject:10(fence -> score).push_back(t)10

    请评出第 2 位参赛者的成绩: 20

检测tempsubject:20(fence -> score).push_back(t)20

    请评出第 3 位参赛者的成绩: 30

检测tempsubject:30(fence -> score).push_back(t)30

ReadAll是否有问题 10t 10 push_back是否成功.10

ReadAll是否有问题 20t 20 push_back是否成功.20

ReadAll是否有问题 30t 30 push_back是否成功.30

显示第一次评分工作中的tempscoreAll10

显示第一次评分工作中的tempscoreAll20

显示第一次评分工作中的tempscoreAll30

 o(≧v≦)o~~  恭喜,您的评分工作已完成...

ReadAll是否有问题 10

ReadAll是否有问题 20

ReadAll是否有问题 30

tscore[i]是否正常 10

singleScore[i]是否正常 10

j = 1放入

PutScore第0科的成绩,我输出为: 10

fence的地址0051E6C8

PerIn 将 fence -> PutScore(t)扔进去了。

.显示第0项.10

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.10

tscore[i]是否正常 20

singleScore[i]是否正常 20

j = 2放入

PutScore第0科的成绩,我输出为: 20

fence的地址0051E6C8

PerIn 将 fence -> PutScore(t)扔进去了。

.显示第0项.20

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.20

tscore[i]是否正常 30

singleScore[i]是否正常 30

j = 3放入

PutScore第0科的成绩,我输出为: 30

fence的地址0051E6C8

PerIn 将 fence -> PutScore(t)扔进去了。

.显示第0项.30

PerIn 将 fence -> PutScore(t)扔进去了。

.显示score 的第0项.30

第1个学生的preRefe

       subject1 : 30

执行循环

AllAccount开始取平均分

i0: totscore;30

i0: tempscore;30

temppingju:30

avscore:30

第2个学生的preRefe

       subject1 : 30

执行循环

AllAccount开始取平均分

i0: totscore;30

i0: tempscore;30

i1: totscore;60

i1: tempscore;60

temppingju:60

avscore:60

第3个学生的preRefe

       subject1 : 60

执行循环

AllAccount开始取平均分

i0: totscore;30

i0: tempscore;30

i1: totscore;60

i1: tempscore;60

i2: totscore;120

i2: tempscore;120

temppingju:120

avscore:120

 o(≧v≦)o~~  恭喜,全部的评委评分工作已完成了,可以查询全部学生的成绩啦...

请按任意键继续...

 

于是,怀疑是新增用户那里面的问题了。可能是复制的时候用的是浅复制,或者只复了地址

 

于是,创建局部变量,自由变量,尝试改变其地址,并且可以获取值。

//  ------------ 管理员功能 -- 新增用户,放入原容器 ------------

int InputUser(int itemp2,std::vector<player> &p, std::vector<Syndic> &s, subject *tsub, std::string stemp1)

{

    subject tesu;

    tesu.getSubject (tsub);

    player *xp;

    if (1 == itemp2)

    {

        xp = new player(stemp1, tesu);

        p.push_back(*xp);

        delete xp;

        xp = NULL;

        return 0;

    }

    Syndic *ys;

    if (2 == itemp2)

    {

        ys = new Syndic(stemp1,tesu);

        s.push_back(*ys);

        delete ys;

        ys = NULL;

        return 0;

    }

    return 0;

}

 

成功

 

―――――――――――――――――――――――――――――――――――――――――――

问题,尝试先添加参赛者用户再添加科目,失败,评分的时候player2不见了

于是考虑到可能是添加科目的时候,没有将科目中的参赛者数目信息更新到类中,于是加了以下语句

 

All.GetTwoNumbers(itemp2, itemp4);

for (itemp1 = 0; itemp1 < p.size(); itemp1++)

    {

            p[itemp1].ResetNum(itemp2);

    }

for (itemp1 = 0; itemp1 < s.size(); itemp1++)

    {

        s[itemp1].ResetNum(itemp4);

}

 

还是有错,经检查cout,再次修改:

    All.GetTwoNumbers(itemp2, itemp4);

for (itemp1 = 0; itemp1 < p.size(); itemp1++)

    {

        p[itemp1].ResetNum(itemp2);

    }

for (itemp1 = 0; itemp1 < s.size(); itemp1++)

        {          

                s[itemp1].ResetNum(itemp2);

        }

 

后来,成功评分了,但是,评分结果却还是有错,于是:

    for ( j = 1; j<= plnum; ++j)

    {   // j个参赛者

        for ( k = 1; k <= sunum; ++k)

        {   // k个科目

            temppushnum = 0;

            for ( i = 1; i <= synum; i++)

            {   // 先读取一个参赛者一个科目的全部分数

 

                temppushnum = i * k * j - 1;

                singleScore.push_back (tscore[temppushnum]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[temppushnum] << endl;

                cout << "\nsingleScore["<< i << "]" << "是否正常 "

                    << singleScore[i-1] << endl;

 

//.....................................放入单科也正常-----------------------------

            }

        //

            cout << "\nj = " << j << "放入\n";

//

        p[j - 1].PerIn(k, singleScore);

        singleScore.clear();

        }

    }

 

这个算法的弊端是当其为乘法时,2*1和1*2的结果是一样的,用*法的时候,它不能有序地读出数据,它只是一个顺序表。

所以这样的算法在这里并不适合,得修改。

 

    for ( j = 1; j<= plnum; ++j)

    {   // j个参赛者

        for ( k = 1; k <= sunum; ++k)

        {   // k个科目

            temppushnum = 0;

            for ( i = 1; i <= synum; i++)

            {   // 先读取一个参赛者一个科目的全部分数

               

                // 将全部评委的同一参赛者同一科目成绩放入每一个参赛者每一科目中

 

 

                temppushnum = j + ( ( (k - 1) + (sunum * ( i - 1) ) ) * plnum) - 1;

                singleScore.push_back (tscore[temppushnum]);

//

                cout << "\ntscore[i]" << "是否正常 "

                    << tscore[temppushnum] << endl;

                cout << "\nsingleScore["<< i << "]" << "是否正常 "

                    << singleScore[i-1] << endl;

 

//..................................................................放入单科也正常------------------------------------------------------------

            }

        //

            cout << "\nj = " << j << "放入\n";

//

        p[j - 1].PerIn(k, singleScore);

        singleScore.clear();

        }

    }

 

经过三个小时的奋半,这次这个算法完全正确了,要在顺序表中找出精确的位置,关键知道k里面有多少个j,i里面有多少个k,注意最大值的取法,方法就出来了。

 

最后,完善程序,规范格式,去掉临时用的测试用注释和输出行。

 

 

 

// main.cpp -- 将数个功能使用该函数联结起来

#include <iostream>
#include <string>
#include <vector>
#include <cstdlib>		// system("cls")
#include <cstddef>		// size_t
#include <conio.h>		// _getch()

#include "users.h"
#include "subject.h"
#include "player.h"
#include "Syndic.h"
#include "admins.h"

int main()
{
	#include "menu.h"
	using namespace std;

// Create Temp Variable to make some menu circulation
	int CirculateJudge;	
	int &cij1 = CirculateJudge;
	int cij2;
	int jiemian;
	char ChoiceJudge;
	char &chj = ChoiceJudge;

// Create Temp Variable to realize other functions
	char ctemp;
	int itemp1;
	int itemp2;
	unsigned itemp3;
	int itemp4;
	int PingfenDone = 0;
	double dtemp1;
	double dtemp2;
	string stemp1;
	string stemp2;
	
// 默认初始化一个项目和三个用户和一个存放所有分数的容器。
	admins All("subject1", 1, 0);
	All.AppendUser("Player1", "123", 1);
	All.AppendUser("Syndic1", "123", 2);
	All.AppendUser("Admin1", "123", 3);
	vector<double> tempScoreAll;

// 建立subject变量并且从刚刚初始化的用户中提取该变量
	subject tempsub;
	subject *tsub = &tempsub;
	All.getSubject(tempsub);

// 创建 player 及 syndic 容器
	vector <player> p;
	vector <Syndic> s;

// 新建两用户放进这两个容器中。
	player *tpn = new player("Player1", tempsub);
	p.push_back(*tpn);
	Syndic *tsn = new Syndic("Syndic1", tempsub);
	s.push_back(*tsn);
	delete tpn;
	tpn = NULL;
	delete tsn;
	tsn = NULL;
	
// 开始执行程序
	do													// 欢迎界面 - do
	{
	cij1 = 0;											// 退出欢迎界面的循环 - 0
    system("cls");
	chj = AllMenu(WelcomeMenu, '1', '2');				// 欢迎界面的选择 1.进入 2.退出
	if ('1' == chj)										// 选择 1, 进入下一界面
	 {
		system("cls");									// 清屏
		LangMenu();										// 显示登陆界面
		cij2 = 3;										// 初始化用户的输入机会为 3
		do												// 用户的三次输入循环 - do
		{
		cout << "1. 请输入账号:";
		cin >> stemp1;
		cout << "2. 请输入密码:";
		cin >> stemp2;
		if (All.FindName(stemp1) && All.CheckPassword(stemp2))
		{
			cij2 = 0;									// 退出登陆界面的循环 
			cout << "\n\n     o(≧v≦)o~~  恭喜您,登陆成功,请按任意键进入下一界面...";
			ctemp = _getch();
			system("cls");
			All.GetType(itemp1);						// 自动获取选择需要登陆的类型
			switch(itemp1)
			{

// ************************************* 参赛者 *********************************************
			 case 1:
			 {
				do
				{											// 界面循环 - do
				jiemian = 0;
				system("cls");
				chj = AllMenu(PlayerMenu, '1', '3');
				switch(chj)
				{
				 case '3':									// 退出系统
					{
						cij1 = 0;
						jiemian = 0;
						break;
					}
				 case '2':									// 注销
					 {
						 cij1 = 1; 
						 jiemian = 0;
						 break;
					 }
				 case '1':									// 查询
					 {
					  // 搜出该姓名在容器中的位置 -- p[itemp3]
						 for (itemp3 = 0; itemp3 < (p.size()); ++itemp3)
						 {
							 p[itemp3].getpname(stemp2);
							 if(stemp2 == stemp1)
							 {
								 break;
							 }
						 }

						cout << endl << endl;
						if (p[itemp3].CheckScore())
							{
								cout << endl;
								cout.width(15);
								cout << "姓名";
								cout.width(10);
								cout << "总平均分";
								cout.width(10);
								cout << "总分";
								cout.width(5);
								cout << "名次";
								cout << endl;
								if(p[itemp3].Mprint())
								{
									cout << "\n\n下面显示每科平均分:\n";
									p[itemp3].PerRefer();
									cout << endl;
								}
								else
								{
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								}
							}
						else
							{
							cout << "现在成绩仍未得出,请耐心等待评委们评分....";
							}
						
						cout << '\n' << "请按任意键继续...";							 
						ctemp = _getch();
						system("cls");
						chj = AllMenu(PersonReferMenu, '1', '3');
						switch(chj)
						{
						case '1':				// 界面循环 
							{
								jiemian = 1; 
								break;
							}
						 case '3':				// 退出系统
							{
								cij1 = 0;
								jiemian = 0;
								break;
							}
						 case '2':				// 注销
							 {
								 cij1 = 1; 
								 jiemian = 0;
								 break;
							 }
						 default:	break;
						 }
						break;					// 查询界面中查询功能的break
					 }
				 default:	break;
				}
				}while(jiemian);				// 查询界面循环 - do
				break;
				}

//  ************************************* 评委 *********************************************

			 case 2:
				{
				do													// 界面循环--do
				{
				jiemian = 0;
				system("cls");
				chj = AllMenu(GradeMenu, '1', '4');
				switch(chj)
				{
				case'4':											// 退出系统
					{
						cij1 = 0;
						jiemian = 0;
						break;
					}
				 case '3':											// 注销
					 {
						 cij1 = 1; 
						 jiemian = 0;
						 break;
					 }
				 case '2':											// 集体成绩查询
					 {
						system("cls");
						chj = AllMenu(AllReferMenu, '1', '6');
						{
						switch(chj)
							{
							case '1':								 // 查询全部
							{
								if (All.AreaShow(1, 0, 0, p));
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							}
							case'2':								// 查询总平均分范围内的 
							{
								cout << "\n ---> 请输入需要查询分数的范围之最大值:";
								cin >> dtemp1;
								cout << " ---> 请输入需要查询分数的范围之最小值:";
								cin >> dtemp2;
								if (All.AreaShow(2, dtemp1, dtemp2, p)); 
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							  }
							case'3':							 // 查询名次分范围内的
							{
								cout << "\n ---> 请输入需要查询名次的范围之最大值:";
								cin >> dtemp1;
								cout << " ---> 请输入需要查询名次的范围之最小值:";
								cin >> dtemp2;
								if ( All.AreaShow(3, dtemp1, dtemp2, p));
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							}
							case '4':			// 界面循环 
							{
								jiemian = 1; 
								break;
							}
							 case '5':			// 注销
							 {
								 cij1 = 1; 
								 jiemian = 0;
								 break;
							 }
							 case '6':			// 退出系统
							{
								cij1 = 0;
								jiemian = 0;	// 满足退出欢迎界面的循环
								break;
							}
							default: break;
							}
						}
						cout << '\n' << "请按任意键继续...";
						ctemp = _getch();
						break;
					 }
				 case '1':			// 评分
					 {
						// 搜出该评委姓名在容器中的位置 -- s[itemp3]
						 for (itemp3 = 0; itemp3 < (s.size()); ++itemp3)
						 {
							 s[itemp3].getsname(stemp2);
							 if(stemp2 == stemp1)
							 {
								 break;
							 }
						 }
						 cout << endl;
						 All.ReadSubnum(itemp4);
						 if(s[itemp3].CheckScore())
						 {
							 cout << "\n您的评分工作已完成,请勿重复工作。";
						 }
						 else
						 {
						 if (s[itemp3].Syn(p,tempScoreAll) || itemp4)
						   {
							 PingfenDone++;
							 cout << "\n o(≧v≦)o~~  恭喜,您的评分工作已完成...";
					    	 }
						 else
						    {
							cout << "  未发现科目或参赛者,请以管理员身分登陆,调整系统... ";
						    }
						 }
						All.GetTwoNumbers(itemp1, itemp2);
						if(PingfenDone == itemp2)
						{	// 全部评委评分完毕则放入学生数组
							s[itemp3].Syn2(itemp4, itemp1, itemp2, tempScoreAll, p, s);
							cout << "\n o(≧v≦)o~~  恭喜,全部的评委评分工作已完成了,可以查询全部学生的成绩啦..."
								<< endl;
							PingfenDone = 0;
							tempScoreAll.clear();
						}
						cout << '\n' << "请按任意键继续..."; 
						ctemp = _getch();
						jiemian = 1;
						break;
					 }
				 default: break;
				 }
				}while(jiemian);									// 界面循环--while
				break;
				}

// ************************************* 管理员 *********************************************

			 case 3:					
			  {
				do													// 界面循环--do
				{
				jiemian = 0;
				system("cls");
				chj = AllMenu(AdminMenu, '1', '5');
				switch(chj)
				{
				case '5': 											// 退出系统
					{
						cij1 = 0;
						jiemian = 0;
						break;
					}		
				case '4':											// 注销
					{
						cij1 = 1; 
						jiemian = 0;
						break;
					 }
				case '3':											// 文件保存
					{
						if (0 == p.size())
						{
							cout << "数据还未输入,请耐心等待。";
						}
						else
						{
							All.SaveFile(p);
						}
						cout << '\n' << "请按任意键继续..."; 
						ctemp = _getch();
						jiemian = 1;
						break;
					}
				case '2':											// 参数设置
					{
						system("cls");
						chj = AllMenu(SettingMenu, '1', '9');		// 设置界面
						switch(chj)
						{
						case '9': 									// 退出系统
							{
								cij1 = 0;
								jiemian = 0;
								break;
							}
						case '8':									// 注销
							{
								cij1 = 1; 
								jiemian = 0;
								break;
							 }
						case '7':									// 返回界面
							{
								jiemian = 1;
								break;
							}
						case '4':									// 查询评分项目
							{
								All.PrintSubject();
								cout << "\n操作成功,";
								cout << '\n' << "请按任意键继续..."; 
								ctemp = _getch();
								jiemian = 1;
								break;
							}
						case '5':									// 添加评分项目
							{
								cout << "\n请输入需要添加科目的名称:";
								cin >> stemp1;
								if(All.AppendSubject(stemp1))
								{
									cout << "\n\n ------- 科目添加成功 ------- \n";
									All.getSubject(*tsub);
									All.CopyNewUsers(p, s, (*tsub));
									cout << endl;
									All.PrintSubject();

									All.GetTwoNumbers(itemp2, itemp4);
									for (itemp1 = 0; itemp1 < int(p.size()); itemp1++)
										{
											p[itemp1].ResetNum(itemp2); 
										}
									for (itemp1 = 0; itemp1 < int(s.size()); itemp1++)
										{
											s[itemp1].ResetNum(itemp2); 
										}
									tempScoreAll.clear();
									PingfenDone = 0;
								}
								else
								{
									cout << "意外,科目添加失败,请重启程序.";
								}
								cout << '\n' << "请按任意键继续..."; 
								ctemp = _getch();
								jiemian = 1;
								break;
							}
						case '6':									// 删除评分项目
							{	
								All.PrintSubject();
								All.ReadSubnum(itemp1);
								if(1 != itemp1 && 0 != itemp1)
								{
									cout << "\n请输入需要删除科目的名称:";
									cin >> stemp1;
									if(All.DelSubject(stemp1))
									{
										cout << "\n\n ------- 科目删除成功 ------- \n";
										All.getSubject(*tsub);
										All.CopyNewUsers(p, s, *tsub);
										All.PrintSubject();
										All.GetTwoNumbers(itemp2, itemp4);
										for (itemp1 = 0; itemp1 < int(p.size()); itemp1++)
										{
											p[itemp1].ResetNum(itemp2); 
										}
										for (itemp1 = 0; itemp1 < int(s.size()); itemp1++)
										{
											s[itemp1].ResetNum(itemp2); 
										}

										tempScoreAll.clear();
										 PingfenDone = 0;
									}
									else
										cout << "\n科目删除失败,请检查是否输入正确.";
								}
								else
								{
									cout << "\n操作失败,科目数目只剩下1科或更少,禁止删除。";
								}
								cout << '\n' << "请按任意键继续..."; 
								ctemp = _getch();
								jiemian = 1;
								break;
							}
						case '1':									// 查询系统人员
							{
							All.PrintAll();
							cout << "\n操作成功,";
							cout << '\n' << "请按任意键继续..."; 
							ctemp = _getch();
							jiemian = 1;
							break;
							}
						case '2':									// 添加系统人员
							{ 
								do
								{
								itemp4 = 0;
								do
								{
								itemp1 = 0;
								cout << "\n-------------请选择需要添加的类型号码-----------\n\n"
									 << "      1. 参赛者      2.评委		3.管理员\n"
									 << "选择:";
								cin >> itemp2;
								if (!cin || (itemp2 > 3 || itemp2 < 1))
								{ 
									cout << "\n o(︶︿︶)o 输入有误,请重新输入.\n";
									cin.clear();
									while(cin.get() != '\n') continue;
									itemp1 = 1;
								}
								}while(itemp1);
								cout << "\n请输入姓名:";
								cin >> stemp1;
								cout << "请输入密码:";
								cin >> stemp2;

								if(All.FindName(stemp1))
									{
									itemp4 = 1;
									cout << "\n\n (+﹏+)~  错误:用户已存在,添加失败,请重新添加不存在的用户。\n";
									}
								}while(itemp4);

								All.AppendUser(stemp1, stemp2, itemp2);
								All.InputUser(itemp2, p, s, tsub,stemp1);			// 将用户放入类中
								if (1 == itemp2 || 2 == itemp2)						// 当参赛者数目有变动时
								{
									itemp3 = unsigned (p.size());
									itemp2 = int(itemp3);
									for( itemp1 = 0; itemp1 < itemp2; itemp1 ++)
									{
										p[itemp1].ResetNum(itemp2);
									}
									for( itemp1 = 0; itemp1 < int(s.size()); itemp1 ++)
									{
										s[itemp1].ResetNum(itemp2);	
									}
								}
								tempScoreAll.clear();
								 PingfenDone = 0;
								cout << "操作成功,";
								cout << '\n' << "请按任意键继续..."; 
								ctemp = _getch();
								jiemian = 1;
								break;
							}
						case '3':										// 删除系统人员
							{
								
								All.PrintAll();
								cout << "\n请输入需要删除的姓名:";
								cin >> stemp1;
								if(All.DelUsers(stemp1))
								{
									 for (itemp3 = 0; itemp3 < (p.size()); itemp3++)
									 {
										 
										 p[itemp3].getpname(stemp2);
										 if (stemp1 == stemp2)		// 当参赛者数目有变动时
										 {
											p.erase(p.begin() + itemp3);	
											itemp3 = unsigned(p.size());
											itemp2 = int(itemp3);
											for( itemp1 = 0; itemp1 < itemp2; itemp1 ++)
											{
												p[itemp1].ResetNum(itemp2);
											}
											for( itemp1 = 0; itemp1 < int(s.size()); itemp1 ++)
											{
												s[itemp1].ResetNum(itemp2);	
											}									
											tempScoreAll.clear();
											 PingfenDone = 0;
											break;
										 }
									 
									 for (itemp3 = 0; itemp3 < (s.size()); itemp3++)
									 {
										 
										 s[itemp3].getsname(stemp2);
										 if (stemp1 == stemp2)		// 当评委数目有变动时
										 {
											 s.erase(s.begin() + itemp3);
											 cout << "\n 注意:评委用户组有变动,评分工作重新开始。\n";

											 for (itemp3 = 0; itemp3 < s.size(); itemp3 ++)
											 {
												 if(s[itemp3].DelaSubject())
												 {
												 }
												 else
												 {
													 break;
												 }
											 }
											 for (itemp3 = 0; itemp3 < p.size(); itemp3 ++)
											 {
												 if(p[itemp3].DelaSubject())
												 {
												 }
												 else
												 {
													 break;
												 }
											 }
											tempScoreAll.clear();
											 PingfenDone = 0;
											 break;
										 }

									 }
									 cout << "\n 用户删除成功.";
									 }
								}
								else
									cout << "未找到用户名或违规操作,删除失败。\n";
								cout << '\n' << "请按任意键继续..."; 
								ctemp = _getch();
								jiemian = 1;
								break;
							}
						default: break;
						}
						break;
					}
				case '1':												// 集体成绩查询
					 {
						system("cls");
						chj = AllMenu(AllReferMenu, '1', '6');
						{
						switch(chj)
							{
							case '1':									 // 查询全部
							{
								if (All.AreaShow(1, 0, 0, p));
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							}
							case'2':									// 查询总平均分范围内的 
							{
								cout << "\n ---> 请输入需要查询分数的范围之最大值:";
								cin >> dtemp1;
								cout << " ---> 请输入需要查询分数的范围之最小值:";
								cin >> dtemp2;
								if (All.AreaShow(2, dtemp1, dtemp2, p)); 
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							  }
							case'3':									 // 查询名次分范围内的
							{
								cout << "\n ---> 请输入需要查询名次的范围之最大值:";
								cin >> dtemp1;
								cout << " ---> 请输入需要查询名次的范围之最小值:";
								cin >> dtemp2;
								if ( All.AreaShow(3, dtemp1, dtemp2, p));
								else
									cout << "\n现在总成绩仍未得出,请耐心等待评委们评分....";
								jiemian = 1;
								break;
							}
							case '4':			// 界面循环 
							{
								jiemian = 1; 
								break;
							}
							 case '5':			// 注销
							 {
								 cij1 = 1; 
								 jiemian = 0;
								 break;
							 }
							 case '6':			// 退出系统
							{
								cij1 = 0;
								jiemian = 0;	// 满足退出欢迎界面的循环
								break;
							}
							default: break;
							}
						}
						cout << '\n' << "请按任意键继续...";
						ctemp = _getch();
						break;
				}
				 default:break;				
				 }
			}while(jiemian);
			break;									// 管理员界面 case 3
			}
			default: break;							// 该default为对应三大界面的switch
			}										// 该括号对应三大界面的自动选择
		 }
			
		else										// 用户输入错误的账号密码时
		 {
			--cij2;
			if (0 != cij2)
			{
			cout << "\n                  ——o(╯□╰)o—o(╯□╰)o—o(╯□╰)o——\n"
				 << "    ————  您的输入有误,请重新输入(您还有 "
				 << cij2
				 << " 次输入机会)  ————\n\n";
			}
			else
			{
				cout << "\n\n —o(╯□╰)o— 很遗憾地说,您的输入机会用完了...";
				cij1 = 0;
				cout << "\n\n 请按任意键退出";
				ctemp = _getch();
			}
		  }
		}while(cij2);									// 用户的三次输入循环 - while
	 }													// chj 选择了'1'则进行 if 语句
	}while(cij1);										// 欢迎界面的循环 - while
	// 退出系统,显示提示
	system("cls");
	cout << "\n   ( ^_^ )/~~ 拜拜      成功退出简易评分系统,请按任意键关闭...";
	ctemp = _getch();
	return 0;
}


// Menu.h -- Menus Statement

char AllMenu(void (*menu)(), char minnum, char maxnum);			// All Menus Choice
void WelcomeMenu();												// 欢迎界面
void LangMenu();												// 登陆界面
void PlayerMenu();												// 查询界面
void GradeMenu();												// 评分界面
void AdminMenu();												// 管理界面
void PersonReferMenu();											// 个人查询功能界面
void AllReferMenu();											// 集体查询功能界面
void SettingMenu();												// 设置界面

// menu.cpp -- All menus define

#include <iostream>

char AllMenu(void (*menu)(), char minnum, char maxnum)
{
	using namespace std;
	menu();
	char ch;
	cin >> ch;
	while (ch < minnum || ch > maxnum)
	{
	cin.clear();								// 令failbit = 0; 清除错误状态。
	while(cin.get() != '\n')					// 读取多余字符。
		continue;
	cout << "\n              ——o(╯□╰)o—— \n"
	     << "————    您的选择有误,请重新选择  ————\n\n"
		 << " -> 我要实现的功能:";
	cin >> ch;
	}
	// 如果输入成功,清除多余的字符,以防对以后的输入带来影响。
	cin.clear();
	while(cin.get() != '\n')
		continue;
	return ch;
}

void WelcomeMenu()			// 欢迎界面
{
	std::cout << " ------- O(∩_∩)O~ ------- 欢迎来到简易评分系统 ------- O(∩_∩)O~ -------\n\n"
			 << "1. 进入登陆界面  \n"
			 << "2. 退出系统     \n"
			 << "-> 我要实现的功能:";
	return ;
}


 void LangMenu()				// 登陆界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之登陆界面 ---- O(∩_∩)O~ -----\n\n";
	return ;
}


 void PlayerMenu()			// 查询界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之查询界面 ---- O(∩_∩)O~ -----\n\n"
			 << "1. 查询个人成绩\n"
			 << "2. 注销用户\n"
			 << "3. 退出系统\n"
			 << "-> 我要实现的功能:";
	return;
}

void PersonReferMenu()		// 个人查询功能界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之查询界面 ---- O(∩_∩)O~ -----\n\n"
			 << "1. 返回登陆界面\n"
			 << "2. 注销用户\n"
			 << "3. 退出系统\n"
			 << "-> 我要实现的功能:";
	return;
}


void GradeMenu()			// 评分界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之评分界面 ---- O(∩_∩)O~ -----\n\n"
			 << "1. 评分\n"
			 << "2. 成绩查询\n"
			 << "3. 注销用户\n"
			 << "4. 退出系统\n"
			 << "-> 我要实现的功能:";
	return;
}

void AllReferMenu()			// 集体查询功能界面
{
	std::cout << " ----- O(∩_∩)O~ -- 欢迎来到简易评分系统之查询功能界面 -- O(∩_∩)O~ -----\n\n"
			 << "1. 普通无序查询\n"
			 << "2. 按指定总平均分范围内的成绩人员查询\n"
			 << "3. 按指定名次范围内的成绩人员查询\n"
			 << "4. 返回上一界面\n"
			 << "5. 注销用户\n"
			 << "6. 退出系统\n"
			 << "-> 我要实现的功能:";
	return;
}

void AdminMenu()			// 管理界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之管理界面 ---- O(∩_∩)O~ -----\n\n"
			 << "1. 成绩查询\n"
			 << "2. 参数设置\n"
			 << "3. 文本保存\n"
			 << "4. 注销用户\n"
			 << "5. 退出系统\n"
			 << "-> 我要实现的功能:";
	return;
}

void SettingMenu()			// 设置界面
{
	std::cout << " ----- O(∩_∩)O~ ---- 欢迎来到简易评分系统之设置界面 ---- O(∩_∩)O~ -----\n\n"
			 << "1. 查询系统人员\n"
			 << "2. 添加系统人员\n"
			 << "3. 删除系统人员\n"
			 << "4. 查询评分项目\n"
			 << "5. 添加评分项目\n"
			 << "6. 删除评分项目\n"
			 << "7. 返回管理界面\n"
			 << "8. 注销用户\n"
			 << "9. 退出系统\n\n"
			 << "- 注意:此处实现任何添加删除功能都将清空所评分数,评委需要重新评分。\n"
			 << "-> 我要实现的功能:";
	return;
}

// users.h -- 管理用户类--作为其它功能的基类

#ifndef USERS_H_	
#define USERS_H_

#include <iostream>
#include <cstring>
#include <vector>
#include "player.h"
#include "Syndic.h"
#include "subject.h"

class users
{
private:
	std::vector<std::string> UsersName;			// 用户名
	std::vector<std::string> UsersPassword;		// 密码
	std::vector<int> UsersType; 				// 用户类型:设定1为参赛者,2为评委,3为管理员

public:
	int UsersNumber;							// 用户数目
	int PositionUsers;							// 定位,用于搜寻类中的元素

	users(int pu = 0, int un = 0): PositionUsers(pu), UsersNumber(un){}

	bool GetTwoNumbers(int &, int &);								// 获取参赛者及评委数目
	bool GetOneNumbers(int & adn);									// 获取管理员数目
	void GetName(std::string &);									// 从类中提取姓名
	bool FindName(const std::string &);								// 从类中寻找姓名
	bool CheckPassword(const std::string &);						// 检查姓名与密码是否对应
	bool GetType(int &);											// 判断登陆类型
	bool DelUsers(const std::string&);								// 删除该用户
	void AppendUser(std::string, std::string, int);					// 新建用户
	void PrintAll();												// 打印全部用户
																	// 删除原来容器,用现在的用户名重建
	void CopyNewUsers(std::vector<player>& p, std::vector<Syndic>& s, subject &);

/*
	~users() 
	{
		PositionUsers = 0;
		UsersNumber = 0;
		UsersName.clear();
		UsersPassword.clear();
		UsersType.clear();
	}
	*/
};

#endif

// Syndic.h -- 评判类

#ifndef SYNDIC_H_
#define SYNDIC_H_

#include <iostream>
#include <string>
#include <vector>
#include "player.h"
#include "subject.h"

class Syndic: public subject
{
private:
	std::string sname;
	
public:
	Syndic(std::string ssn, const subject &ss):subject(ss), sname(ssn){}

	void getsname(std::string& t);											// 提取本参赛者的姓名
	bool Syn(std::vector<player> & p, std::vector<double> &tempScoreAll);	// 评分工作
	// 评分工作-2 (评分计算)放入学生成绩
	void Syn2(int sunum, int plnum, int synum, std::vector<double>& tscore, std::vector<player> & p, std::vector<Syndic> &s);
};

#endif

// subject.h -- 用于创建多个评分项目及存储每个项目的成绩

#ifndef SUBJECT_H_
#define SUBJECT_H_

#include <iostream>
#include <string>
#include <vector>

class node
{
public:
	std::string SubjectName;			// 科目名称
	std::vector<double> score;			// 科目分数
	node *next;							// 下一指针
	node (std::string sn, node *n = NULL): SubjectName(sn), next(n){}
	node (node* n = NULL): next(n){}

	void PutScores(std::vector<double> t);
	void ShowName();
};

class subject: public node
{
private:
	int num;					// 参赛者的数目(node的数目)

public:
	node * fence;				// 阑珊
	node * tail;				// 尾结点
	node * head;				// 头指针
	int subnum;					// 科目数目

	subject()
	{
		int n = 0;
		int subn = 0;
		num = n;
		subnum = subn;
	}
	subject(std::string suname, int n = 0, int sum = 0)
	{
		num = n;
		tail = fence = head = new node(suname, NULL);
		subnum = sum + 1;
	}
/*
	~subject()
	{
		while (head != NULL)
		{
			fence = head;
			head = head -> next;
			delete fence;
		}
	}
*/
	void GetPNum(int &n);							// 获取科目中参赛者的数目(node的数目)	
	void ResetNum(int n);							// 重置科目中参赛者的数目(node的数目)
	void ReadSubnum(int &n);						// 读取科目数目
	bool AppendSubject(const std::string &);		// 在尾部追加元素
	bool Find(const std::string&);					// 找到指定名字的函数
	bool DelSubject(const std::string &);			// 删除fence指针的函数
	bool DelaSubject();								// 删除所有指针的score函数
	bool EnterSubject();							// 给全部科目评(N个学生或学生)分
	bool PrintSubject();							// 打印全部科目名称 
	bool ReadAll(std::vector<double>&);				// 读取全部科目的数据
	bool CheckScore();								// 检查该数组中是否已放入数据
	void getSubject(subject *);						// 复制整个subject类
};

#endif

// player.h -- 主要完成参赛者的相关功能

#ifndef PLAYER_H_
#define PLAYER_H_

#include <iostream>
#include <string>
#include <vector>
#include "subject.h"


class player: public subject
{
private:
	std::string pname;
	double avscore;				// 总平均分
	double totscore;			// 总分
	int mingci;					// 名次

public:
	player(const subject & subtemp1):subject(subtemp1){}
	player(std::string pn, const subject &ts, double a = 0, double s = 0, int m = 0): 
	  pname(pn), subject(ts), avscore(a), totscore(s), mingci(m){}

	bool PerIn(int n,std::vector<double>&);							// 放入第N科的成绩
	bool PerRefer();												// 打印每一科成绩
	bool Mprint();													// 名次总分总平均分打印
	bool getin(std::string &, double &, double &, int &);			// 提取本参赛者所有资料
	void getpname(std::string&);									// 提取本参赛者的姓名
	bool AllAccount(int);											// 计算各科平均分,总平均分,总分
	bool GetAc(double &);											// 提取总平均分
	bool PutMingci(const int &);									// 放入名次
};	

#endif

// admins.h -- 管理员类

#include <iostream>
#include <cstring>
#include <vector>
#include <fstream>
#include "player.h"
#include "Syndic.h"
#include "users.h"
#include "subject.h"

class admins: public users, public subject
{
public:
	admins(std::string sub, int np = 0, int ns = 0):subject(sub, np, ns){}

	void getSubject(subject & );									// 从本类中获取整个subject
	void SaveFile(std::vector<player> & );							// 保存文件
	bool AreaShow(int, double, double, std::vector<player> &);	// 按不同方式查询分数
	// 新增用户,放入原容器 
	int InputUser(int,std::vector<player> &, std::vector<Syndic> &, subject *, std::string);

};

// admins.cpp -- 管理员类中新添获取subject,保存文件,新增用户的功能

#include "admins.h"

void admins::getSubject(subject & t)			// 从本类中获取整个subject
{
		t.getSubject(this);
		return ;
}

void admins::SaveFile(std::vector<player> & p)	// 保存文本
{
	using namespace std;
	string name;
	int c;
	ofstream fout;
	do
	{
	c = 0;
	cout << "\n请输入文件名:";
	cin >> name;
	name.append(".txt");
	fout.open(name.c_str());
	if (!fout)
	{
		cout << "无法创建文件,请尝试给文件重命名。";
		c = 1;
	}
	}while(c);

	fout.width(15);
	fout << "姓名";
	fout.width(10);
	fout << "总平均分";
	fout.width(10);
	fout << "总分";
	fout.width(5);
	fout << "名次";
	fout << endl;

	unsigned i;
	std::string n;
	double a;
	double t;
	int m;
	 for (i = 0; i < p.size(); ++i)
	 {
		 p[i].getin(n, a, t, m);
		 fout.width(15);
		 fout << n;
		 fout.width(10);
		 fout << a;
		 fout.width(10);
		 fout << t;
		 fout.width(5);
		 fout << m;
		 fout << endl;
	 }
	 cout << " o(≧v≦)o~~  恭喜,文件保存成功。";
	 fout.close();
	 return;
}

//  ------------  新增用户,放入原容器 ------------ 
int admins::InputUser(int itemp2,std::vector<player> &p, std::vector<Syndic> &s, subject *tsub, std::string stemp1)
{
	subject tesu;
	tesu.getSubject (tsub);
	player *xp;
	if (1 == itemp2)
	{
		xp = new player(stemp1, tesu);
		p.push_back(*xp);
		delete xp;
		xp = NULL; 
		return 0;
	}
	Syndic *ys; 
	if (2 == itemp2)
	{
		ys = new Syndic(stemp1,tesu);
		s.push_back(*ys);
		delete ys;
		ys = NULL;
		return 0;
	}
	return 0;
}

//  ------------ 集体分数查询功能 ------------ 
bool admins::AreaShow(int c, double max, double min,std::vector<player> & p)
{
	using namespace std;
	if (0 == p.size() || 0 == p[0].CheckScore()) return false;
	unsigned i;
	string n;
	double a;
	double t;
	int m;
	int MakeSure = 0;
	cout << endl;
	cout.width(15);
	cout << "姓名";
	cout.width(10);
	cout << "总平均分";
	cout.width(10);
	cout << "总分";
	cout.width(5);
	cout << "名次";
	cout << endl;
	if (1 == c)				// 查询所有人员的分数
	{
	 for (i = 0; i < (p.size()); ++i)
	 {
		 p[i].getin(n, a, t, m);
		 cout.width(15);
		 cout << n;
		 cout.width(10);
		 cout << a;
		 cout.width(10);
		 cout << t;
		 cout.width(5);
		 cout << m;
		 cout << endl;
		 MakeSure++;
	 }	
	 cout << " \n\n  (⊙o⊙)…  查询完毕,共查询了 " << MakeSure << " 个学生的总平均成绩。\n";
	return true;		
	}

	if (2 == c)			// 查询平均分数范围内的
	{
	 for (i = 0; i < p.size(); ++i)
	 {
	 p[i].getin(n, a, t, m);
	 if ( a >= min && a <= max)
	 {
		cout.width(15);
		cout << n;
		 cout.width(10);
		 cout << a;
		 cout.width(10);
		 cout << t;
		 cout.width(5);
		 cout << m;
		 cout << endl;
		 MakeSure++;
	 }
	 }	
	 if (MakeSure)
		cout << " \n\n  (⊙o⊙)…  查询完毕,共有 " << MakeSure << " 个学生的总平均成绩符合要求。\n";
	 else
		 cout <<  " \n\n  (⊙o⊙)…  未发现符合要求的学生。\n";
	 return true;		
	}

	if (3 == c)			// 查询名次范围内的
	{
	 for (i = 0; i < p.size(); ++i)
	 {
	 p[i].getin(n, a, t, m);
	 if ( m >= min && m <= max)
	 {
		 cout.width(15);
		 cout << n;
		 cout.width(10);
		 cout << a;
		 cout.width(10);
		 cout << t;
		 cout.width(5);
		 cout << m;
		 cout << endl;
		 MakeSure++;
	 }
	 }
	 if (MakeSure)
		cout << " \n\n  (⊙o⊙)…  查询完毕,共有 " << MakeSure << " 个学生的总名次符合要求。\n";
	 else
		 cout <<  " \n\n  (⊙o⊙)…  未发现符合要求的学生\n。";
	return true;		
	}
	return true;
}

// player.cpp

#include "player.h"

bool player::PerIn(int n, std::vector<double>&t)					// 放入第N科的成绩
{
	if (NULL == head) return false;
	int i;
	for (fence = head, i = 1; i < n; fence = fence -> next, ++i);	// 定位至第N科
	fence -> PutScores (t);
	return true;
}

bool player::PerRefer()												// 打印每一科成绩(参赛者功能)
{
	using std::cout;
	if (head -> score.size() == NULL) return false;
	int i;
	i = int (head -> score.size())  - 1;
	int j;
	for (fence = head, j = 0; fence != NULL; fence = fence -> next, j++)
	{
		if (0 == (j % 3)) {cout << std::endl;}
		cout.width(15);
		cout << (fence -> SubjectName);
		cout << " : " << (fence -> score[i]);
	}
	return true;
}

bool player::Mprint()													// 名次总分总平均分打印
{
	using std::cout;
	using std::endl;
	if (pname == "") return false;

	cout.width(15);
	cout << pname;
	cout.width(10);
	cout << avscore;
	cout.width(10);
	cout << totscore;
	cout.width(5);
	cout << mingci;
	cout << endl;
	return true;
}

bool player::getin(std::string & n, double & a, double & t, int & m)	// 提取本参赛者所有资料
{
	n = pname;
	a = avscore;
	t = totscore;
	m = mingci;
	return true;
}

void player::getpname(std::string& t)									// 提取本参赛者的姓名
{
	t = pname;
	return;
}

bool player::AllAccount(int synum)										// 计算各科平均分(放入容器的最后),总平均分,总分
{
	if ( head == NULL ) return false;
	int k;
	unsigned i = 0;
	double max = 0;
	double min = 0;
	double tempscore;													// 用于临时储存单科总分
	double temppingju;													// 临时存单科平均分

	for (fence = head; fence != NULL; fence = fence -> next)
	{
		k = 0;
		tempscore = 0;
		temppingju = 0;
		for (i = 0; i < (fence -> score).size(); i++)
		{
			totscore += (fence -> score)[i];
			tempscore += (fence -> score)[i];
			if((fence -> score).size() > 3)									// 评分人数大于三时,记录单科最高最低成绩
			{
				if (max < (fence -> score)[i])
				{
					max = (fence -> score)[i];
				}
				if (min > (fence -> score)[i])
				{
					min = (fence -> score[i]);
				}
				k = 2;
			}
		}
		temppingju =(tempscore - max - min) /(synum - k);
		(fence -> score).push_back(temppingju);								// 将单科平均分放在该科目的最后一位
		avscore += temppingju;
	}
	return true;
}


bool player::GetAc(double & ac)												// 提取总平均分
{
	ac = avscore;
	return true;
}

		
bool player::PutMingci(const int & mc)										// 放入名次(需从外部计算放入)
{		
	mingci = mc;
	return true;
}

// subject.cpp 

#include "subject.h"

void node::PutScores(std::vector<double> t)								// 将外来容器的数据放入类中
{
	int i;
    score.clear();
	for ( i = 0; i < int(t.size()); i++)
	{
		score.push_back (t[i]);
	}
	return;
}

void node::ShowName()													// 输出科目名称
{
	std::cout << SubjectName;
	return ;
}


void subject::GetPNum(int &n)											// 获取科目中参赛者的数目(node的数目)
{
	n = num;
	return;
}

void subject::ResetNum(int n)											// 重置科目中参赛者的数目(node的数目)
{
	num = n;
	return ;
}


void subject::ReadSubnum(int &n)										// 读取科目数目
{
	n = subnum;
	return;
}

bool subject::AppendSubject(const std::string & newname)				// 在尾部追加元素
{
	if (0 == subnum)
	{
		head = fence = tail = new node(newname, NULL);
	}
	else
	{
		tail -> next = new node( newname, NULL);
	}
	if (tail -> next == NULL) return false;
	subnum++;
	tail = tail -> next;
	return true;
}

bool subject::Find(const std::string& oldname)							// 找到指定科目名字的函数
{
	if(NULL == head) return false;
	for (fence = head; fence != NULL; fence = fence -> next)
	{
		if (strcmp((fence -> SubjectName).c_str() , oldname.c_str()) == 0)
		{
			return true;
			break;
		}
	}
	return false;
}

bool subject::DelSubject(const std::string & oldname)					// 删除fence指针的函数
{
	if(Find(oldname))
	{
		if (fence == head)					// 假如仅是头结点
		{
			if (tail == fence)				// 假如即是头结点,又是尾结点
			{
				delete fence;
				fence = NULL;
				head = NULL;
				tail = NULL;
				subnum--;
				return true;
			}
			else
			{
				head = fence -> next;
				delete fence;
				fence = head;
				subnum--;
				return true;
			}
		}

		node * t = fence;					// 假如在中间或尾结点
		for (fence = head; fence -> next != t; fence = fence -> next){}
		if (t == tail)						// 假如是尾结点		
		{
			delete t;
			fence -> next = NULL;
			tail = fence;
		}
		else								// 是在中间
		{
			fence -> next = fence -> next -> next;
			delete t;
		}
		fence = head;
		subnum--;
		return true;
	}
		return false;
}

bool subject::DelaSubject()												// 删除所有指针的score函数
{
	if( head == NULL) return false;
	for(fence = head; fence != NULL; fence = fence -> next)
	{
		fence -> score .clear();
	}
	return true;
}
		
bool subject::EnterSubject()											// 给全部科目评(N个学生或学生)分
{
	using namespace std;
	if (head == NULL)		return false;
	int i;
	int j;
	double t;
	int cir;

	cout << "\n\n -> 提示信息:共有 " << subnum << " 个项目需要评分:\n";
	for ( fence = head, j = 1; fence != NULL; fence = fence -> next, ++j)
	{
		cout <<  "\n第 " << j << " 个项目: ";
		fence -> ShowName(); 
		cout << " \n";
		for (i = 0; i < num; i++)										// 给num个参赛者评同一项目的分数
		{
			cout << "\n    请评出第 " << i+1 << " 位参赛者的成绩: ";
			do
			{
				cir = 0;
				cin >> t;
				if (!cin)
				{
					cin.clear();
					while(cin.get() != '\n')
						continue;
					cout << " 输入错误,请重新输入此次成绩。";
					cir = 1;
				}
			}while(cir);
			(fence -> score).push_back(t);
		}
		cout << endl;
	}
	return true;
}
	
bool subject::PrintSubject()											// 打印全部科目名称
{
	using std::cout;
	if (head == NULL) return false;
	int i;
	for (fence = head, i = 1; fence != NULL; fence = fence -> next, ++i)
	{
		cout << ' ' <<  i << " : "  << (fence -> SubjectName).c_str() << '\n';
	}
	cout << "\n ------- 显示完毕 ------- \n";
	return true;
}

bool subject::ReadAll(std::vector<double>& temp)					    // 读取全部科目的数据
{
    using namespace std;
    if(head == NULL && 0 == (head -> score).size()) return false;
    int i;
    double t;
    for ( fence = head; fence != NULL; fence = fence -> next)   // 多个科目
    {
        for (i = 0; i < num; i++)								// 给num个参赛者同一科目的分数按顺序存入
        {
            t = (fence -> score[i]);
            temp.push_back(t);
        }
    }
    return true;
}


bool subject::CheckScore()										// 检查该数组中是否已放入数据
{
	if (NULL == head)		return false;
	if (0 == (head -> score.size()))	return false;
	return true;
}

void subject::getSubject(subject * value)						// 复制整个subject类
{
	num = (*value).num;
	subnum = (*value).subnum;

	if (0 == (*value).subnum)
	{
		head = NULL;
		fence = NULL;
		tail = NULL;
		return;
	}
	head = new node ((*value).head -> SubjectName, NULL);
	head -> score = (*value).score;
	fence =	head;
	node * t;
	for (t = ((*value).head -> next); t != NULL; t = t -> next, fence = fence -> next)
	{
		fence -> next = new node(t -> SubjectName, NULL);
		fence -> next -> score = t -> score;
	}
	tail = fence;
	return;
}

// Syndic.cpp -- Syndic中有评分功能,全部评分功能

#include "Syndic.h"

void Syndic::getsname(std::string& t)											// 提取本参赛者的姓名
{
	 t = sname;
	 return;
}

bool Syndic::Syn(std::vector<player> & p, std::vector<double> &tempScoreAll)			// 评分工作
	{
		using std::cout;
		if(p.size() == 0) return false;
		cout << "------------------------- > " <<  sname << " 评委评分中 "
				<< "< ------------------------- ";
		if(EnterSubject())
		{
			ReadAll(tempScoreAll);
		}
		else
		{
			cout << "请使用管理员登陆并输入相关评分项目...";
		}
		return true;
	}

// 放入学生成绩(总评分)
void Syndic::Syn2(int sunum, int plnum, int synum, std::vector<double>& tscore, std::vector<player> & p, std::vector<Syndic> &s)
{
	// tempscore的存放顺序是:评委,参赛者,科目
	// 此函数获得:总分,总平均分,每科平均分,名次
	using namespace std;
	int i;
	int j;
	int k;
	int temppushnum;
	vector <double> singleScore;

	for ( j = 1; j<= plnum; ++j)
	{	// j个参赛者
		for ( k = 1; k <= sunum; ++k)
		{	// k个科目
			temppushnum = 0;
			for ( i = 1; i <= synum; i++)
			{	// 先读取一个参赛者一个科目的全部分数
				// 将全部评委的同一参赛者同一科目成绩放入每一个参赛者每一科目中
				temppushnum = j + ( ( (k - 1) + (sunum * ( i - 1) ) ) * plnum) - 1;
				singleScore.push_back (tscore[temppushnum]);
			}
		p[j - 1].PerIn(k, singleScore);
		singleScore.clear();
		}
	}

	for (i = 0; i < plnum; ++i)					// 全部学生取得各自的总分,平均值
	{
		p[i].AllAccount(synum);
	}

	// 计算名次
	vector <double> tmici;						// 临时存放提取的平均分
	vector <int> rmici(plnum);					// 按顺序储放名次
	double dt;
	double tempmax = 0;
	for (i = 0; i < plnum; i++)					// 提取平均分放入数组
	{
		p[i].GetAc(dt);
		tmici.push_back (dt);
	}
	for (k = 0; k < plnum; k++)
	{
		for (i = 0; i < plnum; i++)				// 找出最大值位置 j
		 {	
			if (tempmax < tmici[i])
			{
				j = i;
				tempmax = tmici[j];
			}
		 } 
	rmici[j] = k + 1;							// 按原数组的顺序存放名次
	tmici[j] = -5000;							// 令最大值变为最小值,使下一次能作比较
	tempmax = 0;
	}
	
	for ( i = 0; i < plnum; i++)				// 放入名次到类中存放进入学生类中
	{
		p[i].PutMingci(rmici[i]);
	}

	return;
}

// user.cpp  -- 管理用户类(功能的实现)

#include "users.h"
#include <cstddef>

bool users::GetTwoNumbers(int & pln, int & ggn)				// 获取参赛者及评委数目
{
	if( 0 == UsersNumber) return false;
	
	size_t t = UsersType.size();
	size_t i;
	pln = 0;
	for (i = 0; i < t; i++)
	{
		if (1 == UsersType[i])
		{
			++pln;
		}
	}
	ggn = 0;
	for (i = 0; i < t; i++)
	{
		if (2 == UsersType[i])
		{
			++ggn;
		}
	}
	return true;
}

bool users::GetOneNumbers(int & adn)						// 获取管理员数目
{
	if( 0 == UsersNumber) return false;
	
	size_t t = UsersType.size();
	size_t i;
	adn = 0;
	for (i = 0; i < t; i++)
	{
		if (3 == UsersType[i])
		{
			++adn;
		}
	}
	return true;
}



void users::GetName(std::string & gn)						// 从类中提取姓名并将其放在gn变量中
{
	gn = UsersName[PositionUsers];
	return;
}


bool users::CheckPassword(const std::string &cp)			// 检查姓名与密码是否对应
{
	if (UsersPassword[PositionUsers] == cp)
		return true;
	return false;
}


bool users::GetType(int >)								// 判断登陆类型(提取类型)
{
	gt = UsersType[PositionUsers];
	return true;
}

bool users::FindName(const std::string &fn)					// 从类中寻找fn用户,若成功则确定用户位置	
{
	int i;
	for (i = 0; i < UsersNumber; i++)
	{
		if ( 0 == strcmp(UsersName[i].c_str() , fn.c_str()))
		{
			PositionUsers = i;
			return true;
		}
	}
	return false;
}

bool users::DelUsers(const std::string& du)					// 删除用户
{
	using namespace std;
	int i;
	int j;
	int k;
	this -> GetOneNumbers (i);
	this -> GetTwoNumbers (j,k);
	bool l = FindName(du);
	if(l) 
	{
	}
	else
	{
		return false;
	}
    int m;
	this -> GetType(m);
	switch (m)
	{
		case 1:	{ j--;	break; }
		case 2:	{ k--;	break; }
		case 3:	{ i--;	break; }
		default: break;
	}
	if(0 == i || 0 == j || 0 == k)
	{
		cout << "\n\n 对不起,不能删除仅剩一个用户的用户组。";
		return false;
	}
	if(l)
	{
		UsersName.erase(UsersName.begin() + PositionUsers);
		UsersPassword.erase(UsersPassword.begin() + PositionUsers);
		UsersType.erase(UsersType.begin() + PositionUsers);
		UsersNumber--;
		return true;
	}
	else
	{
		return false;
	}
}

void users::AppendUser(std::string un, std::string up, int ut)	// 新建用户并将用户放在后面
{
	UsersName.push_back(un);
	UsersPassword.push_back(up);
	UsersType.push_back(ut);
	++UsersNumber;
	return;
}

void users::PrintAll()											// 打印全部用户(区分出参赛者,评委,系统管理员)
{
	using namespace std;
	
	cout << "\n\n-----  参赛者  -----\n\n";
	int i;
	for(i = 0; i < UsersNumber; i++)
	{
		if (1 == UsersType[i])
		{
			cout << UsersName[i] << endl;
		}
	}
	
	cout  << "\n\n" << "-----  评委 -----\n\n";
	for(i = 0; i < UsersNumber; i++)
	{
		if (2 == UsersType[i])
		{
			cout << UsersName[i] << endl;
		}
	}

	cout  << endl << endl << "-----  管理员  -----\n\n";
	for(i = 0; i < UsersNumber; i++)
	{
		if (3 == UsersType[i])
		{
			cout << UsersName[i] << endl;
		}
	}
	cout << endl;
	return;	
}

// 删除原来容器,用现在的用户名重建
void users::CopyNewUsers(std::vector<player>& p, std::vector<Syndic>& s, subject &ss)
{
	int i;
	p.clear();
	s.clear();
	player *pl;
	Syndic *sy;
	std::vector<subject> ts(UsersNumber);
	for (i = 0; i < UsersNumber; ++i)
	{
		ts[i].getSubject (&ss);
		if (1 == UsersType[i])
		{
			pl = new player(UsersName[i], ts[i]);
			p.push_back(*pl);
			delete pl;
		}
		if (2 == UsersType[i])
		{
			sy = new Syndic(UsersName[i], ts[i]);
			s.push_back(*sy);
			delete sy;
		}
	}
	return;
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值