c++的string一键介绍

 

前言:

这篇文章旨在帮助读者回忆如何使用string,并提醒注意事项。它不是一篇详细的功能介绍,而是一篇润色文章。

先展示重载函数,如果该函数一笔不可带过,就先展示英文原档(附带翻译),最后展示代码实现与举例

这里先提供c++官网相关链接:cplusplus.com/reference/string/

可以直接去看英文文档,也可以看本篇文章,但是更建议去看英文原档。

那么废话少说直接开始进行挨个介绍

Member functions:

1:std::basic_string::basic_string构造函数

进行初始化,c++的官方给了很多的初始化重载函数,也完美应对了我们不同的要求,看来c++祖师爷还是很细心的。 


 

下面举一个例子,使用每一个初始化方式 

#include<string>
#include<iostream>
using namespace std;

int main()
{
	string s0("Initial string");

	// constructors used in the same order as described above:
	string s1;
	string s2(s0);
	string s3(s0, 8, 3);
	string s4("A character sequence", 6);
	string s5("Another character sequence");
	string s6(10, 'x');
	string s7a(10, 42);
    string s7b(s0.begin(), s0.begin() + 7);

	cout << "s1: " << s1 << "\ns2: " << s2 << "\ns3: " << s3;
	cout << "\ns4: " << s4 << "\ns5: " << s5 << "\ns6: " << s6;
	cout << "\ns7a: " << s7a << "\ns7b: " << s7b << '\n';
	return 0;
}

运行结果展示:

 2:std::basic_string::~basic_string析构函数

 析构函数官方没有给详细解释,应该走的是默认析构

那么这里展示我写的析构函数:

class string
{
public:
	~string()
	{
		delete[]_str;
		_str = nullptr;
		_size = _capacity = 0;
	}
private:
	char* _str;
	size_t _size;
	size_t _capacity;
	const static size_t npos = -1;//可以先忽略
};

 3:std::basic_string::operator=运算符=

官方给出了三个重载

第一个就是将string类型赋值给string类型

第二个是将字符串赋值给string类型

第三个是单个字符赋值给string类型

需要注意的是自己实现的时候要进行深拷贝,而不是浅拷贝

string& operator= (const string& str)
{
	if (this != &str)
	{
		char* tmp= new char[str._capacity + 1];
		strcpy(tmp, str._str);
		delete[] _str;
		_str = tmp;
		_size = str._size;
		_capacity = str._capacity;
	}
}

也可以借助swap函数进行优化:

	string& operator=(string tmp)
	{
		swap(tmp);
		return *this;
	}

Iterators:

1:begin

 

iterator begin();

const_iterator begin() const;

官方解释就是Returns an iterator pointing to the first character of the string.

也就是返回一个指向第一个字符的string迭代器

反之对应的就是end,最后一个

2:end

 

iterator end();

const_iterator end() const;

 需要注意的是返回的是最后一个元素的下一个,不是最后一个,

就比如说如果string里面存的是 abcdef  那么end返回的是指向f下一个位置的迭代器。

注意点:

If the object is an empty string, this function returns the same as basic_string::begin.

如果对象为空字符串,则此函数返回与 basic_string::begin 相同的值。

这一点也就解决了如果string为空的情况

3:rbegin与rend 

reverse_iterator rbegin();
const_reverse_iterator rbegin() const;

reverse_iterator rend();
const_reverse_iterator rend() const;

 两个是对应的begin与end其中r为reverse逆置的意思

返回的都是字符串反向端的反向迭代器。

举例:

#include<string>
#include<iostream>
using namespace std;
int main()
{
	string str("now step live...");
	string::reverse_iterator it = str.rbegin();
	while (it != str.rend())
	{
		cout << *it;
		++it;
	}
	cout << endl;
	return 0;
}

打印效果:

4: cbegin与cend

const_iterator cbegin() const noexcept;

const_iterator cend() const noexcept;

 分别是Return const_iterator to begin  回到const_iterator开始

Return const_iterator to end                返回const_iterator到结束

 5:同样有crbegin与crend

const_reverse_iterator crbegin() const noexcept;

const_reverse_iterator crend() const noexcept;

 Capacity

1:size

size_type size() const;

 

返回string的大小

这个还是很好理解的,直接展示代码的自己实现

        size_t size() const
        {
            return _size;
        } 

2:length

这个函数跟size()其实没什么区别,而且用的很少,他出现的原因就是因为string是早期的c++产物,当时c++还不成熟,就造出了他,到后面也不能删除导致的。

3:max_size

size_type max_size() const;

 

这个就是返回string中size最大是多大

4:resize 

void resize (size_type n);
void resize (size_type n, charT c);

这个函数就是修改size的值,意在修改string的大小

 在函数也对应了两种特殊情况;第1种便是n的值比原来的size大,还有1种是比原来的小;

那么我们看看原档对于此的解决

If n is smaller than the current string length, the current value is shortened to its first n character, removing the characters beyond the nth.
如果 n 小于当前字符串长度,则当前值将缩短为其第一个 n 字符,从而删除第 n 个字符之外的字符。

If n is greater than the current string length, the current content is extended by inserting at the end as many characters as needed to reach a size of n. If c is specified, the new elements are initialized as copies of c, otherwise, they are value-initialized characters (null characters).
如果 n 大于当前字符串长度,则通过在末尾插入所需数量的字符来扩展当前内容,以达到 n 的大小。如果指定了 c,则新元素将初始化为 c 的副本,否则,它们是值初始化的字符(空字符)。

那么展示代码的实现:

		void resize(size_t n, char ch = '\0') 
		{
			if (n > _size)
			{

				reserve(n);//修改capacity大小为n后面回介绍

				for (size_t i = _size; i < n; i++)
				{
					_str[i] = ch;
				}
				_str[n] = '\0';
				_size = n;
			}
			else 
			{
				_str[n] = '\0';
				_size = n;
			}
		}

5:capacity

size_type capacity() const;

 该函数与size差不多,但这个还是是返回capacity的大小

       size_type capacity() const;
        {
            return _capacity;
        } 

6:reserve

void reserve (size_type n = 0);

 该函数是在修改capacity的大小,但是它只能放大不可以缩小。主要是因为如果缩小的话,代价太过于大,而且会产生很多不必要的麻烦。所以该函数只支持放大容量不可以缩小。

代码实现也有很多小细节:主要是末尾的'\0';

		void reserve(size_t n = 0)
		{
			if (n > _capacity)
			{
				char* tmp = new char[n + 1];//第n+1个位置存的是'/0'
				strcpy(tmp, _str);
				delete[] _str;
				_str = tmp;
				_capacity = n;
			}
		}

7:clear

void clear();

该函数也是人如其名,进行了清理clear,所以函数的实现还是比较好理解的。这里不再进行多说那么这些进行代码展示

Erases the contents of the basic_string, which becomes an empty string (with a length of 0 characters).
擦除basic_string的内容,该内容将变为空字符串( 0 字符长度)。

		void clear()
		{
			_str[0] = '\0';
			_size = 0;
		}

 8:empty

bool empty() const;

Returns whether the basic_string is empty (i.e. whether its length is 0).

这句话的详细意思就是如果该对象为空就返回1(true)如果对象不为空就返回零(false);

		bool empty() const
		{
			return _size == 0;
		}

9:shrink_to_fit

void shrink_to_fit();

 这个函数官方的介绍还有比较少的,但是实际上实现起来还是比较麻烦的。

它的作用主要是修改修改capacity大小,使其正好达到满的效果,也就是第capacity的位置就为第size的值。

其实该函数的实现不单单是调用了reserve

因为如果原本的capacity很大很大,但是我们又删了很多,那么这时候在shrink_to_fit,就会很浪费空间,原码是这样实现的,会先拷贝,后修改,不是单单的reserve

 最后展示一下官方举例

Element access: 元素访问

1: operator[]

reference operator[] (size_type pos);

const_reference operator[] (size_type pos) const;

 实现起来还是比较简单的这里就不在说了。

		char& operator[] (size_t pos)
		{
			assert(pos < _size);
			return _str[pos];
		}
		const char& operator[] (size_t pos) const
		{
			assert(pos < _size);
			return _str[pos];
		}

2:at

reference at (size_type pos);

const_reference at (size_type pos) const;

at与operator[]效果完全差不多,但是有一点不同的是operator在出错时会掏出他的七匹狼给你直接报告,但是at出错时只是会警告,所以at使用的很少 

3:back与front

charT& back();const charT& back() const;

charT& front();const charT& front() const;

 返回第一个与最后一个

Modifiers: 修饰 符

1:operator+=

 

string (1)

basic_string& operator+= (const basic_string& str);

c-string (2)

basic_string& operator+= (const charT* s);

character (3)

basic_string& operator+= (charT c);

这个重载运算符那就不需要多的介绍了吧,我们已经很详细了,就是+= 

string& operator+=(const char* str)
{
	append(str);
	return *this;
}
string& operator+=(char ch)
{
	push_back(ch);
	return *this;
}

2:append

string (1)

basic_string& append (const basic_string& str);

substring (2)

basic_string& append (const basic_string& str, size_type subpos, size_type sublen);

c-string (3)

basic_string& append (const charT* s);

buffer (4)

basic_string& append (const charT* s, size_type n);

fill (5)

basic_string& append (size_type n, charT c);

range (6)

template <class InputIterator>   basic_string& append (InputIterator first, InputIterator last);

initializer list(7)

basic_string& append (initializer_list<charT> il);

可以看到C++祖师爷写了很多它的重载,也完美了应对了我们的所有要求。而且这还是C++11如果C++14的话那么就会更多.那么这里就介绍几个我们经常用到的。

函数的作用

向后添加想要对象,俗话说时延长

代码实现 :

string& append(size_t n, char c)
{
	if (_size + n > _capacity)
	{
		reserve(_size + n);
	}
	size_t begin = _size;
	_size += n;
	for (size_t i = begin; i < _size; i++)
	{
		_str[i] = c;
	}
	return *this;
}
void append(const char* str)
{
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	strcpy(_str + _size, str);
	_size += len;
}
string& append(const string& str)
{
	append(str._str);
	return *this;
}

3:push_back与pop_back

void push_back (charT c);

void pop_back();

向后添加,与后删,这个就没有好多说的。

4:assign

string (1)

basic_string& assign (const basic_string& str);

substring (2)

basic_string& assign (const basic_string& str, size_type subpos, size_type sublen);

c-string (3)

basic_string& assign (const charT* s);

buffer (4)

basic_string& assign (const charT* s, size_type n);

fill (5)

basic_string& assign (size_type n, charT c);

range (6)

template <class InputIterator>   basic_string& assign (InputIterator first, InputIterator last);

initializer list(7)

basic_string& assign (initializer_list<charT> il);

move (8)

basic_string& assign (basic_string&& str) noexcept;

 

Assign content to string
将内容分配给字符串

Assigns a new value to the string, replacing its current contents.
为字符串分配一个新值,替换其当前内容。

(1) string (1) 字符串

Copies str. 副本 str.

(2) substring (2) 子字符串

Copies the portion of str that begins at the character position subpos and spans sublen characters (or until the end of str, if either str is too short or if sublen is basic_string::npos).
复制从字符位置 subpos 开始并跨越 sublen 字符的 str 部分(如果任一 str 太短或 sublen 为 basic_string::npos,则复制到 str 的末尾)。

(3) c-string (3) C-串

Copies the null-terminated character sequence (C-string) pointed by s.

复制以 s 为结尾的以 null 结尾的字符序列(C 字符串)。


The length is determined by calling traits_type::length(s).
长度由调用 traits_type::length(s) 确定。

(4) buffer (4) 缓冲器

Copies the first n characters from the array of characters pointed by s.
从 s 指向的字符数组中复制前 n 个字符。

(5) fill (5)填写

Replaces the current value by n consecutive copies of character c.
将当前值替换为字符 c 的 n 个连续副本。

(6) range (6) 范围

Copies the sequence of characters in the range [first,last), in the same order.
以相同的顺序复制 范围 [first,last) 中的字符序列。

(7) initializer list (7) 初始值设定项列表

Copies each of the characters in il, in the same order.
以相同的顺序复制 il 中的每个字符。

(8) move (8) 移动

Acquires the contents of str.
获取 str 的内容。
str is left in an unspecified but valid state.
str 保持未指定但有效的状态。

简单举例演示

#include<string>
#include<iostream>
using namespace std;
int main()
{
	string str("now step live...");
	string s;
	s.assign(str);
	auto it = s.begin();
	while (it != s.end())
	{
		cout << *it;
		++it;
	}
	cout << endl;
	return 0;
}

 运行效果:

 5:insert

string (1)

basic_string& insert (size_type pos, const basic_string& str);

substring (2)

basic_string& insert (size_type pos, const basic_string& str,                      size_type subpos, size_type sublen);

c-string (3)

basic_string& insert (size_type pos, const charT* s);

buffer (4)

basic_string& insert (size_type pos, const charT* s, size_type n);

fill (5)

basic_string& insert (size_type pos,   size_type n, charT c);     iterator insert (const_iterator p, size_type n, charT c);

single character (6)

     iterator insert (const_iterator p, charT c);

range (7)

template <class InputIterator>     iterator insert (iterator p, InputIterator first, InputIterator last);

initializer list (8)

basic_string& insert (const_iterator p, initializer_list<charT> il);

同样c++给了很多重载,insert就是在pos的前面插入 

代码实现:

string& insert(size_t pos, char ch)
{
	assert(pos <  _size);
	if (_size == _capacity)
	{
		reserve(_capacity == 0 ? 4 : _capacity * 2);
	}
	size_t end = _size + 1;
	while (end > pos)
	{
		_str[end] = _str[end - 1];
		--end;
	}
	_str[pos] = ch;
	_size++;
	return *this;
}
string& insert(size_t pos, const char* str)
{
	assert(pos < _size);
	size_t len = strlen(str);
	if (_size + len > _capacity)
	{
		reserve(_size + len);
	}
	size_t end1 = _size + 1;
	size_t end2 = _size + len + 1;
	while (end1 > pos)
	{
		_str[end2 - 1] = _str[end1 - 1];
		end2--;
		end1--;
	}
	_str[_size + len] = '\0';
	strncpy(_str + pos, str, len);
	_size+=len;
	return *this;
}

6:erase

sequence (1)

basic_string& erase (size_type pos = 0, size_type len = npos);

character (2)

     iterator erase (const_iterator p);

range (3)

     iterator erase (const_iterator first, const_iterator last);

 

需要注意的是这里的len是删除的个数,而npos是-1; 

返回值就是删除后指向的位置(为了使其迭代器不失效)

 7:replace

就是代替,这个用的不是很多,就不想insert与erase那样全部展示了,就举个简单的例子吧

 

#include<string>
#include<iostream>
using namespace std;
int main()
{
	string str("now step live...");
	string s1("pqpq2");
	str.replace(2, 2, s1);//把str从第二个开始把两个字符,替换为s1,
	auto it = str.begin();
	while (it != str.end())
	{
		cout << *it;
		++it;
	}
	cout << endl;
	return 0;
}

效果打印演示:

通常可以与find一同使用,统一替换某个特殊字符转化为想要的结果。 

8:c_str

获取 C 字符串等效值

通常可以应用输出流

代码实现

        const char* c_str() const
        {
            return _str;
        }

9:copy

这个就是复制拷贝,很好理解 

同样第一个参数就是要拷贝的对象,第二个是要拷贝的个数,第三个参数就是被拷贝的对象第一个拷贝的位置。

举例: 

 10:find

string (1)

size_type find (const basic_string& str, size_type pos = 0) const noexcept;

c-string (2)

size_type find (const charT* s, size_type pos = 0) const;

buffer (3)

size_type find (const charT* s, size_type pos, size_type n) const;

character (4)

size_type find (charT c, size_type pos = 0) const noexcept;

 

代码实现:

		size_t find(char ch, size_t pos = 0)
		{
			for (size_t i = pos; i < _size; i++)
			{
				if (_str[i] == ch)
				{
					return i;
				}
			}
			return npos;
		}

简单的运用举例:

#include<string>
#include<iostream>
using namespace std;
void test()
{
	string s3("https://legacy.cplusplus.com/reference/string/string/rfind/");
	// 协议
	// 域名
	// 资源名

	string sub1, sub2, sub3;
	size_t i1 = s3.find(':');
	if (i1 != -1)
		sub1 = s3.substr(0, i1);//可以理解为赋值从第0到第i1个
	else
		cout << "没有找到i1" << endl;

	size_t i2 = s3.find('/', i1 + 3);
	if (i2 != -1)
		sub2 = s3.substr(i1 + 3, i2 - (i1 + 3));
	else
		cout << "没有找到i2" << endl;

	sub3 = s3.substr(i2 + 1);

	cout << sub1 << endl;
	cout << sub2 << endl;
	cout << sub3 << endl;
}
int main()
{
	test();
	return 0;
}

 运行展示:

 11:substr

asic_string substr (size_type pos = 0, size_type len = npos) const;

该函数就是生成其子字符串

代码实现 :

		string substr(size_t pos, size_t len = npos)
		{
			string s;
			size_t end = pos + len;
			if (len == npos || pos + len >= _size) // 有多少取多少
			{
				len = _size - pos;
				end = _size;
			}
			s.reserve(len);
			for (size_t i = pos; i < end; i++)
			{
				s += _str[i];
			}
			return s;
		}



 

那么到这里这篇文章就结束了,本篇文章不是详细介绍,而是帮助回忆!!!

 看到这了就给自己点个赞把

 

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

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

相关文章

基于语音信号MFCC特征提取和GRNN神经网络的人员身份检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 MFCC特征提取 4.2 GRNN神经网络概述 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022a 3.部分核心程序 ...............................................…

Django序列化器中is_valid和validate

今天上班的时候分配了一个任务&#xff0c;是修复前端的一个提示优化&#xff0c;如下图所示&#xff1a; 按照以往的经验我以为可以直接在validate上进行校验&#xff0c;如何抛出一个异常即可 &#xff0c;例如&#xff1a; class CcmSerializer(serializers.ModelSerialize…

HALCON-从入门到入门-软件界面介绍

1.废话 从halcon12到halcon23&#xff0c;开发的IDE界面大差不差&#xff0c;简单说下界面上不同功能按键的分布&#xff0c;以及一些快捷键啥的&#xff0c;要是还有我没有总结到的&#xff0c;又比较好用的&#xff0c;欢迎大家补充一下。 1.菜单栏 从上看到下&#xff0c;…

大型医疗器械企业四套系统数据集成技术干货分享

在大型医疗企业中&#xff0c;数据的互联互通是提升运营效率和数据利用率的关键。本次分享将概述如何通过轻易云集成平台将金蝶ERP、ZOHO CRM、泛微OA和汇联易报销系统进行高效联动&#xff0c;展示在实施过程中积累的技术干货。 某大型医疗企业&#xff0c;专注于麻醉和呼吸医…

系统架构设计师 - 操作系统(1)

操作系统 操作系统&#xff08;5-6分&#xff09;操作系统概述进程管理进程和线程的基本概念进程的状态 ★前趋图 ★★★★信号量与 PV 操作 ★★★★死锁及银行家算法 ★ 大家好呀&#xff01;我是小笙&#xff0c;本章我主要分享系统架构设计师 - 操作系统(1)知识&#xff0c…

B站如何屏蔽短视频:成都鼎茂宏升文化传媒公司

B站如何屏蔽短视频&#xff1a;优化你的观看体验 在当今数字化时代&#xff0c;B站&#xff08;哔哩哔哩&#xff09;作为国内领先的弹幕视频网站&#xff0c;以其丰富的视频资源和独特的弹幕文化吸引了大量用户。然而&#xff0c;随着短视频的兴起&#xff0c;B站也引入了短视…

智能学工系统实现学生管理

人才培养是高校的榜首要务&#xff0c;高校在抓好学生教育作业的一起&#xff0c;更多的是要加强对学生的办理作业。作为在校大学生健康成长的指导者和引路人&#xff0c;面临很多的学生办理作业内容杂乱&#xff0c;事无巨细&#xff0c;但在传统的办理方式下&#xff0c;尽管…

在 LLM 架构中应用多专家模型

本文转载自&#xff1a;在 LLM 架构中应用多专家模型 2024年 3月 14日 By Kyle Kranen and Vinh Nguyen https://developer.nvidia.cn/zh-cn/blog/applying-mixture-of-experts-in-llm-architectures/ 文章目录 一、概述二、LLM 架构领域的专家齐聚一堂1、模型容量2、MoE 在降低…

计算机系统结构之Cache

一、全相联映像和变换 全相联映像的主存-Cache地址变换过程如图&#xff1a; 给出主存地址Nm访存时&#xff0c;将其主存块号Nmb与目录表(硬件)中所有各项的Mmb字段同时相联比较。若有相同的&#xff0c;就将对应行的Cache块号Ncb取出&#xff0c;拼接上块内地址Nmr形成Cache地…

JAVA基础|多线程

什么是线程&#xff1f; 线程&#xff08;Thread&#xff09;是一个程序内部的一条执行流程。 多线程是什么&#xff1f; 多线程是指从软硬件上实现的多条执行流程的技术&#xff08;多条线程由CPU负责调度执行&#xff09; 一. 如何在程序中创建出多条线程&#xff1f; Ja…

社交媒体数据恢复:Voxer

一、Voxer数据恢复教程 了解Voxer应用 Voxer是一款专门为iPhone和Android智能手机设计的免费对讲机应用&#xff0c;为用户提供即时的语音、文本、照片等信息发送和接收服务。该应用有点类似短信服务&#xff0c;但用声音代替文本。当你下载之后&#xff0c;如果不邀请朋友&a…

XTuner 微调个人小助手认知实战

XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。GitHub - InternLM/xtuner: An efficient, flexible and full-featured toolkit for fine-tuning LLM (InternLM2, Llama3, Phi3, Qwen, Mistral, ...)An efficient, flexible and full-featured toolkit for fine-tun…

vue中使用svg图像

一 、svg图像是什么 SVG&#xff08;可缩放矢量图形&#xff09;是一种图像格式&#xff0c;它以XML文档的形式存在&#xff0c;用以描述图像中的形状、线条、文本和颜色等元素。由于其基于矢量的特性&#xff0c;SVG图像在放大或改变尺寸时能够保持图形质量不受影响。这种格式…

【深入学习Redis丨第二篇】Redis集群部署详解

文章目录 Redis集群部署Redis4 Cluster部署 Redis集群部署 1 Redis各节点部署 使用源码安装各节点&#xff0c;不过与非cluster方式不同的是&#xff0c;配置文件中需启动cluster相关的配置。 因本次为伪分布式部署&#xff0c;生产环境部署时建议至少3台机器部署&#xff0…

解决JSON.stringify 方法在序列化 BigInt 类型时的错误

今天学nest时&#xff0c;使用apifox发送请求获取数据&#xff0c;结果还一直报错&#xff0c;而且还是我从未见过的 Do not know how to serialize a BigInt at JSON.stringify (<anonymous>) at stringify&#xff0c; 我都是跟着人家敲的&#xff0c;我就纳闷了&…

Java——异常详解

异常五个主要关键字&#xff1a;throw、try、catch、finally、throws 1. 异常的概念与体系结构 1.1 异常的概念 在Java中&#xff0c;程序执行过程中发生的不正常行为被称为异常&#xff0c;如&#xff1a; 1. 算数异常 public static void main(String[] args) {System.ou…

数据结构队列(深入链表的应用)

目录 队列的概念及结构 队列的实现 结构的选择 从Pop来看&#xff1a; 队列的结构 &#xff1a; 分析&#xff1a; 头文件(queue.h) 实现队列功能&#xff1a; 队列的初始化(与链表类似) 队列的摧毁 队列的插入(链表尾插) 队头的删除 取队头队尾的数据(简单中藏陷阱…

Vue3中的常见组件通信之props和自定义事件

Vue3中的常见组件通信 概述 ​ 在vue3中常见的组件通信有props、mitt、v-model、 r e f s 、 refs、 refs、parent、provide、inject、pinia、slot等。不同的组件关系用不同的传递方式。常见的撘配形式如下表所示。 组件关系传递方式父传子1. props2. v-model3. $refs4. 默认…

【TB作品】MSP430F5529,单片机,打地鼠游戏

功能 针对这块开发板做了一个打地鼠游戏&#xff1a; 1 给单片机上电后&#xff0c;初始化显示界面&#xff0c;显示出分数和等级。 2 游戏是一轮一轮进行的&#xff0c;每一轮会以50%几率点亮板子上的五个小灯&#xff0c;表示地鼠露头需要打了。 3 一轮游戏开始后&#xff…

STM32作业设计

目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…