举办歌手大奖赛。
设计歌手类,包括:编号、姓名、各评委打分等属性。
要求功能:
可以打印当前最高、最低分选手属性;
打印已出场人数;
可以按照平均分由高到低打印已出场选手属性;
写出main函数中模拟n个选手出场的过程;
要求:1.使用静态成员。

说明:

  1. 由于不太清楚题意这个“打印当前最高、最低分选手属性”,表意到底是打印某个选手的最高分/最低分 还是打印所有选手中最高/最低的选手的信息,所以全部都写了出来。
  2. 另外,由于 “可以按照平均分由高到低打印已出场选手属性” 这个题目要求,出现在了“要求功能”里面,所以感觉应该是写一个类的函数来打印。而不是在main函数中手动实现。
  3. 开整!

依据要求的功能,定义的类如下:

//Singer.h
#include<string>
#include<vector>
using namespace std;class Singer
{public:Singer(string pName, string pID);   /*构造函数初始化名字,编号等,确定pNext*/float addMarks();                   /*加入各评委分数,计算并存储、返回平均值*/void printMax();                    /*打印某个选手的最高分*/void printMin();                    /*打印某个选手最低分*/static void printPeoNumber();       /*可打印已出场人数*/static void printAllMax();          /*打印最高分的选手的属性*/static void printAllMin();          /*打印最低分选手的属性*/static void orderPrint();           /*按平均分大小打印选手属性*/~Singer();private:static int nuOfPeople;               /*记录出场的人数*/static Singer* pFirst;               /*整个类的头指针*/Singer* pNext;                  /*指向下一个节点,链表*/string name;                       /*储存名字*/string ID;                          /*储存编号*/vector<float> marks;                  /*用容器vector,动态化存储各评委的分数*/int order;                         /*记录出场顺序而已,后面为用到*/float average;                      /*储存选手的平均分*
};

1.为实现属于整个类的——“按平均分从大到小,打印选手属性”的功能,首先想到的还是链表,当每声明一个新的该类对象的时候,将新声明的这个对象自动变为链表的节点。

2.与上次MyVector类练习,应用的链表不同之处在于:上次链表出现是在,每一个MyVector类的对象的成员中,而这次我们是要将声明的对象作为节点。

3.为动态存储评委分数,采用了vector容器,之后运用的vector的方法有:

方法 作用
v.size() 返回容器中实际数据的个数
v.empty() 判断容器是否为空,空为true
c.push_back(elem) 在尾部加入一个数据

在 Singer.cpp 文件中各函数实现如下:

//Singer.cpp  文件中引入的头文件
#include<iostream>
#include "Singer.h"
using namespace std;
/*构造函数初始化名字,编号等,确定pNext*/
Singer::Singer(string pName,string pID)
{nuOfPeople++;name = pName;ID = pID;order = nuOfPeople;average = 0;pNext = pFirst;        //尾插法创建链表
pFirst = this;
}
/*加入各评委分数,计算并存储、返回平均值*/
float Singer::addMarks()
{static int number = 0;                   /*利用静态局部变量生命期直到程序结束的特性,只在第一次调用addMarks函数时输入评委个数*/if (number == 0) {                        /*大致约等于第一次执行函数时 才输入评委人数 (ˉ▽ˉ;)  */cout << "请输入评委位数:";cin >> number;}cout << "请开始输入" << name << "的分数:" << endl;for (int i = 0; i < number; i++) {float mark;cin >> mark;marks.push_back(mark);}cout << "--------------------------------------------------" << endl;  //分隔开每次输入分数,在控制台显示更分明float sum = 0;                           /*输入分数后直接计算平均分*/for (int i = 0; i < marks.size(); i++)sum += marks[i];average = sum / marks.size();return average;
}*可打印已出场人数*/
void Singer::printPeoNumber()
{cout << "出场人数是:" << nuOfPeople<<endl;
}*打印某个选手的最高分*/
void Singer::printMax()
{if (marks.empty())cout << "Empty!" << endl;else {float max = marks[0];for (int i = 0; i < marks.size(); i++)   / /遍历所有分数找出最高分if (marks[i] > max)max = marks[i];cout << "选手"<<name<<"的最高分为:" << max << endl;}
}/*打印某个选手最低分*/
void Singer::printMin()
{if (marks.empty())                          //先判断有没有分cout << "Empty" << endl;else {float min = marks[0];for (int i = 0; i < marks.size(); i++)     //便历所有分数找出最低分if (marks[i] <min)min = marks[i];cout << "选手"<<name<<"的最低分为:" << min << endl;}
}/*打印最高分的选手的属性*/
void Singer::printAllMax()
{if (pFirst == nullptr) {         //先判断链表有没有节点,pFirst是不是为空,避免对空指针引用(主要是为了打消编译器的警告⚠+▽+)。cout << "链表为空!" << endl;return;}float max = pFirst->average;Singer* pMax=pFirst;                             //用于标记最大值节点     for (Singer* pS = pFirst;pS; pS = pS->pNext) {  //遍历链表找出最大值if (pS->average > max) {max = pS->average;pMax = pS;}}for (Singer* pSame=pFirst;pSame;pSame=pSame->pNext) {     // 遍历一遍防止有分数相同的情况出现if(pSame->average==pMax->average){cout << "当前最高分选手姓名" << pSame->name << "   编号" << pSame->ID << endl;cout << "各评委打分为:" << endl;for (int i = 0; i < pSame->marks.size(); i++)cout << pSame->marks[i] << "  ";cout << endl << endl;     // 为了输出好看}}cout << "——————————————————————————————————————————————————————————" << endl;
}/*打印最低分选手的属性*/
void Singer::printAllMin()
{ if (pFirst == nullptr) {cout << "链表为空!" << endl;return;}for (Singer* pS = pFirst; pS; pS = pS->pNext) {           //遍历找出最大值if (pS->average < min) {min = pS->average;pMin = pS;}}for (Singer* pSame = pFirst; pSame; pSame = pSame->pNext) { //遍历一遍,防止有分数相同的情况出现if (pSame->average==pMin->average) {cout << "当前最低分选手姓名" << pSame->name << "   编号" << pSame->ID << endl;cout << "各评委打分为:" << endl;for (int i = 0; i < pSame->marks.size(); i++)cout << pSame->marks[i] << "  ";cout << endl << endl;      //为了输出好看}}
}/*按平均分大小打印选手属性*/
void Singer::orderPrint()
{if (pFirst == nullptr) {cout << "链表为空!" << endl;return;}static float premax = 1000;      //设置为1000主要是想给他一个十分大的初始值利用静态局部变量只初始化一次,生命期直到程序结束的特性,记录找出的以前的的最大值,int i = 0;        //i记录打印了的个数while(i!=nuOfPeople) {           //记录输出的次数float max = 0;Singer* pMax = nullptr;for (Singer* pS = pFirst; pS; pS = pS->pNext) {     //遍历找出单次最大值,注意每次找出的最大值要小于上一次if ((pS->average > max)&&(pS->average<premax)) {max = pS->average;pMax = pS;}}int  rank = i;                          //引入为解决每次可能有相同分数出现的排名问题for (Singer* pSame = pFirst; pSame; pSame = pSame->pNext) { //遍历一次防止出现两个平均值相同的情况,同样小心空链表时候的对nullptr引用if (pMax->average == pSame->average) {       //按格式打印i++;                            //更新打印次数cout << "排名:" << rank+1<< "    姓名" << pSame->name << "   编号" << pSame->ID << endl;cout << "各评委打分为:" << endl;for (int k = 0; k < pSame->marks.size(); k++)cout << pSame->marks[k] << "  ";cout << endl;cout << "均分为:" << pSame->average << endl;cout << "______________________________________________" << endl;     //分隔符}} /*for*/premax = max;   /*记录上一次的最大值,下一次的最大值要小于这个值*/}/*while*/premax = 1000.0;        由于静态局部变量值初始化一次 重置premax防止当在程序中第二次调用函数时 比大小 出现问题
}/*析构,减去人数*/
Singer::~Singer()
{nuOfPeople--;  if (pFirst == this)                    //当删除的处于头部的对象的时候{pFirst = pNext;    return;}for (Singer* pS = pFirst; pS; pS = pS->pNext) //当删除的对象位于链表中间的时候if (pS->pNext == this){pS->pNext = pNext;return;}
}

对于析构函数的说明:

把析构函数写成这样,主要是为了避免当创建的对象作用域为块作用域的时候,出了块,对象被销毁,导致链表断裂,所以在对象被销毁的时候,也应该调整链表。

最后测试类的功能,模拟歌手出场顺序:

//mian.cpp
#include<iostream>
#include<string>
#include"Singer.h"
using namespace std;int Singer::nuOfPeople = 0;
Singer* Singer::pFirst = nullptr;int main()
{/*模拟选手出场顺序*/Singer a("zhang","12000"), b("sun", "12001"), c("li", "12002"), d("zhou", "12003"),e("kou","12004");a.addMarks();b.addMarks();c.addMarks();d.addMarks();e.addMarks();cout << endl;Singer::printPeoNumber();cout << endl;d.printMax();d.printMin();cout << endl;Singer::orderPrint();Singer::printAllMax();Singer::printAllMin();return 0;
}

注意事项:
类的静态成员一定要记住初始化,在初始化的时候才能分配空间,不然过不了编译器:
上述main函数执行结果如下:



测试使用的数据有:
5
1 2 3 4 5
9 9 9 9 9
9 9 9 9 9
1 1 1 1 1
1 1 1 1 1
5
1 2 3 4 5
8 2 6 4 2
8 3 4 7 5
3 4 6 8 2
1 2 4 9 8
5
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1

总结:
在一些打印数据的函数,比如printAllMax( )、printAllMin()、orderPrint(),打印部分本可以写成一个函数来复用,以此减少代码量,使程序更简洁。由于想偷懒就不重构了,hhh。
就这样,给大伙儿整点儿烂活。

C++(学习) —— Vector容器,类的静态成员的使用练习(Singer类)相关推荐

  1. PHP 类的静态成员变量和普通成员变量对比

    有很多人可能弄不清楚,在PHP中类的静态成员变量和普通成员变量有什么区别? 1.类的静态方法只能访问静态成员变量,而不能访问非静态成员变量 2.静态成员变量不需要实例化就能访问,且访问速度快一些 3. ...

  2. 学习笔记:C++初阶【C++入门、类和对象、C/C++内存管理、模板初阶、STL简介、string、vector、list、stack、queueu、模板进阶、C++的IO流】

    文章目录 前言 一.C++入门 1. C++关键字 2.命名空间 2.1 C语言缺点之一,没办法很好地解决命名冲突问题 2.2 C++提出了一个新语法--命名空间 2.2.1 命名空间概念 2.2.2 ...

  3. C++vector容器学习

    发现一篇好文:比较详细地介绍了vector容器的知识点 https://blog.csdn.net/fanyun_01/article/details/56842637 vector<vecto ...

  4. ACM学习历程—BestCoder 2015百度之星资格赛1002 列变位法解密(vector容器)

    Problem Description 列变位法是古典密码算法中变位加密的一种方法,具体过程如下 将明文字符分割成个数固定的分组(如5个一组,5即为密钥),按一组一行的次序整齐排列,最后不足一组不放置 ...

  5. java中vector容器,vector向量容器(常用的使用方法总结)

    关于STL中vector容器的学习,编译运行后边看代码,边看执行结果效果更佳,还是想说看别人的代码一百遍,不如自己动手写一遍. vector向量容器不但能像数组一样对元素进行随机访问,还能随时在尾部插 ...

  6. C++vector容器

    文章目录 一.容器的定义 二.容器的使用 1.存放整数 2.存放字符串 3.存放结构体 4.存放类 三.其它成员函数 1.定位的函数 2.增加元素的函数 3.删除元素的函数 4.判断容器的大小 四.容 ...

  7. C++语言vector容器介绍和示例

    之前我们在声明数组的时候,采用的是datatype  array[len]的形式,数组在分配之后,不能调整大小,删除和插入数据时操作十分的繁琐,虽然可以采用链表,但是链表的操作更麻烦,我喜欢简单的方法 ...

  8. STL之Vector容器

    一.初识Vector容器 学习目标1:学会往Vector容器中添加内置数据类型和Vector容器的遍历 示例: #include "iostream" #include <v ...

  9. STL学习--vector的学习

    (一):学习目标: 1:模板,包括函数模板和类模板 2:容器及其分类,以容器中的数据结构 3:容器vector和迭代器的具体用法 (二):学习 1:函数模板 /*** 学习模板函数*/ int max ...

最新文章

  1. 剑指offer: 斐波那契数列 python 实现
  2. Outlook中删除重复的邮件
  3. python版本升级后编译_python学习笔记(7)--python版本升级
  4. java中的foreach语句
  5. oracle的监听器是什么,Oracle监听器,让你监听想要的东东
  6. 利用 Domino V8 新特性开发 Mashup 应用(转载)
  7. 12 个有效的提高编程技能的方法
  8. java 上界和下界,Java 泛型上下界(上下限)
  9. 第三章 Goroutine调度策略(16)
  10. 续订Exchange 2010 Edge SMTP证书
  11. AD笔记4-元件封装库绘制
  12. 用Java实现md5加密
  13. 无线路由器破解教程-CDlinux(by 星空武哥)
  14. Winform调用风云二号卫星云图
  15. Unity DOTS在hybird renderer v2 中rendermesh不显示
  16. 如何正确利用肢体语言表达自己
  17. POJ-1637 混合图欧拉回路-网络流求解
  18. 题解 - [POI2008]KUP-Plot purchase
  19. 単語境界/非単語境界(¥b, ¥B)
  20. pandas排序csv文件并且按时间分类 python学习 pandas应用

热门文章

  1. 小猪佩奇用计算机怎么弹,小猪佩奇第一季学习笔记计算机软件及应用IT计算机专业资料-小猪.pdf...
  2. 用java实现的文本编辑器可以媲美windows自带的编辑器吗?(功能全,超详细)
  3. Hyperledger/cello实际测试——SDK
  4. 小U管家如何加入联盟?
  5. 2015062402 - 求伯君
  6. excel百万数据如何导入导出
  7. 根据Excel表头的位置数转化为对应列名称
  8. 2017全年Java书单整理
  9. batT脚本如何自动执行 adb shell 以后的命令(android抓包)
  10. sina获取股票代码java