简单实现---基于STL的演讲比赛流程管理系统(C++实现)

前言       

       事先声明本文章中编写的代码仅用于学习算法思想和编写基础形式使用,并未进行太多的代码优化,因此,若需要对代码进行优化以及异常处理的小伙伴们,可自行添加相关操作,谢谢!

一、题目描述

比赛规则
  
 1 学校举行一场演讲比赛,共有12个人参加。比赛共两轮,第一轮为淘汰赛,第二轮为决赛
    2 每名选手都有对应的编号,如10001~10012
    3 比赛方式:分组比赛,每组6个人
    4 第一轮分为两个小组,整体按照选手编号进行抽签后顺序演讲
    5 十个评委分别给每名选手打分,去除最高分和最低分,求的平均分为本轮选手的成绩
    6 当小组演讲完后,淘汰组内排名最后的三个选手,前三名晋级,进入下一轮的比赛
    7 第二轮为决赛,前三名胜出,每轮比赛过后需要显示晋级选手的信息

二、需求分析

一、问题概述

本系统设计旨在模拟学校举办的演讲比赛流程,实现一个基于C++STL(标准模板库)的演讲比赛流程管理系统。系统需要处理包括选手编号、分组、评分、淘汰和晋级在内的各个环节,并能够在比赛过程中显示晋级选手的信息。

二、系统要求与限制条件

  1. 选手信息:系统需要管理12名选手的信息,包括编号(10001~10012)。
  2. 比赛轮次:比赛分为两轮,第一轮为淘汰赛,第二轮为决赛。
  3. 分组规则:第一轮需要将12名选手分成两组,每组6人。
  4. 评分机制:每个选手演讲后,由十个评委打分,系统需要去除最高分和最低分后计算平均分作为选手成绩。
  5. 淘汰与晋级:每组淘汰成绩排名最后的三个选手,晋级前三名进入下一轮。
  6. 信息显示:系统需要在每轮比赛后显示晋级选手的信息。
  7. 技术限制:使用C++和STL实现,避免使用非标准库。

三、系统目标

  1. 实现选手信息管理:系统应能够存储和检索选手的编号信息。
  2. 实现分组与抽签:系统应能自动将选手分成两组,并随机决定演讲顺序。
  3. 实现评分机制:系统应能接收评委的评分,并自动计算选手的最终成绩。
  4. 实现淘汰与晋级逻辑:系统应能根据选手成绩自动淘汰和晋级选手。
  5. 实现信息显示功能:系统应能在每轮比赛后显示晋级选手的编号和成绩。
  6. 实现最终信息存取功能:系统应能在每届比赛后保存该节比赛记录,并显示往届记录。
  7. 代码可维护性:系统应具有良好的代码结构,方便后续维护和扩展。

三、总体设计

一、设计目标分析

       本次课程设计的目标是开发一个基于C++STL的演讲比赛流程管理系统。该系统需要模拟学校演讲比赛的流程,包括选手信息管理、分组抽签、评分计算、淘汰晋级以及信息显示等功能。

二、基本思路

  1. 数据结构定义
    • 使用vector<int>来存储选手编号,方便遍历和操作。
    • 使用map<int, Speaker>来存储每个选手的编号、姓名以及评分。
    • 定义一个选手类Speaker来封装选手的姓名和成绩,方便后续排序和筛选。
    • 使用int的 m_idenx 来记录比赛的轮次。
  2. 分组与抽签
    • 自动模拟12名选手,命名为“选手A~L”,并依次给出编号,并给出默认成绩0。
    • 使用随机打乱的方式对选手编号排序,确定选手比赛顺序。
    • 然后按照抽签后的顺序显示每轮比赛的选手编号。
    • 根据排序后的编号将选手分成两组。
  3. 评分机制
    • 为每轮比赛选手创建一个临时容器vector,用于遍历选手编号进行打分,其中采用随机数器模拟打分。
    • 然后为每个选手创建一个评分deque<double>,用于存储各个评委的评分。
    • 去除最高分和最低分后计算平均分,作为选手的最终成绩。
  4. 淘汰晋级
    • 根据选手的最终成绩进行排序。
    • 淘汰每组后三名选手,晋级前三名进入下一轮。
  5. 信息显示
    • 在每轮比赛后,显示晋级选手的编号和成绩。
  6. 记录存取
    • 在每届比赛完后,将最终获胜选手的编号和成绩以文件的形式保存。
    • 且想要查看时,也可调用文件进行查看往届比赛记录。

三、遇到的问题和解决方法

  1. 随机数生成
    • 问题:如何确保模拟打分的分数的随机性。
    • 解决方法:使用<stdlib.h>头文件中的随机数生成器,并引用<ctime>库,设置随机数种子。 
  2. 乱序模拟随机
    • 问题:如何打乱顺序模拟随机情况以实现抽签功能。
    • 解决方法:使用C++的STL中的algorithm头文件,调用”洗牌”函数实现打乱选手的编号实现抽签的效果。
  3. 评分计算
    • 问题:如何高效地去除最高分和最低分,并求和接着计算平均分。
    • 解决方法:使用STL中的map实现对分数的自动排序,利用其pop()和front()函数去除最高分和最低分,然后使用algorithm头文件中的accumulate算法求和,最后计算剩余评分的平均值。
  4. 选手排序
    • 问题:如何根据选手成绩进行排序。
    • 解决方法:使用STL中的map/multimap存放选手信息,成绩作为键值,可根据成绩高低对选手进行自动排序。
  5. 信息显示
    • 问题:如何优雅地显示晋级选手的信息。
    • 解决方法:使用C++的cout进行输出,可以格式化输出信息,如使用制表符或空格对齐。
  6. 记录存取
    • 问题:如何用文件保存最终获胜者信息。
    • 解决方法:使用C++中的文件流fstream创建一个文件,将信息输入文件中保存,后续仍可查看文件信息。

四、完成本次设计的完整过程

  1. 需求分析:明确系统需求和限制条件,分析需要实现的功能。
  2. 总体设计:确定基本思路,规划程序结构,设计数据结构和算法。
  3. 详细设计:编写代码实现各个功能模块,包括选手管理、分组抽签、评分计算、淘汰晋级和信息显示等。
  4. 代码实现:按照详细设计编写代码,并进行单元测试,确保每个模块的正确性。
  5. 系统集成:将各个模块集成到系统中,进行整体测试,确保系统能够正常运行。
  6. 编写文档:编写设计文档,介绍系统的开发过程及相关功能。

五、功能关系图或主要框图

    1.主要组成模块和各个模块之间的调用关系图

 

     其中,在对象被创建并调用的时候,演讲选手的编号、姓名、成绩等信息均被创建且初始化完毕。

      2. 其中重点功能实现在于开始比赛功能模块,其功能结构图如下

       其中,为方便代码编写,我们内部实现先抽签乱序,再分成6人组,该实现步 骤不影响控制台上展示的实际比赛流程,便于降低代码出错率。

三、详细设计

      本程序基于vs2022编译环境,使用的语言是C++,主要运用其中的STL库进行编写。

      本次程序中创建了一个大的管理类,以及一个选手类。其中,管理类中包含了众多功能函数以及一些操作的数据,选手类中包括了选手的姓名和成绩。下面我来详细介绍一下程序中用到的头文件、变量属性、功能函数及其参数和返回值等。

1、需要包含的头文件如下

#include<iostream> //C++标准输入输出流
#include<string>   //字符串类
#include<vector>   //vector容器
#include<map>      //map/multimap容器
#include<deque>    //deque容器
#include<numeric>  //调用算法
#include<algorithm>   //调用algorithm算法
#include<ctime>     //调用随机数种子
#include<fstream>   //调用文件流

 2、创建的类和成员属性以及函数

  2.1管理类 SpeechManage

   管理类下:

成员函数如下
SpeechManage();
void show_Manu();
void initSpeech();
void createSpeaker();
void speakerDraw();
void speechContest();
void showScore();
void saveRecord();
void loadRecord();
void startSpeech();
void showRecord();
void clearFile();
void exitSystem();
~SpeechManage();
成员属性如下
vector<int> v1;  
vector<int> v2; 
vector<int> vVictor;  
map<int, Speaker> m_Speaker; 
int m_idenx;   
map<int, vector<string>> m_Record;
bool fileEmpty;

  2.2 选手类 Speaker

    选手类下:

成员函数 无
成员属性如下
    string m_Name;  //姓名
    double m_Score[2];   //两轮成绩

3、涉及的功能函数的参数、功能以及返回值

  1. 析构函数SpeechManage();
  2. 创建菜单showManu();
  3. 初始化成员属性initSpeech();
  4. 创建选手createSpeaker();
  5. 抽签speakerDraw();
  6. 正式比赛模拟speechContest();
  7. 显示晋级选手信息showScore();
  8. 保存记录saveRecord();
  9. 读取记录loadRecord();
  10. 开始比赛startSpeech();
  11. 展示往届记录showRecord();
  12. 清空文件clearFile();
  13. 退出程序exitSystem();
  14. 析构函数~SpeechManage();
  15. 本次程序所涉及函数均为无参无返回值函数。

  16. 其中,为保证系统运行时控制台显示的简洁性和对用户的友好性,我们调用了两个系统函数对界面进行适当的清屏和暂停函数,对功能调用前后作适当的暂停和清屏操作,即:

         清屏->system(“cls”);

         暂停->system(“pause”);

4、各个模块间调用关系以及数据存储格式说明


1)模块间调用关系

       在本次设计的系统中,采用C++中的类与对象的方式控制并操作各个数据和模块,模块间的调用关系主要体现在主菜单、初始化、开始比赛(分组抽签、评分计算、晋级信息显示、记录保存)和往届记录展示等核心功能。下面,我来大致介绍一些他们之间的调用关系。

       开始比赛、查看往届记录、清空记录和退出系统等主要模块由主调函数main函数调用,各个小模块将在主要模块中被嵌套调用。下面再说说其中复杂部分的调用关系。

       初始化、创建选手、加载数据记录和读取数据记录等成员函数将被构造函数调用,抽签、正式比赛、显示晋级选手信息和保存记录等函数将被开始比赛函数调用。

2)数据存储格式说明

1、选手编号存储:

    格式:使用vector<int>存储选手编号,每个元素代表一个选手的编号。

    用途:初始化时加载选手编号,后续传递给分组抽签和比赛模块进行处理。

2、评委评分存储:

    格式:使用deque<double>存储每个选手的评委评分。

    用途:在评分时接收并存储评委对选手的评分,用于后续计算选手成绩。

3、选手成绩与编号关联存储:

    格式:使用map<int,Speaker>、map<int, vector<string>>以及自定义的类来存储选手的编号和成绩。

    用途:在比赛模块中存储每位选手的编号和成绩,便于后续根据成绩进行排序、晋级相关操作和记录存储和显示操作。

4、晋级选手存储:

    格式:使用vector<int>存储晋级选手的编号。

    用途:在淘汰晋级模块中存储每轮比赛的晋级选手编号,便于后续轮次的比赛或最终结果显示。

5、比赛轮次记录:

    格式:使用整型变量m_Index存储比赛轮次。

    用途:在比赛过程中记录比赛进行的轮次,便于在正确的轮次进行相关操作。

       在实际实现中,可以根据具体需求和性能考虑选择更合适的数据结构和存储方式。同时,为了保持数据的一致性和完整性,在模块间传递数据时需要注意数据的正确性和有效性。

5、各个模块的调用方式

       为使代码结构清晰,可读性良好,本程序采用了分文件处理的方式进行代码编写,其中创建了管理类和选手类的头文件。我们将在头文件中对各个成员函数及属性进行声明,在对应.cpp文件中进行定义,在主调函数main函数中创建一个管理对象并利用while循环和Switch语句的方式对各个模块实现有向调用。

5.1各项功能的代码实现

5.1.1 创建管理类

class SpeechManage
{
public:
	SpeechManage();
	void show_Manu();
	void initSpeech();
	void createSpeaker();
	void speakerDraw();
	void speechContest();
	void showScore();
	void saveRecord();
	void loadRecord();
	bool fileEmpty;
	map<int, vector<string>> m_Record;
	void startSpeech();
	void showRecord();
	void clearFile();
	void exitSystem();
	~SpeechManage();
	vector<int> v1; 
	vector<int> v2;  
	vector<int> vVictor;  
	map<int, Speaker> m_Speaker;  
	int m_idenx; 
};

5.1.2 创建选手类

class Speaker
{
public:
	string m_Name;   
	double m_Score[2]; 
};

5.1.3主调函数框架搭建

    创建一个管理对象,再使用Switch语句按照用户选择调用相关成员函数实现相关功能。

int main()
{
	SpeechManage sm;
	int choice;
	while (1)
	{
		sm.show_Manu();
		cout << "请输出你的选择:" << endl;
		cin >> choice;
		switch (choice)
		{
			case 1:			//比赛开始
				break;
			case 2:			//查看往届信息
				break;
			case 3:			//清空比赛信息
				break;
			case 0:			//退出系统程序
				break;
			default:
				system("cls");
		}
	}
	system("pause");
	return 0;
}

5.1.4  管理类成员函数实现(speechProcessManagement.cpp中实现)

     因为是分文件处理,所以所有头文件中的成员函数都会附带作用域SpeechManage::

1)创建菜单void show_Manu()

      按照自己喜欢的设计方式设计菜单样式,直接打印即可。

void SpeechManage::show_Manu()
{
	cout << "***************************************" << endl;
	cout << "*********** 欢迎参加演讲比赛 **********" << endl;
	cout << "*********** 1、开始演讲比赛 ***********" << endl;
	cout << "*********** 2、查看往届记录 ***********" << endl;
	cout << "*********** 3、清空比赛记录 ***********" << endl;
	cout << "*********** 0、退出比赛程序 ***********" << endl;
	cout << "***************************************" << endl;
}

2)赛前初始化信息 void initSpeech()

       本届比赛开始前,应将所有比赛相关信息进行初始化操作,包括存放编号处、记录选手信息处以及记录比赛轮次处,且为避免往届记录没有及时更新,我们应在每次比赛前进行清空操作,然后后续重新增加新总记录(因为记录的从保存记录的文件中读取得到)。

void SpeechManage::initSpeech()
{
	this->v1.clear();
	this->v2.clear();
	this->vVictor.clear();
	this->m_Speaker.clear();
	//初始化比赛轮次
	this->m_idenx = 1;
	//初始化往届记录,避免比赛完后每一次查看均为同样的记录
	this->m_Record.clear();
}

3)创建选手 void createSpeaker()

       按个人喜好给定11名选手名称,然后创建选手对象存放相关最初数据,接着将12名选手编号存放至第一轮比赛选手编号存放处,并记录比赛前的选手参赛信息。

//创建选手
void SpeechManage::createSpeaker()
{
	//创建12名选手
	string nameSeed = "ABCDEFGHIJKL";
	for (int i = 0; i < nameSeed.size(); i++)
	{
		string name = "选手";
		name += nameSeed[i];

		Speaker sp;
		sp.m_Name = name;

		//初始化选手成绩
		for (int j = 0; j < 2; j++)
		{
			sp.m_Score[j] = 0;
		}
		//把编号存放至v1容器
		this->v1.push_back(i + 10001);
		//存放选手信息 编号+姓名分数
		this->m_Speaker.insert(make_pair(i + 10001, sp));
	}

}

4)构造函数进行整个比赛的初始化 SpeechManage()

SpeechManage::SpeechManage()
{
	//初始化属性
	this->initSpeech();
	//创建选手
	this->createSpeaker();
	//读取数据
	this->loadRecord();
}

5)赛前抽签 void speakerDraw()

       因为比赛分两轮,所以首先用条件控制轮次,然后对选手编号进行打乱模拟抽签,最后显示抽签后的选手编号顺序。

void SpeechManage::speakerDraw()
{
	cout << "第 <<" << this->m_idenx << ">> 轮比赛选手正在抽签..." << endl;
	cout << "----------------------------------" << endl;
	cout << "选手演讲顺序如下:" << endl;
	if (this->m_idenx == 1)
	{
		random_shuffle(v1.begin(), v1.end());  //随机打乱表示12人随机抽取,以便后面随机分组
		for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
	else
	{
		random_shuffle(v2.begin(), v2.end());
		for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
	cout << "----------------------------------" << endl;
	//为用户给出查看抽签情况提供暂停
	system("pause");
}

6)正式比赛 void speechContest()

       打印轮次表示该场轮次,接着创建临时容器存放比赛选手编号,然后开始比赛用随机数模拟10名评委打分,接着求和掐头去尾取平均存放至选手成绩信息记录处,然后再创建一个临时分组容器,每六名存放一次选手成绩和编号并排好序,再选出前三存放至该轮晋级编号存放处,并且打印晋级选手编号。(最后注意清空临时分组容器避免下次使用时信息重复)


void SpeechManage::speechContest()
{
	cout << "--------第" << this->m_idenx << "轮比赛正式开始--------" << endl;

	//准备一个临时容器,存放小组参赛选手,num用作记录小组数
	int num = 0;
	multimap<double, int, greater<int>> groupSpeaker;

	//创建存放比赛选手编号的容器
	vector<int> v_Src;
	if (this->m_idenx == 1)
	{
		v_Src = v1;
	}
	else
	{
		v_Src = v2;
	}

	//遍历所有参赛选手
	for (vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++)
	{
		num++;
		//参赛选手开始演讲,十位评委开始打分
		deque<double> d;
		for (int i = 0; i < 10; i++)
		{
			
			//分数
			double score = (rand() % 401 + 600) / 10.f;
			d.push_back(score);
		}

		sort(d.begin(), d.end());
		//去除最高分和最低分
		d.pop_front();
		d.pop_back();
		//求和
		double sum = accumulate(d.begin(), d.end(), 0.0f);   //0.0f ?
		//取平均值
		double avr = sum / (double)d.size();
		
		测试
		//cout << "编号:" << *it << "  姓名:" << this->m_Speaker[*it].m_Name
		//	<< "  成绩:" << avr << endl;

		//将分数存放至m_Speaker
		this->m_Speaker[*it].m_Score[this->m_idenx - 1] = avr;

		//利用容器存放临时各组的选手,并记录第几组
		groupSpeaker.insert(make_pair(avr,*it));
		if (num % 6 == 0)
		{
			cout << "-------第" << num / 6 << "组的参赛选手信息-------" << endl;
			//遍历groupSpeaker容器输出信息
			for (multimap<double, int, greater<int>>::iterator it = groupSpeaker.begin(); it != groupSpeaker.end(); it++)
			{
				cout << "编号:" << it->second << "  姓名:" << this->m_Speaker[it->second].m_Name 
				<< "  成绩:" << this->m_Speaker[it->second].m_Score[this->m_idenx - 1] << endl;
			}
			cout << endl;

			//取前三名选手,晋级编号存放至v2中
			int count = 0;
			for (multimap<double, int, greater<int>>::iterator it = groupSpeaker.begin(); it != groupSpeaker.end() && count<3; it++,count++)
			{
				if (this->m_idenx == 1)
				{
					v2.push_back(it->second);
				}
				else
				{
					vVictor.push_back(it->second);
				}
			}

			//每一组分完以后清空临时容器
			groupSpeaker.clear();
		}
	}

	cout << "----------- 第" << this->m_idenx << "轮比赛完毕!----------" << endl;
	system("pause");
}

7)显示晋级选手信息 void showScore()

       创建一个临时容器存放每轮的晋级选手根据比赛进行的轮次输 出相应的晋级选手编号和成绩等信息。

//显示晋级选手信息
void SpeechManage::showScore()
{
	cout << "---------第" << this->m_idenx << "轮晋级选手信息如下:---------" << endl;

	//提供一个临时容器存放晋级选手编号
	vector<int> v;
	if (this->m_idenx == 1)
	{
		v = v2;
	}
	else
	{
		v = vVictor;
	}

	//遍历容器输出选手信息
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "编号:" << *it << "  姓名:" << this->m_Speaker[*it].m_Name 
		<< "  成绩:" << m_Speaker[*it].m_Score[this->m_idenx - 1] << endl;
	}
	
	cout << endl;
	//提供暂停,便于用户查看晋级选手信息
	system("pause");
	system("cls");
	this->show_Manu();
}

8)保存最终获胜选手记录 void saveRecord()

      本节比赛完毕后,创建一个.csv文件,保存最终比赛获胜选手的编号和成绩等信息,并定义一个bool类型的判断文件是否为空,记录保存后布尔值为false,即不为空了。

//保存记录
void SpeechManage::saveRecord()
{
	//创建文件
	ofstream ofs;

	//打开文件
	ofs.open("speech.csv", ios::out | ios::app);

	//写入数据
	for (vector<int>::iterator it = vVictor.begin(); it != vVictor.end(); it++)
	{
		ofs << *it << "," << this->m_Speaker[*it].m_Score[1] << ",";
	}
	ofs << endl;

	//关闭文件
	ofs.close();
	
	cout << "比赛记录保存完毕!" << endl;
	//更新文件记录
	this->fileEmpty = false;
}

9)读取文件记录 void loadRecord()

       创建并读取存放记录的文件,先判断文件是否存在,再判断文件是否为空,若存在且不为空则创建临时读取记录的字符串变量,因为.csv文件中的数据用,分隔开了,所以需要解析一下数据才能输出不带逗号的数据,即找到逗号的位置,然后截取起始位置到逗号之间的字符串,反复进行此操作至最后一个逗号为止,并存放至新创建的临时容器中,接着把对应届数和获胜选手编号、成绩等信息存放到存放记录容器   map<int, vector<string>> m_Record中,最后每存一次届数++即可。

//读取记录
void SpeechManage::loadRecord()
{
	//创建并读取文件
	ifstream ifs("speech.csv", ios::in);
	
	//判断文件是否存在
	if (!ifs.is_open())
	{
		this->fileEmpty = true;
		//cout << "文件不存在!" << endl;
		//关闭文件
		ifs.close();
		return;
	}

	//文件清空情况
	char ch;
	ifs >> ch;
	if (ifs.eof())
	{
		//cout << "文件为空!" << endl;
		this->fileEmpty = true;
		ifs.close();
		return;
	}

	//文件不为空
	this->fileEmpty = false;
	//读回字符
	ifs.putback(ch);
	
	string data;			//临时文件数据存放处
	int count = 0;
	

	//从文件中读取内容
	while (ifs >> data)
	{
		//通过逗号位置解析数据
		int pos = -1, start = 0;  //初始化逗号位置不存在,寻找位置初始化为0
		//六个字符串存放处
		vector<string> v;
		while (true)
		{
			pos = data.find(",", start);
			//如果未找到逗号说明遍历完毕
			if (pos == -1)
			{
				break;
			}
			string temp = data.substr(start, pos - start);
			v.push_back(temp);

			//每截取一段数据都更新一下起始位置
			start = pos + 1;
		}
		this->m_Record.insert(make_pair(count+1, v));
		count++;

	}
	
	//关闭文件
	ifs.close();
}

10)正式比赛完整流程 void startSpeech()

       封装正式比赛的完整流程:第一轮-抽签-比赛-晋级-第二轮-抽签-比赛-晋级-保存记录,为保证比完即可查看该届选手记录,务必在最后记录保存后重置并加载比赛信息。

//开始比赛
void SpeechManage::startSpeech()
{
	//第一轮比赛

	//抽签
	this->speakerDraw();
	//开始比赛
	this->speechContest();
	//显示晋级选手
	this->showScore();

	//第二轮比赛
	this->m_idenx++;
	//抽签
	this->speakerDraw();
	//开始比赛
	this->speechContest();
	//显示最终的选手信息
	this->showScore();

	//保存最终获胜选手记录
	this->saveRecord();

	//重置数据
	
	//初始化属性
	this->initSpeech();
	//创建选手
	this->createSpeaker();
	//读取数据
	this->loadRecord();

	cout << "本届比赛完毕!" << endl;
	system("pause");
	system("cls");
}

11)展示往届记录 void showRecord()

       首先判断文件是否为存在或为空,若不为存在且不为空则打印出往届获胜选手信息。

//展示往届记录
void SpeechManage::showRecord()
{
	if (this->fileEmpty)
	{
		cout << "文件不存在或暂无任何往届记录!" << endl;
	}
	else
	{
		for (map<int, vector<string>>::iterator it = this->m_Record.begin(); it != m_Record.end(); it++)
		{
			cout << "第" << it->first << "届 "
				<< " 冠军编号:" << it->second[0] << " 成绩:" << it->second[1]
				<< " 亚军编号:" << it->second[2] << " 成绩:" << it->second[3]
				<< " 季军编号:" << it->second[4] << " 成绩:" << it->second[5] << endl;

		}
	}
	
	system("pause");
	system("cls");
}

12)清空文件记录 void clearFile()

       若确定要清空文件,则使用trunc关键字去删除文件并创建一个空文件,接着初始化比赛的所有信息并读取空文件使得往届记录也清空。

//清空文件
void SpeechManage::clearFile()
{
	cout << "是否确定要清空往届数据?" << endl;
	cout << "1. 确定清空" << endl << "2. 再考虑一下" << endl;
	int select = 0;
	cout << "请输入您的选择:";
	cin >> select;

	//文件清空
	if (select == 1)
	{
		//删除文件并重新创建一个空文件
		ofstream ofs("speech.csv", ios::trunc);
		
		//更新系统数据
		//初始化属性
		this->initSpeech();
		//创建选手
		this->createSpeaker();
		//读取数据
		this->loadRecord();

		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

13)退出管理程序 void exitSystem()

       给出退出提示语,接着exit退出程序即可。

//退出系统程序
void SpeechManage::exitSystem()
{
	cout << "欢迎再次使用!" << endl;
	system("pause");
	exit(0);
}

14)析构函数空实现 ~SpeechManage()

        最终处理类的成员属性且释放相关内存。

SpeechManage::~SpeechManage() {}

5.1.5主调函数main的模块完善

      增加随机数种子是模拟更加趋于真实,实例化管理对象,使用Switch语句通过不同选择调用相关功能模块。

int main()
{
    //随机数种子
    srand((unsigned int)time(NULL));
    //实例化管理类的对象
    SpeechManage sm;
    //创建菜单
    int choice;
    while (1)
    {
       sm.show_Manu();
       cout << "请输出你的选择:" << endl;
       cin >> choice;

       switch (choice)
       {
           case 1:           //比赛开始
              sm.startSpeech();
              break;

           case 2:           //查看往届信息
              sm.showRecord();
              break;
           case 3:           //清空比赛信息
              sm.clearFile();
              break;
           case 0:           //退出系统程序
              sm.exitSystem();
              break;
           default:
              system("cls");
       }
    }
    system("pause");
    return 0;

}

四、设计结果及分析

1、主菜单测试

2、选择1,开始比赛

2.1 比赛完毕,记录保存

3、选择2---查看往届记录

4、选择3---清空文件记录

4.1 检查是否确实清空

5、退出系统程序

   

 

  6. 查看Speech.csv文件内容(前面因被清空,故以下记录为我重新进行几次比赛得出,因此可能与前面现显示不同)

 

    至此,管理系统程序测试完毕!

五、总结与归纳

1、课题总结

       该程序是基于C++的STL的演讲比赛流程管理系统的简易实现。现在总结一下它的关键特点和功能:

1. STL的使用:

        使用STL中的vector\deque\map等容器对选手编号等信息进行记录或存放。

2. 随机数生成:

       使用rand()函数和time(NULL)来生成随机数种子,确保每次运行程序时都能获得不同的随机数序列。

3. 面向对象编程:

       使用类SpeechManage来管理整个演讲比赛流程,包括开始比赛、显示菜单、查看往届信息、清空比赛信息等功能。

       利用面向对象的思想将相关的功能进行封装,提高了代码的可读性和可维护性。

4. 循环结构:

       使用while循环不断显示菜单,等待用户输入选择。

       在用户选择退出系统前,程序将持续运行。

5. Switch语句:

       使用switch语句根据用户的选择执行相应的功能,增加了程序的交互性和可操作性。

6. 文件操作:

       程序可能包括对文件的读取和写入操作,例如存储选手信息和比赛记录,以及清空比赛信息等。

7. 算法设计:

       比赛规则明确,使用了常见的算法设计,如选手分组、评委打分、淘汰选手等。

8. 清屏操作:

      使用了system("cls")来清屏,使得菜单界面始终保持清晰。

9. 用户交互:

      程序通过cin和cout实现与用户的交互,提供友好的命令行界面。

10. 程序结构清晰:

      程序结构清晰,功能模块化,易于理解和扩展。

       本程序展示了如何利用C++的STL设计一个简单但功能完整的演讲比赛流程管理系统。通过良好的代码组织和逻辑设计,使得程序具有较高的可维护性和可扩展性。

2、个人收获

     通过该系统程序的编写,我从以下几点谈谈我的收获:

1、深入理解STL:通过实践,你对C++标准模板库(STL)的使用和功能有了更深入的理解,特别是对vector容器的灵活运用。

2、面向对象思想:通过构建SpeechManage类来管理整个比赛流程,你对面向对象编程的理解更加深入,并学会了如何将功能模块化、封装化。

3、算法设计能力:通过比赛规则的实现,你锻炼了设计算法的能力,包括选手分组、评委打分、淘汰选手等。

4、程序设计与逻辑思维:编写这个程序过程中,你学会了如何合理划分功能模块、设计程序逻辑,提高了编程能力和逻辑思维能力。

5、用户交互设计:通过与用户的交互,你学会了如何设计友好的命令行界面,提高了用户体验。

6、调试与错误处理:在编写过程中可能会遇到各种问题,通过调试和错误处理,你学会了解决问题的方法,提高了问题排查和解决能力。

       总之,通过编写这个项目,我不仅学会了更多关于C++编程语言和STL的知识,还提高了解决问题的能力、团队合作能力以及项目管理技能。

六、总源代码实现

1、选手类speaker.h实现

#pragma once  //防止头文件重复编译
#include<iostream>
using namespace std;

//创建选手类
class Speaker
{
public:

	string m_Name;   //选手姓名

	double m_Score[2]; //两轮比赛每名选手最多存在两轮成绩
};

2、大管理类speechProcessManagement.h实现

#pragma once  //防止头文件重复编译
#include<iostream>
#include<vector>
#include<map>
#include<string>
#include<algorithm>
#include<deque>
#include<numeric>  //后期调用求和函数accumlate()
#include<fstream>
#include<ctime>
#include"speaker.h"  //包含选手类头文件
using namespace std;

//创建管理类
class SpeechManage
{
public:
	
	//构造函数
	SpeechManage();

	//创建菜单
	void show_Manu();

	//初始化成员属性
	void initSpeech();

	//创建选手
	void createSpeaker();

	//抽签
	void speakerDraw();

	//正式比赛
	void speechContest();

	//显示晋级选手信息
	void showScore();

	//保存记录
	void saveRecord();

	//读取记录
	void loadRecord();

	//判断文件为空
	bool fileEmpty;

	//保存往届记录的容器
	map<int, vector<string>> m_Record;

	//开始比赛
	void startSpeech();

	//展示往届记录
	void showRecord();

	//清空文件
	void clearFile();

	//退出
	void exitSystem();

	//析构函数
	~SpeechManage();

	//创建成员属性
	vector<int> v1;  //第一轮十二名队员的编号
	vector<int> v2;  //第二轮六名队员的编号
	vector<int> vVictor;  //最终夺冠队员的编号
	map<int, Speaker> m_Speaker;  //记录的队员信息
	int m_idenx;   //比赛的轮数

};

3、管理类成员函数speechProcessManagement.cpp实现

#include "speechProcessManagement.h"  //调用管理类声明
using namespace std;

//构造函数
SpeechManage::SpeechManage()
{
	//初始化属性
	this->initSpeech();
	//创建选手
	this->createSpeaker();
	//读取数据
	this->loadRecord();

}

//初始化成员属性
void SpeechManage::initSpeech()
{
	this->v1.clear();
	this->v2.clear();
	this->vVictor.clear();
	this->m_Speaker.clear();
	//初始化比赛轮次
	this->m_idenx = 1;
	//初始化往届记录,避免比赛完后每一次查看均为同样的记录
	this->m_Record.clear();
}

//创建选手
void SpeechManage::createSpeaker()
{
	//创建12名选手
	string nameSeed = "ABCDEFGHIJKL";
	for (int i = 0; i < nameSeed.size(); i++)
	{
		string name = "选手";
		name += nameSeed[i];

		Speaker sp;
		sp.m_Name = name;

		//初始化选手成绩
		for (int j = 0; j < 2; j++)
		{
			sp.m_Score[j] = 0;
		}

		//把编号存放至v1容器
		this->v1.push_back(i + 10001);
		//存放选手信息 编号+姓名分数
		this->m_Speaker.insert(make_pair(i + 10001, sp));
	}

}

//创建菜单
void SpeechManage::show_Manu()
{
	cout << "***************************************" << endl;
	cout << "*********** 欢迎参加演讲比赛 **********" << endl;
	cout << "*********** 1、开始演讲比赛 ***********" << endl;
	cout << "*********** 2、查看往届记录 ***********" << endl;
	cout << "*********** 3、清空比赛记录 ***********" << endl;
	cout << "*********** 0、退出比赛程序 ***********" << endl;
	cout << "***************************************" << endl;
}

//抽签
void SpeechManage::speakerDraw()
{
	cout << "第 <<" << this->m_idenx << ">> 轮比赛选手正在抽签..." << endl;
	cout << "----------------------------------" << endl;
	cout << "选手演讲顺序如下:" << endl;
	if (this->m_idenx == 1)
	{
		random_shuffle(v1.begin(), v1.end());  //随机打乱表示12人随机抽取,以便后面随机分组
		for (vector<int>::iterator it = v1.begin(); it != v1.end(); it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
	else
	{
		random_shuffle(v2.begin(), v2.end());
		for (vector<int>::iterator it = v2.begin(); it != v2.end(); it++)
		{
			cout << *it << " ";
		}
		cout << endl;
	}
	cout << "----------------------------------" << endl;
	//为用户给出查看抽签情况提供暂停
	system("pause");
}

//比赛
void SpeechManage::speechContest()
{
	cout << "--------第" << this->m_idenx << "轮比赛正式开始--------" << endl;

	//准备一个临时容器,存放小组参赛选手,num用作记录小组数
	int num = 0;
	multimap<double, int, greater<int>> groupSpeaker;

	//创建存放比赛选手编号的容器
	vector<int> v_Src;
	if (this->m_idenx == 1)
	{
		v_Src = v1;
	}
	else
	{
		v_Src = v2;
	}

	//遍历所有参赛选手
	for (vector<int>::iterator it = v_Src.begin(); it != v_Src.end(); it++)
	{
		num++;
		//参赛选手开始演讲,十位评委开始打分
		deque<double> d;
		for (int i = 0; i < 10; i++)
		{
			
			//分数
			double score = (rand() % 401 + 600) / 10.f;
			d.push_back(score);
		}

		sort(d.begin(), d.end());
		//去除最高分和最低分
		d.pop_front();
		d.pop_back();
		//求和
		double sum = accumulate(d.begin(), d.end(), 0.0f);   //0.0f ?
		//取平均值
		double avr = sum / (double)d.size();

		//将分数存放至m_Speaker
		this->m_Speaker[*it].m_Score[this->m_idenx - 1] = avr;

		//利用容器存放临时各组的选手,并记录第几组
		groupSpeaker.insert(make_pair(avr,*it));
		if (num % 6 == 0)
		{
			cout << "-------第" << num / 6 << "组的参赛选手信息-------" << endl;
			//遍历groupSpeaker容器输出信息
			for (multimap<double, int, greater<int>>::iterator it = groupSpeaker.begin(); it != groupSpeaker.end(); it++)
			{
				cout << "编号:" << it->second << "  姓名:" << this->m_Speaker[it->second].m_Name 
				<< "  成绩:" << this->m_Speaker[it->second].m_Score[this->m_idenx - 1] << endl;
			}
			cout << endl;

			//取前三名选手,晋级编号存放至v2中
			int count = 0;
			for (multimap<double, int, greater<int>>::iterator it = groupSpeaker.begin(); it != groupSpeaker.end() && count<3; it++,count++)
			{
				if (this->m_idenx == 1)
				{
					v2.push_back(it->second);
				}
				else
				{
					vVictor.push_back(it->second);
				}
			}

			//每一组分完以后清空临时容器
			groupSpeaker.clear();
		}
	}

	cout << "----------- 第" << this->m_idenx << "轮比赛完毕!----------" << endl;
	system("pause");
}

//显示晋级选手信息
void SpeechManage::showScore()
{
	cout << "---------第" << this->m_idenx << "轮晋级选手信息如下:---------" << endl;

	//提供一个临时容器存放晋级选手编号
	vector<int> v;
	if (this->m_idenx == 1)
	{
		v = v2;
	}
	else
	{
		v = vVictor;
	}

	//遍历容器输出选手信息
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "编号:" << *it << "  姓名:" << this->m_Speaker[*it].m_Name 
		<< "  成绩:" << m_Speaker[*it].m_Score[this->m_idenx - 1] << endl;
	}
	
	cout << endl;
	//提供暂停,便于用户查看晋级选手信息
	system("pause");
	system("cls");
	this->show_Manu();
}

//保存记录
void SpeechManage::saveRecord()
{
	//创建文件
	ofstream ofs;

	//打开文件
	ofs.open("speech.csv", ios::out | ios::app);

	//写入数据
	for (vector<int>::iterator it = vVictor.begin(); it != vVictor.end(); it++)
	{
		ofs << *it << "," << this->m_Speaker[*it].m_Score[1] << ",";
	}
	ofs << endl;

	//关闭文件
	ofs.close();
	
	cout << "比赛记录保存完毕!" << endl;
	//更新文件记录
	this->fileEmpty = false;
}

//读取记录
void SpeechManage::loadRecord()
{
	//创建并读取文件
	ifstream ifs("speech.csv", ios::in);
	
	//判断文件是否存在
	if (!ifs.is_open())
	{
		this->fileEmpty = true;
		//cout << "文件不存在!" << endl;
		//关闭文件
		ifs.close();
		return;
	}

	//文件清空情况
	char ch;
	ifs >> ch;
	if (ifs.eof())
	{
		this->fileEmpty = true;
		ifs.close();
		return;
	}

	//文件不为空
	this->fileEmpty = false;
	//读回字符
	ifs.putback(ch);
	
	string data;			//临时文件数据存放处
	int count = 0;
	

	//从文件中读取内容
	while (ifs >> data)
	{
		//通过逗号位置解析数据
		int pos = -1, start = 0;  //初始化逗号位置不存在,寻找位置初始化为0
		//六个字符串存放处
		vector<string> v;
		while (true)
		{
			pos = data.find(",", start);
			//如果未找到逗号说明遍历完毕
			if (pos == -1)
			{
				break;
			}
			string temp = data.substr(start, pos - start);
			v.push_back(temp);

			//每截取一段数据都更新一下起始位置
			start = pos + 1;
		}
		this->m_Record.insert(make_pair(count+1, v));
		count++;
	}
	//关闭文件
	ifs.close();
}

//开始比赛
void SpeechManage::startSpeech()
{
	//第一轮比赛

	//抽签
	this->speakerDraw();
	//开始比赛
	this->speechContest();
	//显示晋级选手
	this->showScore();

	//第二轮比赛
	this->m_idenx++;
	//抽签
	this->speakerDraw();
	//开始比赛
	this->speechContest();
	//显示最终的选手信息
	this->showScore();

	//保存最终获胜选手记录
	this->saveRecord();

	//重置数据
	
	//初始化属性
	this->initSpeech();
	//创建选手
	this->createSpeaker();
	//读取数据
	this->loadRecord();

	cout << "本届比赛完毕!" << endl;
	system("pause");
	system("cls");
}

//展示往届记录
void SpeechManage::showRecord()
{
	if (this->fileEmpty)
	{
		cout << "文件不存在或暂无任何往届记录!" << endl;
	}
	else
	{
		for (map<int, vector<string>>::iterator it = this->m_Record.begin(); it != m_Record.end(); it++)
		{
			cout << "第" << it->first << "届 "
				<< " 冠军编号:" << it->second[0] << " 成绩:" << it->second[1]
				<< " 亚军编号:" << it->second[2] << " 成绩:" << it->second[3]
				<< " 季军编号:" << it->second[4] << " 成绩:" << it->second[5] << endl;

		}
	}
	
	system("pause");
	system("cls");
}

//清空文件
void SpeechManage::clearFile()
{
	cout << "是否确定要清空往届数据?" << endl;
	cout << "1. 确定清空" << endl << "2. 再考虑一下" << endl;
	int select = 0;
	cout << "请输入您的选择:";
	cin >> select;

	//文件清空
	if (select == 1)
	{
		//删除文件并重新创建一个空文件
		ofstream ofs("speech.csv", ios::trunc);
		
		//更新系统数据
		//初始化属性
		this->initSpeech();
		//创建选手
		this->createSpeaker();
		//读取数据
		this->loadRecord();

		cout << "清空成功!" << endl;
	}

	system("pause");
	system("cls");
}

//退出系统程序
void SpeechManage::exitSystem()
{
	cout << "欢迎再次使用!" << endl;
	system("pause");
	exit(0);
}

//析构函数
SpeechManage::~SpeechManage() {}

4、主调函数实现speechContestManagementSystem.cpp

#include<iostream>
#include"speechProcessManagement.h"
using namespace std;

int main()
{
	//随机数种子
	srand((unsigned int)time(NULL));

	//实例化管理类的对象
	SpeechManage sm;
	//创建菜单
	int choice;
	
	while (1)
	{
		sm.show_Manu();
		cout << "请输出你的选择:" << endl;
		cin >> choice;

		switch (choice)
		{
			case 1:			//比赛开始
				sm.startSpeech();
				break;
			case 2:			//查看往届信息
				sm.showRecord();
				break;
			case 3:			//清空比赛信息
				sm.clearFile();
				break;
			case 0:			//退出系统程序
				sm.exitSystem();
				break;
			default:
				system("cls");
		}
	}
	system("pause");
	return 0;
}

       至此,基于STL的模拟的演讲比赛流程管理系统的实现全部完毕!

以上表述难免存在疏漏和不足之处,欢迎小伙伴们在评论区留言和批评指正~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/622673.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

绘图软件 excalidraw 部署流程 [ Ubuntu 22.4已验证 ]

文章目录 前置一、修改DNS二、添加docker 镜像三、pull excalidraw/excalidraw四、启动一个docker五、访问 简介&#xff1a;这篇文章介绍的是一份开源的绘图软件的部署过程 前置 安装docker&#xff1a;Ubuntu 系统&#xff0c;Docker 安装步骤 [Ubuntu 22.4已验证] 其他系…

回炉重造java----JVM

为什么要使用JVM ①一次编写&#xff0c;到处运行&#xff0c;jvm屏蔽字节码与底层的操作差异 ②自动内存管理&#xff0c;垃圾回收功能 ③数组下边越界检查 ④多态 JDK&#xff0c;JRE&#xff0c;JVM的关系 JVM组成部分 JVM的内存结构 《一》程序计数器(PC Register) 作用…

谷歌Gboard应用的语言模型创新:提升打字体验的隐私保护技术

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

浦语大模型笔记

书生浦语大模型全链路开源体系 浦语大模型全链路开源体系大模型成为发展通用人工智能的重要途径书生浦语 2.0&#xff08;InternLM2&#xff09;核心理念书生浦语 2.0&#xff08;InternLM2&#xff09;的主要亮点主要亮点 1&#xff1a;超长上下文支持主要亮点 2&#xff1a;性…

网络库-libevent介绍

1.简介 libevent是一个事件驱动的网络库&#xff0c;主要用于构建可扩展的网络服务器。它提供了跨平台的API&#xff0c;支持多种事件通知机制&#xff0c;如select、poll、epoll、kqueue等。 主要组件 event: 表示一个具体的事件&#xff0c;包括事件类型、事件回调等。eve…

大模型管理工具:SWIFT

目录 一、SWIFT 介绍 二、SWIFT 安装 2.0 配置环境(可选) 2.1 使用pip进行安装 2.2 源代码安装 2.3 启动 WEB-UI 三、部署模型 3.0 deploy命令参数 3.1 原始模型 3.2 微调后模型 一、SWIFT 介绍 SWIFT&#xff08;Scalable lightWeight Infrastructure for Fine-Tuni…

golang创建式设计模式------单例模式

目录导航 1.单例模式1)什么是单例模式 2)使用场景3)实现方式1.懒汉式单例模式2.饿汉式3.双重检查式4.sysc.Once式 4)实践案例5)优缺点分析 1.单例模式 1)什么是单例模式 单例模式(Singleton Pattern)是一种常用的设计模式。单例模式的类提供了一种访问其唯一对象的方法&#…

UML快速入门篇

目录 1. UML概述 2. 类的表示 2.1. 类的表示 2.2. 抽象类的表示 2.3. 接口的表示 3. 类的属性&#xff0c;方法&#xff0c;访问权限的表示 3.1. 类的属性 3.2. 类的方法 3.3. 类的权限 4. 类的关联 4.1. 单向关联 4.2. 双向关联 4.3. 自关联 4.4. 类的聚合 4.5.…

sipeed 的 MaixCam显示图片

WiFi联网后&#xff0c;把固件升级到最新 一根tpyc-c连接线为MaixCam供电&#xff0c;点击液晶屏settings 在WiFi中设置确保联网&#xff0c;在更新MaixPy中升级固件 可以选择国内源加速&#xff0c;将固件升级到最新版 MaixVision的操作 1&#xff0c;在MaixVision左下角…

C语言(指针)6

Hi~&#xff01;这里是奋斗的小羊&#xff0c;很荣幸各位能阅读我的文章&#xff0c;诚请评论指点&#xff0c;关注收藏&#xff0c;欢迎欢迎~~ &#x1f4a5;个人主页&#xff1a;小羊在奋斗 &#x1f4a5;所属专栏&#xff1a;C语言 本系列文章为个人学习笔记&#x…

StackQueue+泛型简单理解

&#x1f341; 个人主页&#xff1a;爱编程的Tom&#x1f4ab; 本篇博文收录专栏&#xff1a;Java专栏&#x1f449; 目前其它专栏&#xff1a;c系列小游戏 c语言系列--万物的开始_ &#x1f389; 欢迎 &#x1f44d;点赞✍评论⭐收藏&#x1f496;三连支持一…

新的语言学习系统: 记忆镶嵌

摘要 记忆镶嵌是由多个关联记忆网络协同工作来完成感兴趣的预测任务。与transformer类似,记忆镶嵌具有组合能力和上下文学习能力。与transformer不同,记忆镶嵌以相对透明的方式实现这些能力。该研究在玩具示例上展示了这些能力,并且还表明记忆镶嵌在中等规模语言建模任务上的表…

JVM调优:JVM运行时数据区详解

一、前言 Java运行时数据区域划分&#xff0c;Java虚拟机在执行Java程序时&#xff0c;将其所管理的内存划分为不同的数据区域&#xff0c;每个区域都有特定的用途和创建销毁的时间。 其中&#xff0c;有些区域在虚拟机进程启动时就存在&#xff0c;而有些区域则是随着用户线程…

YOLOv9-20240507周更说明|更新MobileNetv4等多种轻量化主干

专栏地址&#xff1a;目前售价售价69.9&#xff0c;改进点70 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 本周已更新说明&#xff1a; ### ⭐⭐更新时间&#xff1a;2024/5/12⭐⭐ 1. YOLOv9…

企业网站HTTP网站业务被慢连接攻击了该怎么办

企业的网站建设中遇到网络攻击会出现哪些问题&#xff1f;一些中小型企业对于网络安全的认知不足&#xff0c;网站建设种类众多&#xff0c;电子商城类&#xff0c;小型游戏&#xff0c;支付类型&#xff0c;H5页面的网站&#xff0c;开发等等&#xff0c;如遇见网络攻击造成的…

ubuntu server 22.04.4 系统安装详细教程

本教程使用vmware workstation 17创建虚拟机进行安装演示&#xff0c;安装方式和真机安装没有区别。 1、下载镜像 下载ubuntu server版本系统镜像&#xff0c;官网下载地址&#xff1a;https://cn.ubuntu.com/download/server/step1 注意&#xff1a;自己下载时需要确认是否是…

ARP中间人

文章目录 ARP中间人ARP协议介绍使用kali进行ARP毒化使用kali进行ARP中间人使用kali进行ARP钓鱼ARP攻击防御ARP总结 ARP中间人 ARP协议介绍 维基百科ARP介绍 ARP&#xff08;地址解析协议&#xff09;在网络通信中扮演着至关重要的角色&#xff0c;它通过将网络层地址&#x…

运维基础(二)- 钉钉的使用

一、钉钉的介绍&#xff08;来自百度百科&#xff09; 免费沟通和协同的多端平台 帮助中国企业通过系统化的解决方案&#xff08;微应用&#xff09;&#xff0c;全方位提升中国企业沟通和协同效率。 钉钉&#xff08;Ding Talk&#xff09; 是阿里巴巴打造的企业级智能移动…

Windows环境下代码文档生成工具Doxygen使用详细教程

背景 最近研究aom源码&#xff0c;发现编译需要依赖Doxygen工具&#xff0c;故此篇博客详细记录下Doxygen的安装和使用。 Doxygen Doxygen 是一个强大的源代码文档生成工具&#xff0c;它支持多种编程语言&#xff0c;能够直接从源代码中的注释提取文档&#xff0c;并生成多…

RabbitMQ中间件安装

消息队列 RabbitMQ yum -y update yum -y install epel-release erlang # 安装erlang erl -version # 判断是否安装成功根据官网的的表格判断自己用哪个版本的 RabbitMQ&#xff1a;https://www.rabbitmq.com/docs/which-erlang#r16b03 [rootiZuf6hqrs5cb2ccyuc9nqvZ ~]# er…