c++学习笔记(十二、综合案例)

这个综合案例也是来源黑马程序员的,总觉得学了C++之后,不写点东西,都有点心虚,所以写了一下这个东西,希望不要嫌弃。

12.1 学校演讲比赛介绍

在这里插入图片描述
在这里插入图片描述

12.2 需求分析

在这里插入图片描述

12.3 实现思路

  1. 使用一个map容器,存储选手信息,map容器的key为uID(参赛编号),值为Player(选手对象),可以通过uID找到Playe的对象。
  2. 创建一个容器vector v;作为统一摇号的容器,把需要抽签的时候的uID都集中到这个容器中,然后进行抽签。
  3. 还创建了分组容器vector v1[4];因为需要4组,所以创建了一个容器数组,这样理解起来比较简单,先通过容器v抽签,抽完签之后,从头到尾存储到v1分组的4个容器中,然后每一组进行比赛,评分。
  4. 评分的时候,因为有10个评委,需要去掉最高分和最低分,这里使用了deque容器,这个容器就是操作头尾比较快速,刚好排完序之后,去掉头尾刚好是最高分和最低分,剩下的求平均。
  5. 评分的结果需要排序,第一是按最后算出平均分排序,第二如果平均分一样的话,按参赛编号升序排,这个确实让我纠结了很久,不过百度了一些找到了一篇讲:
    对于multimap相同的key是value的排序
    参考这篇博客:https://blog.csdn.net/weixin_44543224/article/details/92714364
    所以就参考了这个写了一个出来,这样就符合题目的意思了。
  6. 一轮比赛完成之后,下一轮之前,还需要再次进行抽签,所以把之前的分组v1里面的数组又全部拷贝到抽签容器v中,然后进行抽签,抽完签,再次分配到各自的分组中,再次进行评分。

12.4 实现代码

#include <iostream>
#include <string>
#include <unordered_map>
#include <map>
#include <vector>
#include <ctime>
#include <algorithm>
#include <deque>
#include <numeric>

using namespace std;  //老是不记得命名空间

#define random(x) rand()%(x)
#define random_2(a, b) ((rand() % (b-a)) + (a))

class Person
{
public:
    string name;
    int age;

    Person(string name, int age) : name(name), age(age) {
        
    }

    Person(char name, int age) {
        this->name = name;
        this->age = age;
    }

};

class Player : public Person
{
public:
    int grade;
    int uID;        //参赛的编号

    Player(string name, int age, int uID) : Person(name, age), uID(uID) {
        grade = 0;
    }

    Player(char name, int age, int uID) : Person(name, age), uID(uID) {
        grade = 0;
    }

    friend ostream& operator<<(ostream& os, Player& p);
};

ostream& operator<<(ostream& os, Player& p)
{
    os << " 名字 " << p.name << " 年龄 " << p.age << " 编号 " << p.uID << " 成绩 " << p.grade << endl;
    return os;
}


//评分
void player_score(vector<int>& v, map<int, Player>& m) {
    multimap<int, int> m_map;   //这个是可以自动排序的map, 第一个是成绩,第二个是uID, 第三个是排序greater<int>大到小
    multimap<int, int, greater<int>> u_map;    //这个是为了排uID的
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        deque<int> grade;
        for(int i=0; i<10; i++) {   //10个评委
            grade.push_back(random_2(20, 60));
        }

        //去掉最高分,和最低分
        sort(grade.begin(), grade.end());
        grade.front();
        grade.back();

        //算出平均值
        int sum = accumulate(grade.begin(), grade.end(), 0);
        map<int, Player>::iterator ret = m.find(*it);
        if(ret == m.end())
            throw out_of_range("超出范围");
        
        ret->second.grade = sum / 8;

        m_map.insert(make_pair(*it, ret->second.grade));    //这里要先反过来
    }

    //这个是对uID也进行排序,就是再次对map排序
    for(auto it1 = m_map.begin(); it1!=m_map.end(); it1++)   
    {
        u_map.insert(pair<int,int>(it1->second, it1->first));		
    }

    //保存到v[i]
    v.clear();
    int count = 0;
    for(multimap<int, int>::iterator it = u_map.begin(); it != u_map.end(); it++) {
        count++;
        if(count <= 3) {
            v.push_back(it->second);
        }
    }
}

//打印晋级选手
void print_promotion(vector<int>& v, map<int, Player>& m) 
{
    //sort(v.begin(), v.end());   //先把参数编号按升序排列
    for(vector<int>::iterator it = v.begin(); it != v.end(); it++) {
        map<int, Player>::iterator ret = m.find(*it);
        //cout << *it << endl;
        if(ret == m.end())
            throw out_of_range("超出范围");
        
        cout << ret->second;
    }
}

//抽签和分组 v要进行抽签的序列,v1是分组的序列, num是几个分组,size是一个分组有几个元素
void draw_group(vector<int>&v, vector<int> v1[], int num, int size)
{
    static int first = 0;
    vector<int>::iterator it;
    if(first == 0) {
        first = 1;
    } else if(first == 1) {
        v.clear();
        v.resize(num*size);
        it = v.begin();
        for(int i=0; i<num*2; i++,it+=size/2) {
            copy(v1[i].begin(), v1[i].end(), it);        
        }
    }

    //抽签
    random_shuffle(v.begin(), v.end());
    //分组
    it = v.begin();
    for(int i=0; i<num; i++,it=it+size) {
        v1[i].resize(size);
        copy(it, it+size, v1[i].begin());
    }
}


int main(int argc, char **argv) {

    cout << "hello c++" << endl;

    //创建选手
    map<int, Player> p_map;
    vector<int> v;
    vector<int> v1[4];
    char name[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    srand(time(NULL));

    for(int i = 1; i<=24; i++) {
        p_map.insert(pair<int, Player>(i,  Player(name[i], random_2(20, 60), i)));
        v.push_back(i);
    }

    for(map<int, Player>::iterator it = p_map.begin(); it != p_map.end(); it++) {
        cout << it->first << "  " << it->second;
    }

    int num = 24/6;
    for(int i=0; i<3; i++) {
        //创建分组,并且抽签
        draw_group(v, v1, num, 6);

        //开始演讲,并且评分
        cout << "==============================" << endl;
        for(int i=0; i<num; i++) {
            player_score(v1[i], p_map);
        }

        //打印这一轮晋级的选手
        for(int i=0; i<num; i++) {
            print_promotion(v1[i], p_map);
            cout << "==============================" << endl;
        }

        num /= 2;
    }
    
    return 0;
}

用c++写了这段程序,相比于c语言来说,变化确实有点大,c++容器和算法都写好了,需要用就申请,然后调用就可以了,相对于c还需要自己写数据结构和基本的算法,确实提高了不少的效率,还有就是写c++的时候好像没怎么关注内存,可能是新手还对内存深入不了,对c的话,老是扣内存。
不知道以后还要不要学习其他语言,虽然语言只是工具,但是这个工具如果好用的话,还是需要学的。
且学且珍惜,共勉。

发布了32 篇原创文章 · 获赞 26 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/C1033177205/article/details/104190276