基于STL的 演讲比赛流程管理系统

news2024/11/23 21:02:31

目录

一、演讲比赛程序要求

        1、比赛规则

        2、程序功能

二、创建管理类

三、菜单功能

四、退出功能

五、演讲比赛功能

1、功能分析

2、创建选手类

3、进行比赛

4、保存分数

 六、查看比赛记录

1、读取记录分数

2、查看记录功能

3、bug解决

七、清空功能

 


一、演讲比赛程序要求

1、比赛规则

举办一场演讲比赛,共有12人参加,比赛共2轮,第一轮为淘汰赛,第二轮为决赛。

①每位选手都有对应的编号:如10001,10002...10012;A、B...、L

②比赛方式:分组比赛,每组6个人比赛一场,共2场

③第一轮比赛分为2个小组,整体按照选手编号进行抽签后顺序演讲

④十名评委分别给每位选手打分,去除最高分和最低分,取平均分为本轮选手的成绩

⑤当第一轮比赛结束后,每个小组的前三名晋级进入下一轮比赛,后三名淘汰

⑥第二轮决赛,六位选手前三名胜出,按成绩分为冠军亚军季军

⑦每轮比赛后显示晋级选手的信息


2、程序功能

①开始比赛功能:完成整届比赛的流程,比赛各个阶段需要给用户一个提示,用户按任意键后继续下一个阶段

②查看往届记录:查看之前比赛的前三名结果,包含姓名和成绩。每次比赛都会记录到文件中,以csv格式保存

③清空比赛记录:将文件中数据清空

④退出比赛程序:可以退出当前程序


二、创建管理类

功能:

①提供菜单界面与用户交互

②对演讲比赛流程进行控制

③与文件的读写交互


首先创建SpeachManager的头文件和源文件 

 然后在头文件里实现管理类Manager,并带上构造函数和析构函数

然后在源文件里空实现构造和析构函数,注意带作用域

 


三、菜单功能

功能:与用户交互的界面

首先在管理类中添加菜单显示接口show_menu();

然后在源文件中实现 :注意带上作用域Manager::

void Manager::show_menu()
{
	cout << "******************************************" << endl;
	cout << "********** 欢迎使用演讲比赛系统 **********" << endl;
	cout << "**********    1、开始演讲比赛   **********" << endl;
	cout << "**********    2、查看往届记录   **********" << endl;
	cout << "**********    3、清空比赛记录   **********" << endl;
	cout << "**********    0、退出比赛系统   **********" << endl;
	cout << "******************************************" << endl;
}

然后在main函数中调用:我们先包含SpeachManager.h头文件,然后再根据管理类创建对象m

调用:


四、退出功能

功能:退出系统

目前系统只有一个显示功能,而且不支持输入与选择,因此我们使用while(true)和switch语句来实现该功能

在头文件里声明exit_m();接口后在源文件中实现:

 

// 退出功能
void Manager::exit_m()
{
	cout << "欢迎下次使用!" << endl;
	exit(0);
}

 修改main函数,添加while(true)循环和switch语句

int main()
{
	Manager m;
	int input;
	while (true)
	{
		m.show_menu();
		cout << "请选择:" << endl;
		cin >> input;
		switch (input)
		{
			case 1:	// 开始比赛
				break;
			case 2: // 显示往届记录
				break;
			case 3: // 清空所有记录 
				break;
			case 0: // 退出系统
				m.exit_m();
			default:
				system("cls"); // 清屏
				break;
		}
	}
	return 0;
}


五、演讲比赛功能

1、功能分析

比赛流程:


2、创建选手类

选手类speaker,应包含属性姓名name与分数score(分数有2轮)

在头文件中创建:

class speaker  // 选手类
{
public:
	string s_name;
	double s_score[2]; // 2轮得分,double使不会出现同分的情况
};

3、进行比赛

①添加成员属性

在管理类中添加各种属性:

    vector<int> v1; // 存放第1轮比赛的选手,共12人
	vector<int> v2; // 存放第2轮比赛的选手,共6人
	vector<int> v3; // 存放比赛胜出的选手,共3人

	map<int, speaker> m_speaker; // 存放编号以及对应的选手 容器
	int index; // 记录比赛的轮数

②初始化属性

头文件中生成初始化属性接口initSpeaker();在源文件中实现,并在构造函数中调用

// 初始化属性
void Manager::initSpeaker()
{
	// 全部清空并置1
	this->v1.clear();
	this->v2.clear();
	this->v3.clear();
	this->m_speaker.clear();
	this->index = 1;
}

 调用:

③创建选手

首先在管理类中添加创建选手的接口createrSperker();

然后在源文件中实现

void Manager::createSpeaker()
{
	string nameSeed = "ABCDEFJHIJKL";
	for (int i = 0; i < nameSeed.size(); i++)
	{
		string name = "选手";
		name += nameSeed[i];

		speaker sp; // 创建一位选手
		sp.s_name = name; // 选手名字初始化
		for (int j = 0; j < 2; j++)
		{
			sp.s_score[j] = 0; // 选手分数初始化
		}
		// 为选手编号
		this->v1.push_back(i + 10001);
		// 将选手编号以及对应选手插入到map容器中,编号10001-100012
		this->m_speaker.insert(make_pair(i + 10001, sp));
	}
}

然后在构造函数中调用

这样就完成了选手的创建,不过为了方便查看,我再实现一个查看map容器中元素的函数,打印出目前选手的信息

	for (map<int, speaker>::iterator it = m.m_speaker.begin(); it != m.m_speaker.end(); it++)
	{
		cout << "选手编号:"<<it->first<<"\t姓名:" << it->second.s_name << "\t分数:" << it->second.s_score[1] << endl;
	}

④开始比赛成员函数添加

首先在管理类中添加开始比赛成员函数startSpeach();

 然后在源文件中空实现

// 开始比赛
void Manager::startSpeach()
{
	// 第一轮比赛
	//	1、抽签
	//	2、比赛
	//	3、显示比赛结果
	
	// 第二轮比赛
	//	1、抽签
	//	2、比赛
	//	3、显示比赛结果
}

⑤抽签

抽签分为2种:第一轮抽签与第二轮抽签

我们可以根据属性index来判断比赛进行的轮数,以给容器v1或是v2进行洗牌

我们先在管理类中加上抽签DrawSpeach();接口

然后在源文件中实现

void Manager::DrawSpeach()
{
	cout << "第" << this->index << "轮抽签正在进行" << endl;
	cout << "***************************************" << endl;
	Sleep(1000);
	cout << "抽签后演讲顺序如下" << endl;
	if (this->index == 1)
	{
		random_shuffle(v1.begin(), v1.end());
		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");
	cout << endl;
}

最后在开始比赛stratSpeach接口中调用

测试:

⑥开始比赛

比赛流程代码可以分为4部分:

Ⅰ创建比赛的人员的容器v_person,并根据不同轮数将对应容器赋给v_perso

Ⅱ创建人数的计数num,遍历v_person里所有选手,创建deque容器,每个选手进行10名评委的打分并将分数插入到deque容器,排序后去除最高分和最低分,最后获取总分和平均分,并将平均分赋值给对应轮数的score[0/1]中

Ⅲ创建小组容器以存储对组,以平均分和编号创建对组,每6个选手为一组,输出这6名选手的姓名编号与成绩

Ⅳ取出前3名,如果是第1场比赛,则将前三名插入到v2容器,如果是第2场比赛,则插入到v3中,每6个清空一次

先在管理类中创建进行比赛Speach(); 接口

然后在源文件中实现

void Manager::Speach()
{
	cout << "------------" << "第" << this->index << "组比赛正式开始" << "-------------" << endl;
	multimap<double, int, greater<double>> Group; // 存储分数与选手编号,降序排列,放在最外面,防止进入循环创建不同的容器

	//	1、创建比赛的人员的容器v_person,并根据不同轮数将对应容器赋给v_person
	vector<int>v_person;
	if (this->index == 1)
	{
		v_person = v1;
	}
	else
	{
		v_person = v2;
	}

	//	2、创建人数的计数num,遍历v_person里所有选手,创建deque容器,每个选手进行10名评委的打分
	//	   排序后去除最高分和最低分,最后获取总分和平均分
	int num = 0;
	for (vector<int>::iterator it = v_person.begin(); it != v_person.end(); it++)
	{
		// 评委打分
		deque<double>d;
		for (int i = 0; i < 10; i++)
		{
			double score = (rand() % 401 + 600) / 10.f; // 随机数600-1000,除以10后保留1位小数,是60.0-100.0
			d.push_back(score); // 将分数插入到d中
		}
		sort(d.begin(), d.end(),greater<double>()); // 降序 排序
		d.pop_back();	// 去除最低分
		d.pop_front();	// 去除最高分

		double sum = accumulate(d.begin(), d.end(),0); // 获取总分
		double avg = sum / d.size();	// 获取均值
		this->m_speaker[*it].s_score[this->index - 1] = avg; // 将均分存入到选手对应轮数的score里

		//	3、创建小组容器,以平均分和编号创建对组,每6个选手为一组,输出这6名选手的姓名编号与成绩
		Group.insert(make_pair(avg, *it)); // 将每位选手的均分和编号插入到Group容器中
		num++;	// 插入后人数++
		if (num % 6 == 0) // 每插入6个人,进入一次遍历输出,此时输出的已经排序
		{
			cout <<"第" << num / 6 << "组选手比赛名次:" << endl;
			for (multimap<double, int, greater<double>>::iterator it = Group.begin(); it != Group.end(); it++)
			{
				cout << "编号:" << it->second << "\t姓名:"
					<< this->m_speaker[it->second].s_name << "\t平均分:"
					<< this->m_speaker[it->second].s_score[this->index - 1] << endl;
			}

			//	4、取出前3名,如果是第1场比赛,则将前三名插入到v2容器,如果是第2场比赛,则插入到v3中,每6个清空一次
			int count = 0; // 使我们可以取出前三名:0、1、2
			for (multimap<double, int, greater<double>>::iterator it = Group.begin(); it != Group.end() && count < 3; it++, count++)
			{
				if (this->index == 1)
				{
					v2.push_back((*it).second);
				}
				else
				{
					v3.push_back((*it).second);
				}
			}
			Group.clear(); // 如果不清空,则下次会有上次遍历的值
			cout << endl;
		}
	}
	cout << "--------------"<<"第" << this->index << "轮比赛结束" <<"---------------" << endl;	 
}

最后在开始比赛stratSpeach接口中调用

⑦显示比赛分数

显示比赛晋级的选手,即每轮比赛的前三名

先在管理类中添加显示比赛结果的接口函数showSpeach();

然后在源文件中实现

void Manager::showSpeach()
{
	cout << "------------" << "第" << this->index << "轮选手晋级信息:" << "-------------" << endl;
	vector<int>v;
	if (this->index == 1)
	{
		v = v2;
	}
	else
	{
		v = v3;
	}
	for (vector<int>::iterator it = v.begin(); it != v.end(); it++)
	{
		cout << "编号:" << *it << "\t姓名:"
			<< this->m_speaker[*it].s_name << "\t平均分:"
			<< this->m_speaker[*it].s_score[this->index - 1] << endl;
	}
	cout << endl;
	system("pause");
	system("cls");
}

 最后在开始比赛stratSpeach接口中调用

⑧第二轮比赛

把第一轮比赛流程的代码加到第二轮即可

不过注意场次index要++


4、保存分数

先在管理类中添加保存比赛结果的接口函数saveSpeach();

然后在源文件中实现

void Manager::saveSpeach()
{
	ofstream ofs;
	ofs.open("Speach.csv", ios::out | ios::app);
	// 以输出和追加方式打开文件,后缀命名为csv
	// 将最终获胜的3人数据写入文件
	for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++)
	{
		ofs << *it <<"," <<this->m_speaker[*it].s_score[1] << ",";
	}
	ofs << endl;
	ofs.close();
	cout << "文件已保存!" << endl;
}


 六、查看比赛记录

1、读取记录分数

先在管理类中添加读取记录分数的接口函数loadSpeach();以及记录文件是否为空的标识符fileISempty和存放往届记录的容器map<int,vector<string>> s_Load

然后在源文件中实现:

 读取文件时,会有3种情况:

Ⅰ文件不存在

	ifstream ifs("Speach.csv", ios::in); // 读方式打开文件

	// 1、文件不存在
	if (!ifs.is_open())
	{
		this->fileISempty = true;
		cout << "文件不存在!" << endl;
		ifs.close();
		return;
	}

Ⅱ文件为空(或被清空)

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

Ⅲ 文件不为空

因为不同数据之间用逗号, 隔开,我们通过substr截取开头到逗号,中间的数据来分割每个数据

而下一个截取的开头就是上次截取结尾+1,结尾就是下一个逗号,的位置

然后将每个数据存放到一个vector容器中,最后将容器以对组插入到map容器

	// 3、文件不为空
	this->fileISempty = false;
	ifs.putback(ch);// 将上面截取的1个字符放回
	string data; // 存储文件中读取到的信息
	int session = 1; // 比赛的届数
	while (ifs >> data)
	{
		vector<string>v; // 存储选手编号以及分数的容器,直接都用string类型
		int pos = -1; // 查到,逗号的位置,将位置存储在pos
		int start = 0;// 起始位置
		while (true)
		{
			pos = data.find(",", start);// 从start 0开始查找 ,逗号 
		// 10003,80.375,10004,80,10007,79.375
		//  start 1  pos ,逗号所在的位置,中间要截取的就是pos-start
			if (pos == -1)
			{
				// 没找到
				break;
			}
			string tmp = data.substr(start, pos - start);
			v.push_back(tmp);
			start = pos + 1; // 让start移到pos+1的位置
		}
		this->s_Load.insert(make_pair(session, v)); // 将届数和选手信息插入到s_Load里
		session++;
	}

2、查看记录功能

先在管理类中添加查看记录分数的接口函数showRecord();

 然后在源文件中实现:判断完文件不为空后,直接遍历输出即可

void Manager::showRecord()
{
	if (this->fileISempty)
	{
		cout << "文件为空或不存在!" << endl;
	}
	else
	{
		for (map<int, vector<string>>::iterator it = s_Load.begin(); it != s_Load.end(); it++)
		{
			cout << "第" << it->first << "届 "
				<< "\t冠军编号为:" << it->second[0] << "\t分数为:" << it->second[1] << endl
				<< "\t亚军编号为:" << it->second[2] << "\t分数为:" << it->second[3] << endl
				<< "\t季军编号为:" << it->second[4] << "\t分数为:" << it->second[5] << endl;
			Sleep(40);
		}
	}
	Sleep(500);
	system("pause");
	system("cls");
}


3、bug解决

当Speach.csv中没有数据时,我们进行一场比赛,结束后数据会存放到文件中,但这时直接运行2查看记录分数时仍然会提示文件为空

 进行比赛

再次使用2,仍然为空

解决:我们每次保存文件时,都应在最后使fileISempty为false

 这样就解决了

Ⅱ不过就上面解决后,我们继续执行代码,重复操作

会发现程序没有任何输出,这是因为数据没有实时更新

解决:我们需要再次初始化属性、创建选手并获取往届记录

即将构造函数中的函数在进行比赛的接口Speach(0;中调用

        

 

 Ⅲ 初始化时,没有初始化记录容器s_Load

会导致我们怎么清空容器,容器都存在数据

解决:在初始化接口initSpeaker();中初始化记录容器


 七、清空功能

先在管理类中添加清空文件的接口函数destroyRecord();

然后在源文件中实现

void Manager:: destoryRecord()
{
	cout << "是否确认清空?" << endl;
	cout << "确认:1" << endl;
	cout << "取消:0" << endl;
	cout << "请输入:" << endl;
	int input;
	cin >> input;

	if (input == 1)
	{
		ofstream ofs("Speach.csv", ios::trunc);
		// trunc:如果文件存在,删除并重新创建
		ofs.close();

		// 然后将属性初始化
		this->initSpeaker(); // 初始化
		this->createSpeaker(); // 创建选手
		this->loadSpeach(); // 获取往届记录
		cout << "清空成功!" << endl;
	}
	system("pause");
	system("cls");
}

最后在main函数中调用

 测试:

 

 至此该项目全部完成

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Linux】信号(上)

文章目录 &#x1f4d5; 信号入门生活角度的信号技术角度的信号 &#x1f4d5; 信号产生认识 signal 函数键盘产生信号通过系统调用产生信号软件条件产生信号硬件异常产生信号 &#x1f4d5; 核心转储&#x1f4d5; 信号保存信号集函数 &#x1f4d5; 信号处理用户态与内核态处…

如何通过桥接模式重构代码?

文章目录 什么是桥接模式&#xff1f;UML结构图通用代码实现适用场景案例场景分析⽤⼀坨坨代码实现桥接模式重构代码代码实现⽀付类型桥接抽象类⽀付类型的实现定义⽀付模式接⼝测试 总结 同类的业务、同样的功能&#xff0c;怎么就你能写出来那么多if else。 很多时候你写出来…

【Web服务器】Tomcat的部署

文章目录 前言一、Tomcat 的概念1. Tomcat 核心组件1.1 什么是 servlet1.2 什么是 JSP 2. Tomcat 功能组件结构2.1 Container 结构分析 3. Tomcat 请求过程4. 配置文件4.1 安装目录4.2 conf 子目录 二、Tomcat 服务部署1. 下载并安装 JDK1.1 关闭防火墙&#xff0c;将安装 Tomc…

Milvus Lite 已交卷!轻量版 Milvus,主打就是一个轻便、无负担

想要体验世界上最快的向量数据库&#xff1f;缺少专业的工程师团队作为支撑&#xff1f;Milvus 安装环境受限&#xff1f; 别担心&#xff0c;轻量版 Milvus 来啦&#xff01; 在正式介绍 Milvus Lite 之前&#xff0c;先简单回顾一下 Milvus。Milvus 是一款开源的向量数据库&a…

logstash启动时默认连接本机节点elasticsearch问题

背景 今天在排查处理一个logstash读取kafka数据写入到hdfs的问题时候&#xff0c;发现在启动日志中多了个 logstash.outputs.elasticsearch 连接的地址是localhost:9200 部分日志如下&#xff1a; 排查过程说明 1、首先确认 logstash 启动的配置文件中的 output 配置&#x…

SonarQube Data Center Edition 10.0 Crack

使用{SonarQube}为团队和企业提供干净的代码 SonarQube Data Center Edition为开发团队提供深度集成到企业环境中的代码质量和安全解决方案;使您能够一致且可靠地部署干净的代码。 灵活性和治理&#xff1a;完美的企业代码质量工具 与您的企业环境深度集成 自我管理&#xff0…

【软件测试】软件测试的基本概念和开发模型

1. 前言 在进行软件测试的学习之前,我们要了解软件测试一些基本概念. 这些基本概念将帮助我们更加明确工作的目标以及软件测试到底要做什么. 2. 软件测试的基本概念 软件测试的基本概念有3个,分别是需求,测试用例和BUG. 2.1 需求 这里的需求还可以分为 用户需求和软件需求,用户…

【博客646】将消息队列放在Prometheus前以提高可靠性并不总是“好主意“

将队列放在Prometheus前以提高可靠性并不总是"好主意" 为了防止突发流量&#xff0c;而在prometheus前加上消息队列以达到削峰填谷的目的 架构如下&#xff1a; 应用程序将指标推送到某种形式的队列&#xff08;通常是 Kafka&#xff09;&#xff0c;暴露器二进制…

超详细IDEA创建Maven项目

文章目录 一、Maven概述二、创建Maven项目三、Maven项目简单介绍3.1 标准化的项目结构3.2 标准化的构建流程3.3 方便的依赖管理 一、Maven概述 Maven是一个专门用于管理和构建Java项目的工具。我们之所以要使用Maven&#xff0c;是因为Maven可以为我们提供一套标准化的项目结构…

Python单元测试框架《python 自动化框架 pytest》

​ 编辑切换为居中 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; Pytest 简介 pytest 是python 的一种单元测试框架&#xff0c;不python 自带的unittest 测试框架类似&#xff0c;但是比 unittest 框架使用起来更简洁&#xff0c;效率更高。根据pyt…

智警杯半决赛知识点

hive&#xff1a; 启动hadoop 启动本地连接&#xff0c;连接外网 主机就是外网IP 1.修改云主机host文件&#xff0c;添加内网ip&#xff0c;对应映射名为hadoop000&#xff0c;实现云主机自身使用root用户ssh访问hadoop000免密登录 改host文件 vim/etc/hosts 比赛时会提…

【论文阅读】(2023.05.10-2023.06.03)论文阅读简单记录和汇总

(2023.05.10-2023.06.08)论文阅读简单记录和汇总 2023/05/10&#xff1a;今天状态&#xff0c;复阳大残&#xff0c;下午淋了点雨吹了点风&#xff0c;直接躺了四个小时还是头晕- -应该是阳了没跑了。 2023/06/03&#xff1a;前两周出差复阳&#xff0c;这两周调整作息把自己又…

第十三届蓝桥杯c++b组国赛题解(还在持续更新中...)

第十三届蓝桥杯Cb组国赛真题pdf自取 试题A&#xff1a;2022 解题思路&#xff1a; 有2022个物品&#xff0c;它们的编号分别是1到2022&#xff0c;它们的价值分别等于它们的编号。也就是说&#xff0c;有2022种物品&#xff0c;物品价值等于物品编号。 从2022个物品种选取10个…

虹科案例 | 虹科Dimetix激光测距传感器可实现无接触式监测采矿设备健康状况!

Part.01 行业挑战 采矿业机器的环境条件通常非常恶劣&#xff0c;损坏的设备会导致生产力和利润下降。虹科虹科Dimetix激光测距传感器为采矿设备和危险区域机器的机器健康监测提供了非接触式解决方案。 采矿操作中的处理设备通常包括分离、混合和粉碎矿石的机械设备。许多重型…

客户线上反馈:从信息搜集到疑难 bug 排查全流程经验分享

写在前面&#xff1a;本文是我在前端团队的第三次分享&#xff0c;应该很少会有开发者写客户反馈处理流程以及 bug 排查的心得技巧&#xff0c;全文比较长&#xff0c;写了一个多星期大概1W多字&#xff08;也是我曾经2年工作的总结&#xff09;&#xff0c;如果你有耐心阅读&a…

因数据库字段可存储长度设置的小了,已达到设置字符类型的存储上限,导致数据存储时报错 及 常用的数据类型

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 使用MySQL数据库&#xff0c;因数据库字段可存储长度设置的小了&#xff0c;已达到设置字符类型的存储上限&#xff0c;导致数据存储时报错 问题描述 提示&#xff1a;这里描述项目中遇到的问题&am…

2天刷完这套八股文,offer到手啦?

前言 大家好&#xff0c;最近有不少小伙伴在后台留言&#xff0c;得准备面试了&#xff0c;又不知道从何下手&#xff01;为了帮大家节约时间&#xff0c;特意准备了一份面试相关的资料&#xff0c;内容非常的全面&#xff0c;真的可以好好补一补&#xff0c;希望大家在都能拿…

我的GIT练习Three

目录 前言 GIT安装教程 Git作者 GIT优点 GIT缺点 为什么要使用 Git GIT练习Three 总结 前言 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照&#xff0c;以此来对整个项目进行版本管理 GIT安装教程 点击进入查看教程&#xff1a;点击进入 G…

(深入浅出)详解虚拟内存

概述 我们都知道一个进程是与其他进程共享CPU和内存资源的。正因如此&#xff0c;操作系统需要有一套完善的内存管理机制才能防止进程之间内存泄漏的问题。 为了更加有效地管理内存并减少出错&#xff0c;现代操作系统提供了一种对主存的抽象概念&#xff0c;即是虚拟内存&am…

从未尝试过的 7 种处理 CSS 的方法

啊&#xff0c;Web 开发的世界——您可以从学习 HTML、JavaScript&#xff0c;当然还有 CSS 等基础知识开始。 但是一旦你在现实世界中构建应用程序&#xff0c;纯 CSS 就不再适用了。 挣扎是真的。 因此&#xff0c;今天我们将深入探讨使用 NextJS 为 React 应用程序编写 CSS…